@lapxo/obligations 0.4.1 → 0.4.2

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.
@@ -18,6 +18,7 @@ export function restOf(c, world = new Map()) {
18
18
  const out = [];
19
19
  const held = new Set();
20
20
  const edge = [...c.restsOn];
21
+ const above = new Map();
21
22
  for (let i = 0; i < edge.length; i += 1) {
22
23
  const name = edge[i];
23
24
  if (name === own)
@@ -26,7 +27,34 @@ export function restOf(c, world = new Map()) {
26
27
  continue;
27
28
  held.add(name);
28
29
  out.push(name);
29
- edge.push(...(world.get(name)?.restsOn ?? []));
30
+ const rests = world.get(name)?.restsOn ?? [];
31
+ above.set(name, rests);
32
+ for (const ancestor of rests)
33
+ edge.push(ancestor);
34
+ }
35
+ const status = new Map();
36
+ for (const name of out) {
37
+ if (status.has(name))
38
+ continue;
39
+ status.set(name, 'visiting');
40
+ const path = [{ name, next: 0 }];
41
+ while (path.length) {
42
+ const head = path[path.length - 1];
43
+ const rests = above.get(head.name);
44
+ if (head.next === rests.length) {
45
+ status.set(head.name, 'done');
46
+ path.pop();
47
+ continue;
48
+ }
49
+ const ancestor = rests[head.next++];
50
+ const seen = status.get(ancestor);
51
+ if (seen === 'visiting')
52
+ throw new UnitError('rest-cycle', `obligations: REFUSE·rest ${own} reaches a cycle at ${ancestor}: an order of rest with a cycle has no fold to reach`, { at: own });
53
+ if (seen === undefined) {
54
+ status.set(ancestor, 'visiting');
55
+ path.push({ name: ancestor, next: 0 });
56
+ }
57
+ }
30
58
  }
31
59
  return out;
32
60
  }
@@ -28,6 +28,28 @@ export declare function capacityBound(n: number, c: RationalInput, policy: Logar
28
28
  value: number;
29
29
  meaning: "upper bound for every k; achievability depends on the private channel";
30
30
  };
31
+ export declare function commonCauseCapacityBound(n: number, c: RationalInput, accuracy: RationalInput, policy: LogarithmPolicy): {
32
+ model: "single-covering-symmetric-cause@1";
33
+ parameters: {
34
+ n: number;
35
+ c: Readonly<{
36
+ numerator: string;
37
+ denominator: string;
38
+ }>;
39
+ q: Readonly<{
40
+ numerator: string;
41
+ denominator: string;
42
+ }>;
43
+ };
44
+ policy: Readonly<{
45
+ logarithm: "binary64-log2";
46
+ }>;
47
+ status: "measured";
48
+ unit: "bits";
49
+ conditions: readonly ["uniform-truth", "cause-indicator-independent-of-truth", "active-cause-copies-one-symmetric-channel", "inactive-private-channel-unrestricted"];
50
+ value: number;
51
+ meaning: "upper bound after revealing cause indicator; copies do not add; no achievability claim";
52
+ };
31
53
  export declare function capacityP0(n: number, c: RationalInput, policy: LogarithmPolicy): {
32
54
  value: number;
33
55
  meaning: "mutual information at p=0 for every positive k";
@@ -29,6 +29,22 @@ export function capacityBound(n, c, policy) {
29
29
  status: 'measured', unit: 'bits', value: Math.log2(n) - numeric(factor) * Math.log2(n - 1),
30
30
  meaning: 'upper bound for every k; achievability depends on the private channel' };
31
31
  }
32
+ export function commonCauseCapacityBound(n, c, accuracy, policy) {
33
+ cardinality(n);
34
+ logPolicy(policy);
35
+ if (accuracy === undefined || accuracy === null)
36
+ refuse('common-cause accuracy q required');
37
+ const factor = probability(c), correct = probability(accuracy), wrong = sub(one, correct);
38
+ const uniform = correct[0] * BigInt(n) === correct[1];
39
+ const channel = uniform ? 0 : correct[0] === 0n ? Math.log1p(1 / (n - 1)) / Math.LN2 :
40
+ Math.max(0, Math.log2(n) - entropy([correct, wrong]) - numeric(wrong) * Math.log2(n - 1));
41
+ return { model: 'single-covering-symmetric-cause@1',
42
+ parameters: { n, c: pack(factor), q: pack(correct) }, policy, status: 'measured', unit: 'bits',
43
+ conditions: ['uniform-truth', 'cause-indicator-independent-of-truth',
44
+ 'active-cause-copies-one-symmetric-channel', 'inactive-private-channel-unrestricted'],
45
+ value: numeric(sub(one, factor)) * Math.log2(n) + numeric(factor) * channel,
46
+ meaning: 'upper bound after revealing cause indicator; copies do not add; no achievability claim' };
47
+ }
32
48
  export function capacityP0(n, c, policy) {
33
49
  const bound = capacityBound(n, c, policy), factor = probability(c);
34
50
  return { ...bound, value: bound.value - entropy([factor, sub(one, factor)]), meaning: 'mutual information at p=0 for every positive k' };
@@ -0,0 +1,73 @@
1
+ import { type RationalInput } from './rational.ts';
2
+ export type DeclaredFailure = Readonly<{
3
+ id: string;
4
+ p: RationalInput;
5
+ justification: string;
6
+ }>;
7
+ export declare function unionBoundConfidence(failures: readonly DeclaredFailure[]): {
8
+ model: "declared-failure-union-bound@1";
9
+ status: "conditional-bound";
10
+ unit: "probability";
11
+ conditions: readonly ["common-probability-space", "each-failure-probability-justified"];
12
+ declarations: {
13
+ id: string;
14
+ p: Readonly<{
15
+ numerator: string;
16
+ denominator: string;
17
+ }>;
18
+ justification: string;
19
+ }[];
20
+ failureSum: Readonly<{
21
+ numerator: string;
22
+ denominator: string;
23
+ }>;
24
+ value: Readonly<{
25
+ numerator: string;
26
+ denominator: string;
27
+ }>;
28
+ trivial: boolean;
29
+ meaning: "lower bound for all declared events succeeding; references are not verified";
30
+ };
31
+ export declare function tolerantCountConfidence(failures: readonly DeclaredFailure[], k: number): {
32
+ model: "declared-failure-count-bound@1";
33
+ allowedFailures: number;
34
+ totalDeclarations: number;
35
+ exclusionOrder: string[];
36
+ candidates: {
37
+ excludedCount: number;
38
+ threshold: number;
39
+ remainingFailureSum: Readonly<{
40
+ numerator: string;
41
+ denominator: string;
42
+ }>;
43
+ failureUpperBound: Readonly<{
44
+ numerator: string;
45
+ denominator: string;
46
+ }>;
47
+ }[];
48
+ failureUpperBound: Readonly<{
49
+ numerator: string;
50
+ denominator: string;
51
+ }>;
52
+ value: Readonly<{
53
+ numerator: string;
54
+ denominator: string;
55
+ }>;
56
+ trivial: boolean;
57
+ meaning: "lower bound for at most k declared failures; references are not verified";
58
+ status: "conditional-bound";
59
+ unit: "probability";
60
+ conditions: readonly ["common-probability-space", "each-failure-probability-justified"];
61
+ declarations: {
62
+ id: string;
63
+ p: Readonly<{
64
+ numerator: string;
65
+ denominator: string;
66
+ }>;
67
+ justification: string;
68
+ }[];
69
+ failureSum: Readonly<{
70
+ numerator: string;
71
+ denominator: string;
72
+ }>;
73
+ };
@@ -0,0 +1,52 @@
1
+ import { add, sub, div, q, rational, zero, one, pack, probability } from "./rational.js";
2
+ const refuse = (cause) => { throw new Error('REFUSE·confidence ' + cause); };
3
+ export function unionBoundConfidence(failures) {
4
+ if (!Array.isArray(failures))
5
+ refuse('declared failures required');
6
+ let sum = zero;
7
+ const names = new Set();
8
+ const declarations = Array.from(failures, failure => {
9
+ if (!failure || typeof failure.id !== 'string' || failure.id.trim() === '')
10
+ refuse('failure identity required');
11
+ if (names.has(failure.id))
12
+ refuse('duplicate failure identity');
13
+ names.add(failure.id);
14
+ if (typeof failure.justification !== 'string' || failure.justification.trim() === '')
15
+ refuse('justification reference required');
16
+ if (failure.p === undefined || failure.p === null)
17
+ refuse('declared failure probability required');
18
+ const p = probability(failure.p);
19
+ sum = add(sum, p);
20
+ return { id: failure.id, p: pack(p), justification: failure.justification };
21
+ });
22
+ const trivial = sum[0] >= sum[1];
23
+ return { model: 'declared-failure-union-bound@1', status: 'conditional-bound',
24
+ unit: 'probability', conditions: ['common-probability-space', 'each-failure-probability-justified'],
25
+ declarations, failureSum: pack(sum), value: pack(trivial ? zero : sub(one, sum)), trivial,
26
+ meaning: 'lower bound for all declared events succeeding; references are not verified' };
27
+ }
28
+ export function tolerantCountConfidence(failures, k) {
29
+ const base = unionBoundConfidence(failures), m = base.declarations.length;
30
+ if (!Number.isSafeInteger(k) || k < 0 || k > m)
31
+ refuse('allowed failure count must be an integer in 0..m');
32
+ const ordered = base.declarations.map(entry => ({ entry, p: probability(entry.p) })).sort((a, b) => {
33
+ const difference = a.p[0] * b.p[1] - b.p[0] * a.p[1];
34
+ return difference > 0n ? -1 : difference < 0n ? 1 : 0;
35
+ });
36
+ let remaining = rational(base.failureSum), upper = k === m ? zero : one;
37
+ const candidates = [];
38
+ if (k < m)
39
+ for (let j = 0; j <= k; j++) {
40
+ const threshold = k + 1 - j, ratio = div(remaining, q(BigInt(threshold)));
41
+ const capped = ratio[0] >= ratio[1] ? one : ratio;
42
+ if (capped[0] * upper[1] < upper[0] * capped[1])
43
+ upper = capped;
44
+ candidates.push({ excludedCount: j, threshold, remainingFailureSum: pack(remaining), failureUpperBound: pack(capped) });
45
+ if (j < k)
46
+ remaining = sub(remaining, ordered[j].p);
47
+ }
48
+ return { ...base, model: 'declared-failure-count-bound@1', allowedFailures: k,
49
+ totalDeclarations: m, exclusionOrder: ordered.map(({ entry }) => entry.id), candidates,
50
+ failureUpperBound: pack(upper), value: pack(sub(one, upper)), trivial: upper[0] === upper[1],
51
+ meaning: 'lower bound for at most k declared failures; references are not verified' };
52
+ }
@@ -16,9 +16,11 @@ export { experimentM3 } from './m3-experiment.ts';
16
16
  export type { M3ExperimentPolicy } from './m3-experiment.ts';
17
17
  export { fitM3 } from './fitting.ts';
18
18
  export type { FitStructure, FitPolicy } from './fitting.ts';
19
- export { capacityBound, capacityP0, mutualInformation, unanimityNoFactor, decisionInformation } from './capacity.ts';
19
+ export { commonCauseCapacityBound, capacityBound, capacityP0, mutualInformation, unanimityNoFactor, decisionInformation } from './capacity.ts';
20
20
  export type { CapacityModel, LogarithmPolicy, CapacityPolicy, DecisionRule } from './capacity.ts';
21
21
  export { fitUnanimityModel } from './unanimity-fit.ts';
22
22
  export type { UnanimityCount, UnanimityGroup, UnanimityCurve, UnanimityFitPolicy } from './unanimity-fit.ts';
23
23
  export { coincidenceExcess } from './coincidence.ts';
24
24
  export type { ValueReading, TruthReading, CoincidenceReference, CoincidencePolicy } from './coincidence.ts';
25
+ export { unionBoundConfidence, tolerantCountConfidence } from './confidence.ts';
26
+ export type { DeclaredFailure } from './confidence.ts';
@@ -7,6 +7,7 @@ export { roundHalfEven } from "./rational.js";
7
7
  export { identifyM3 } from "./identification.js";
8
8
  export { experimentM3 } from "./m3-experiment.js";
9
9
  export { fitM3 } from "./fitting.js";
10
- export { capacityBound, capacityP0, mutualInformation, unanimityNoFactor, decisionInformation } from "./capacity.js";
10
+ export { commonCauseCapacityBound, capacityBound, capacityP0, mutualInformation, unanimityNoFactor, decisionInformation } from "./capacity.js";
11
11
  export { fitUnanimityModel } from "./unanimity-fit.js";
12
12
  export { coincidenceExcess } from "./coincidence.js";
13
+ export { unionBoundConfidence, tolerantCountConfidence } from "./confidence.js";
package/docs/measures.md CHANGED
@@ -194,4 +194,20 @@ Helly is a property of a declared geometric family, not a probabilistic independ
194
194
 
195
195
  ## 17. Publication and stability
196
196
 
197
- Every new operation is linked to its contract, yes/no data and native Bound 0.1.7 captures in two places. Validation readers are maintained TypeScript worlds with ordinary modular compilation; no .mjs bundle or private executor ships in this library. Their implementation inventory is retained once by digest. The installed archive must expose the same public exports, preserve the four states, match all published bytes and close native receipts without a private store. Declaring these requirements does not pay them.
197
+ The historical nine publication groups are linked to their contracts, yes/no data and declared Bound 0.1.7 captures in two places. The 0.4.2 operations below require new captures under their selected reader; historical implementation-bound receipts do not cover changed bytes. Validation readers are maintained TypeScript worlds with ordinary modular compilation; no .mjs bundle or private executor ships in this library. Their implementation inventory is retained once by digest. The installed archive must expose the same public exports, preserve the four states, match all published bytes and close native receipts without a private store. Declaring these requirements does not pay them.
198
+
199
+ ## 18. Declared failure bounds
200
+
201
+ `unionBoundConfidence(failures)` requires distinct nonempty IDs, explicit rational probabilities in [0,1], and nonempty justification references. The caller must establish every failure bound in one probability space. References are retained, not verified. The returned lower bound for all events succeeding is max(0,1−Σp_i), with exact rational arithmetic. The empty family gives 1; Σp_i≥1 gives the trivial bound 0. No independence, truth probability, or algebraic state is inferred.
202
+
203
+ `tolerantCountConfidence(failures,k)` requires a safe integer 0≤k≤m. For k<m it bounds failure by min(1,min_{0≤j≤k}(Σ of the m−j smallest p_i)/(k+1−j)); its exact success lower bound is the complement. For k=m success is certain. For m=3,k=1 and all p_i=1/10 the result is 17/20, not an inferred success rate. The distinct subset-intersection guarantee gives the weaker bound 7/10. Three disjoint paired failures among six events, each pair having probability 1/10, refute the former 4/5 claim: success is 7/10.
204
+
205
+ These operations compute conditional probability bounds. They select neither a geometric tolerance nor a consumer policy. Count-tolerant intersection T_k and widened-interval intersection T_eps remain named forms; tolerant-choice remains open.
206
+
207
+ ## 19. Declared covering cause
208
+
209
+ `commonCauseCapacityBound(n,c,q,{logarithm:'binary64-log2'})` requires integer n≥2 and explicit rational c,q in [0,1]. Truth is uniform; the covering-cause indicator is independent of truth; when active, every report copies one symmetric channel with accuracy q. The inactive private channel is unrestricted. Revealing the indicator gives the upper bound log2(n)−c[h(q)+(1−q)log2(n−1)] in approximate bits. Copy count is no input. This is neither finite-sample mutual information nor an achievability claim.
210
+
211
+ At n=4,c=1,q=1/4 the bound is exactly zero; q=0 gives log2(4/3), and q=1 gives two bits. Missing q refuses. The operational declaration or detection of activation remains open in identification.model. Unconditioned coincidence does not identify q.
212
+
213
+ M/3 and M/4 retain their existing definitions. Partial-factor governance proposals do not supply a conditional joint observation and selection law. The information carried by dissent, including a bottom symbol, is open for those unspecified proposals.
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@lapxo/obligations","version":"0.4.1","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","docs/img","docs/paper.md","docs/reference.md","docs/learn/in-phase.md","docs/learn/price.md","docs/learn/signature.md","docs/learn/thermometer.md","docs/learn/withdrawal.md"],"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"}}
1
+ {"name":"@lapxo/obligations","version":"0.4.2","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","docs/img","docs/paper.md","docs/reference.md","docs/learn/in-phase.md","docs/learn/price.md","docs/learn/signature.md","docs/learn/thermometer.md","docs/learn/withdrawal.md"],"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"}}