@lapxo/topos 0.1.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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +213 -0
  3. package/TARGET.bound +567 -0
  4. package/dist/authority/admit.d.ts +2 -0
  5. package/dist/authority/admit.js +5 -0
  6. package/dist/authority/index.d.ts +4 -0
  7. package/dist/authority/index.js +4 -0
  8. package/dist/authority/motion.d.ts +11 -0
  9. package/dist/authority/motion.js +3 -0
  10. package/dist/capsule/asked.d.ts +28 -0
  11. package/dist/capsule/asked.js +9 -0
  12. package/dist/capsule/declaration.d.ts +26 -0
  13. package/dist/capsule/declaration.js +45 -0
  14. package/dist/capsule/index.d.ts +3 -0
  15. package/dist/capsule/index.js +3 -0
  16. package/dist/capsule/shell.d.ts +51 -0
  17. package/dist/capsule/shell.js +64 -0
  18. package/dist/classes/scale.d.ts +16 -0
  19. package/dist/classes/scale.js +1 -0
  20. package/dist/contract/index.d.ts +27 -0
  21. package/dist/contract/index.js +63 -0
  22. package/dist/forms/alphabet.d.ts +3 -0
  23. package/dist/forms/alphabet.js +19 -0
  24. package/dist/forms/budget.d.ts +3 -0
  25. package/dist/forms/budget.js +11 -0
  26. package/dist/forms/distribution.d.ts +3 -0
  27. package/dist/forms/distribution.js +36 -0
  28. package/dist/forms/form.d.ts +31 -0
  29. package/dist/forms/form.js +42 -0
  30. package/dist/forms/index.d.ts +12 -0
  31. package/dist/forms/index.js +11 -0
  32. package/dist/forms/interval.d.ts +3 -0
  33. package/dist/forms/interval.js +11 -0
  34. package/dist/forms/ladder.d.ts +3 -0
  35. package/dist/forms/ladder.js +11 -0
  36. package/dist/forms/lattice.d.ts +3 -0
  37. package/dist/forms/lattice.js +18 -0
  38. package/dist/forms/phase.d.ts +3 -0
  39. package/dist/forms/phase.js +11 -0
  40. package/dist/forms/rank.d.ts +3 -0
  41. package/dist/forms/rank.js +11 -0
  42. package/dist/forms/stretch.d.ts +3 -0
  43. package/dist/forms/stretch.js +11 -0
  44. package/dist/readers/bindings.d.ts +21 -0
  45. package/dist/readers/bindings.js +1 -0
  46. package/dist/readers/define.d.ts +37 -0
  47. package/dist/readers/define.js +59 -0
  48. package/dist/readers/index.d.ts +3 -0
  49. package/dist/readers/index.js +2 -0
  50. package/dist/wire/claim.d.ts +4 -0
  51. package/dist/wire/claim.js +43 -0
  52. package/dist/wire/claimline.d.ts +78 -0
  53. package/dist/wire/claimline.js +339 -0
  54. package/dist/wire/classes.d.ts +17 -0
  55. package/dist/wire/classes.js +39 -0
  56. package/dist/wire/descriptor.d.ts +45 -0
  57. package/dist/wire/descriptor.js +8 -0
  58. package/dist/wire/evidence.d.ts +2 -0
  59. package/dist/wire/evidence.js +2 -0
  60. package/dist/wire/grammar.d.ts +22 -0
  61. package/dist/wire/grammar.js +42 -0
  62. package/dist/wire/index.d.ts +14 -0
  63. package/dist/wire/index.js +11 -0
  64. package/dist/wire/line.d.ts +10 -0
  65. package/dist/wire/line.js +118 -0
  66. package/dist/wire/measures.d.ts +2 -0
  67. package/dist/wire/measures.js +13 -0
  68. package/dist/wire/names.d.ts +8 -0
  69. package/dist/wire/names.js +8 -0
  70. package/dist/wire/outcome.d.ts +18 -0
  71. package/dist/wire/outcome.js +3 -0
  72. package/dist/wire/sig.d.ts +15 -0
  73. package/dist/wire/sig.js +15 -0
  74. package/dist/wire/spec.d.ts +28 -0
  75. package/dist/wire/spec.js +1 -0
  76. package/dist/wire/types.d.ts +73 -0
  77. package/dist/wire/types.js +2 -0
  78. package/dist/wire/values.d.ts +23 -0
  79. package/dist/wire/values.js +80 -0
  80. package/package.json +68 -0
@@ -0,0 +1,18 @@
1
+ import { latticeForm } from '@lapxo/obligations';
2
+ import { levelsOf, paramsOf, refuseForm, wordsAt } from "./form.js";
3
+ /** An order a line names outright: its levels and, for each pair, whether the first lies under the second. */
4
+ function orderOf(params) {
5
+ const levels = wordsAt('lattice', params, 'levels');
6
+ const leq = paramsOf(params)['leq'];
7
+ if (!Array.isArray(leq) || leq.length !== levels.length || leq.some((row) => !Array.isArray(row) || row.length !== levels.length))
8
+ refuseForm('lattice', 'takes leq as a square of truths over its levels');
9
+ return { levels, leq: leq };
10
+ }
11
+ export const latticeOfForm = {
12
+ id: 'lattice',
13
+ lattice: (params) => latticeForm.lattice(orderOf(params)),
14
+ parse: (params, text) => levelsOf('lattice', orderOf(params).levels, text),
15
+ emit: (_params, value) => (value.floor === value.ceiling ? value.floor : `${value.floor}..${value.ceiling}`),
16
+ show: (params, value) => latticeForm.lattice(orderOf(params)).show(value),
17
+ points: (params, seed, n) => latticeForm.points(orderOf(params), seed, n),
18
+ };
@@ -0,0 +1,3 @@
1
+ import type { Interval } from '@lapxo/obligations';
2
+ import type { WireForm } from './form.ts';
3
+ export declare const phaseForm: WireForm<Interval>;
@@ -0,0 +1,11 @@
1
+ import { continuousForm } from '@lapxo/obligations';
2
+ import { bandOf, bandText, numberAt } from "./form.js";
3
+ const span = (params) => ({ lo: numberAt('phase', params, 'lo'), hi: numberAt('phase', params, 'hi') });
4
+ export const phaseForm = {
5
+ id: 'phase',
6
+ lattice: (params) => continuousForm.lattice(span(params)),
7
+ parse: (params, text) => bandOf('phase', span(params), text),
8
+ emit: (_params, value) => bandText(value),
9
+ show: (params, value) => continuousForm.lattice(span(params)).show(value),
10
+ points: (params, seed, n) => continuousForm.points(span(params), seed, n),
11
+ };
@@ -0,0 +1,3 @@
1
+ import type { Interval } from '@lapxo/obligations';
2
+ import type { WireForm } from './form.ts';
3
+ export declare const rankForm: WireForm<Interval>;
@@ -0,0 +1,11 @@
1
+ import { continuousForm } from '@lapxo/obligations';
2
+ import { bandOf, bandText, numberAt } from "./form.js";
3
+ const span = (params) => ({ lo: 0, hi: numberAt('rank', params, 'n') });
4
+ export const rankForm = {
5
+ id: 'rank',
6
+ lattice: (params) => continuousForm.lattice(span(params)),
7
+ parse: (params, text) => bandOf('rank', span(params), text),
8
+ emit: (_params, value) => bandText(value),
9
+ show: (params, value) => continuousForm.lattice(span(params)).show(value),
10
+ points: (params, seed, n) => continuousForm.points(span(params), seed, n),
11
+ };
@@ -0,0 +1,3 @@
1
+ import type { Interval } from '@lapxo/obligations';
2
+ import type { WireForm } from './form.ts';
3
+ export declare const stretchForm: WireForm<Interval>;
@@ -0,0 +1,11 @@
1
+ import { continuousForm } from '@lapxo/obligations';
2
+ import { bandOf, bandText, numberAt } from "./form.js";
3
+ const span = (params) => ({ lo: numberAt('stretch', params, 'lo'), hi: numberAt('stretch', params, 'hi') });
4
+ export const stretchForm = {
5
+ id: 'stretch',
6
+ lattice: (params) => continuousForm.lattice(span(params)),
7
+ parse: (params, text) => bandOf('stretch', span(params), text),
8
+ emit: (_params, value) => bandText(value),
9
+ show: (params, value) => continuousForm.lattice(span(params)).show(value),
10
+ points: (params, seed, n) => continuousForm.points(span(params), seed, n),
11
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Local, non-serialisable bindings. The descriptor travels; these stay here.
3
+ */
4
+ import type { Claim, Outcome } from '../wire/types.ts';
5
+ import type { FileInput, FormBody, ViewBody } from '../wire/classes.ts';
6
+ interface ActivationContext {
7
+ readonly capabilities?: ReadonlySet<string>;
8
+ readonly store?: {
9
+ get(hash: string): {
10
+ readonly bytes: Uint8Array;
11
+ } | undefined;
12
+ };
13
+ }
14
+ export interface Bindings {
15
+ readonly readers?: Readonly<Record<string, (file: FileInput) => Outcome<readonly Claim[]>>>;
16
+ readonly accepts?: Readonly<Record<string, (place: string) => boolean>>;
17
+ readonly views?: Readonly<Record<string, ViewBody<unknown>>>;
18
+ readonly forms?: Readonly<Record<string, FormBody<unknown>>>;
19
+ readonly activate?: (context: ActivationContext) => unknown;
20
+ }
21
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ import type { Claim } from '../wire/types.ts';
2
+ import type { ToposDescriptor } from '../wire/descriptor.ts';
3
+ import type { Bindings } from './bindings.ts';
4
+ /** A seen row has no origin: the SDK stamps by= and at= from what it handed over, and observe(bytes, digest) turns bytes into seen rows with no files, no store, no clock and no network. */
5
+ type Seen = {
6
+ readonly scope: string;
7
+ readonly measure: string;
8
+ readonly role: Claim['role'];
9
+ readonly bound: Claim['bound'];
10
+ readonly unit?: string;
11
+ };
12
+ type Observe = (bytes: Uint8Array, digest: string) => readonly Seen[];
13
+ export interface DefinedTopos {
14
+ readonly kind: 'defined';
15
+ readonly id: string;
16
+ readonly includes: readonly string[];
17
+ readonly members: readonly unknown[];
18
+ readonly claims: readonly Claim[];
19
+ readonly descriptor: ToposDescriptor;
20
+ readonly bindings: Bindings;
21
+ readonly domain?: readonly string[];
22
+ readonly observe?: Observe;
23
+ }
24
+ /** A region's cost is a fold of what was observed: the join of the spans its runs took, and none while it is only declared. */
25
+ export declare const costOf: (observed: readonly (readonly [number, number])[]) => {
26
+ readonly cost?: readonly [number, number];
27
+ };
28
+ export declare function defineTopos(opts: {
29
+ readonly id: string;
30
+ readonly includes?: readonly string[];
31
+ readonly members?: readonly unknown[];
32
+ readonly by?: string;
33
+ readonly bindings?: Bindings;
34
+ readonly domain?: readonly string[];
35
+ readonly observe?: Observe;
36
+ }): DefinedTopos;
37
+ export {};
@@ -0,0 +1,59 @@
1
+ /**
2
+ * A topos as a container. It lowers to an inert descriptor; it does not invent
3
+ * a fifth class or a universal composition law.
4
+ */
5
+ import { intervals } from '@lapxo/obligations';
6
+ import { claim } from "../wire/claim.js";
7
+ import { emptyDescriptor } from "../wire/descriptor.js";
8
+ const asClaim = (draft) => {
9
+ const judged = claim(draft);
10
+ if (judged.kind !== 'fact') {
11
+ throw new Error(judged.why);
12
+ }
13
+ return judged.value;
14
+ };
15
+ const SPANS = intervals(-Infinity, Infinity);
16
+ /** A region's cost is a fold of what was observed: the join of the spans its runs took, and none while it is only declared. */
17
+ export const costOf = (observed) => ((held) => (SPANS.inhabited(held) ? { cost: [held.lo, held.hi] } : {}))(observed.reduce((all, [lo, hi]) => SPANS.join(all, { lo, hi }), SPANS.bottom));
18
+ export function defineTopos(opts) {
19
+ const by = opts.by ?? opts.id;
20
+ const includes = opts.includes ?? [];
21
+ const members = opts.members ?? [];
22
+ const claims = opts.observe
23
+ ? []
24
+ : [
25
+ asClaim({
26
+ scope: `topos/${opts.id}/class`,
27
+ measure: 'kind',
28
+ role: 'reads',
29
+ by,
30
+ at: opts.id,
31
+ bound: { kind: 'enumerated', values: ['readers'] },
32
+ }),
33
+ ...includes.map((ref) => asClaim({
34
+ scope: `topos/${opts.id}/includes`,
35
+ measure: 'id',
36
+ role: 'reads',
37
+ by,
38
+ at: opts.id,
39
+ bound: { kind: 'enumerated', values: [ref] },
40
+ reference: { rel: 'within', to: [`topos/${ref}`], by: 'declared' },
41
+ })),
42
+ ];
43
+ const descriptor = {
44
+ ...emptyDescriptor(opts.id),
45
+ includes,
46
+ claims,
47
+ };
48
+ return {
49
+ kind: 'defined',
50
+ id: opts.id,
51
+ includes,
52
+ members,
53
+ claims,
54
+ descriptor,
55
+ bindings: opts.bindings ?? {},
56
+ ...(opts.domain ? { domain: opts.domain } : {}),
57
+ ...(opts.observe ? { observe: opts.observe } : {}),
58
+ };
59
+ }
@@ -0,0 +1,3 @@
1
+ /** It answers the world-neutral readers of lines — what does a line say? */
2
+ export { costOf, defineTopos } from './define.ts';
3
+ export type { DefinedTopos } from './define.ts';
@@ -0,0 +1,2 @@
1
+ /** It answers the world-neutral readers of lines — what does a line say? */
2
+ export { costOf, defineTopos } from "./define.js";
@@ -0,0 +1,4 @@
1
+ import type { Claim, Outcome } from './types.ts';
2
+ type ClaimDraft = Partial<Claim> & Pick<Claim, 'scope' | 'measure' | 'bound' | 'role'>;
3
+ export declare function claim(draft: ClaimDraft): Outcome<Claim>;
4
+ export {};
@@ -0,0 +1,43 @@
1
+ import { fact, refuse } from "./types.js";
2
+ const ROLES = new Set(['reads', 'writes', 'demands']);
3
+ const isPointBound = (b) => {
4
+ if (b.kind === 'interval')
5
+ return b.lo === b.hi;
6
+ if (b.kind === 'enumerated')
7
+ return b.values.length === 1;
8
+ return false;
9
+ };
10
+ const present = (value) => typeof value === 'string' && value.length > 0;
11
+ export function claim(draft) {
12
+ if (!present(draft.scope))
13
+ return refuse('claim: scope is required');
14
+ if (!present(draft.measure))
15
+ return refuse('claim: measure is required');
16
+ if (draft.bound === undefined)
17
+ return refuse('claim: bound is required');
18
+ if (!present(draft.role) || !ROLES.has(draft.role)) {
19
+ return refuse(`claim: role must be reads, writes, or demands, not ${String(draft.role)}`);
20
+ }
21
+ if (!present(draft.by))
22
+ return refuse('claim: by is required');
23
+ if (!present(draft.at))
24
+ return refuse('claim: at is required');
25
+ if (draft.role === 'writes' && !isPointBound(draft.bound)) {
26
+ return refuse('claim: a write states one value');
27
+ }
28
+ const built = {
29
+ scope: draft.scope,
30
+ measure: draft.measure,
31
+ bound: draft.bound,
32
+ role: draft.role,
33
+ by: draft.by,
34
+ at: draft.at,
35
+ ...(draft.unit !== undefined ? { unit: draft.unit } : {}),
36
+ ...(draft.epoch !== undefined ? { epoch: draft.epoch } : {}),
37
+ ...(draft.multiplicity !== undefined ? { multiplicity: draft.multiplicity } : {}),
38
+ ...(draft.reference !== undefined ? { reference: draft.reference } : {}),
39
+ ...(draft.support !== undefined ? { support: draft.support } : {}),
40
+ ...(draft.extra !== undefined ? { extra: draft.extra } : {}),
41
+ };
42
+ return fact(built);
43
+ }
@@ -0,0 +1,78 @@
1
+ import type { Outcome } from './outcome.ts';
2
+ import type { Claim } from './types.ts';
3
+ import type { FormGrammar } from './values.ts';
4
+ import type { KeyClass } from '../authority/motion.ts';
5
+ export declare const ENVELOPE: ReadonlySet<string>;
6
+ interface Wire {
7
+ readonly epoch: number;
8
+ readonly fields: ReadonlySet<string>;
9
+ readonly required: ReadonlySet<string>;
10
+ readonly roles: ReadonlySet<string>;
11
+ readonly forms: ReadonlySet<string>;
12
+ readonly classes: ReadonlySet<string>;
13
+ readonly digests: ReadonlySet<string>;
14
+ readonly signatures: ReadonlySet<string>;
15
+ readonly formOf: ReadonlyMap<string, string>;
16
+ readonly lists: ReadonlyMap<string, ReadonlySet<string>>;
17
+ }
18
+ export declare function isWireClaim(fields: Readonly<Record<string, string>>): boolean;
19
+ export declare function wireAt(lines: readonly Readonly<Record<string, string>>[], epoch: number): Wire | null;
20
+ export declare function fromLine(text: string, wire: Wire | null, grammars?: readonly FormGrammar[]): Outcome<Claim>;
21
+ export interface Signer {
22
+ readonly id: string;
23
+ readonly keyClass: KeyClass;
24
+ readonly publicKey: string;
25
+ readonly coverage: readonly string[];
26
+ readonly spans?: readonly {
27
+ readonly globs: readonly string[];
28
+ readonly from: number;
29
+ readonly to: number | null;
30
+ }[];
31
+ readonly depth: {
32
+ readonly lo: number;
33
+ readonly hi: number;
34
+ };
35
+ readonly admittedBy: readonly string[];
36
+ readonly epoch?: {
37
+ readonly start: number;
38
+ readonly close: number | null;
39
+ };
40
+ readonly windows?: readonly {
41
+ readonly lo: number;
42
+ readonly hi: number;
43
+ readonly from: number;
44
+ readonly to: number | null;
45
+ }[];
46
+ }
47
+ type Verify = (fields: Readonly<Record<string, string>>, publicKey: string) => boolean;
48
+ export type SignerVerdict = {
49
+ readonly kind: 'admitted';
50
+ readonly signer: string;
51
+ } | {
52
+ readonly kind: 'grey';
53
+ readonly why: string;
54
+ } | {
55
+ readonly kind: 'refuse';
56
+ readonly why: string;
57
+ readonly named: string;
58
+ };
59
+ export declare function isKeyClaim(fields: Readonly<Record<string, string>>): boolean;
60
+ export declare function windowAt(signer: Signer, epoch: number): {
61
+ readonly start: number;
62
+ readonly close: number | null;
63
+ };
64
+ export declare function signersOf(lines: readonly Readonly<Record<string, string>>[], root: Signer, verify: Verify): {
65
+ readonly admitted: readonly Signer[];
66
+ readonly potential: readonly string[];
67
+ };
68
+ export declare function authorityOf(fields: Readonly<Record<string, string>>, signers: readonly Signer[], verify: Verify): SignerVerdict;
69
+ declare const COORDINATE_ROLES: readonly ["source", "derived", "observed", "foreign"];
70
+ export type CoordinateRole = (typeof COORDINATE_ROLES)[number];
71
+ export interface RoleClaim {
72
+ readonly name: string;
73
+ readonly role: CoordinateRole;
74
+ }
75
+ export declare function roleClaimsOf(lines: readonly Readonly<Record<string, string>>[]): readonly RoleClaim[];
76
+ export declare function namesAt(at: string, name: string): boolean;
77
+ export declare function roleAt(at: string, claims: readonly RoleClaim[]): CoordinateRole;
78
+ export {};