@amalgm/live 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 (159) hide show
  1. package/PURPOSE.md +103 -0
  2. package/README.md +45 -0
  3. package/dist/contracts/binding.d.ts +49 -0
  4. package/dist/contracts/binding.d.ts.map +1 -0
  5. package/dist/contracts/binding.js +23 -0
  6. package/dist/contracts/binding.js.map +1 -0
  7. package/dist/contracts/content.d.ts +42 -0
  8. package/dist/contracts/content.d.ts.map +1 -0
  9. package/dist/contracts/content.js +72 -0
  10. package/dist/contracts/content.js.map +1 -0
  11. package/dist/contracts/docs.d.ts +64 -0
  12. package/dist/contracts/docs.d.ts.map +1 -0
  13. package/dist/contracts/docs.js +51 -0
  14. package/dist/contracts/docs.js.map +1 -0
  15. package/dist/contracts/events.d.ts +45 -0
  16. package/dist/contracts/events.d.ts.map +1 -0
  17. package/dist/contracts/events.js +38 -0
  18. package/dist/contracts/events.js.map +1 -0
  19. package/dist/contracts/frames/gateway.d.ts +83 -0
  20. package/dist/contracts/frames/gateway.d.ts.map +1 -0
  21. package/dist/contracts/frames/gateway.js +35 -0
  22. package/dist/contracts/frames/gateway.js.map +1 -0
  23. package/dist/contracts/frames/stream.d.ts +59 -0
  24. package/dist/contracts/frames/stream.d.ts.map +1 -0
  25. package/dist/contracts/frames/stream.js +17 -0
  26. package/dist/contracts/frames/stream.js.map +1 -0
  27. package/dist/contracts/frames/tunnel.d.ts +78 -0
  28. package/dist/contracts/frames/tunnel.d.ts.map +1 -0
  29. package/dist/contracts/frames/tunnel.js +55 -0
  30. package/dist/contracts/frames/tunnel.js.map +1 -0
  31. package/dist/contracts/index.d.ts +19 -0
  32. package/dist/contracts/index.d.ts.map +1 -0
  33. package/dist/contracts/index.js +19 -0
  34. package/dist/contracts/index.js.map +1 -0
  35. package/dist/contracts/mutation.d.ts +51 -0
  36. package/dist/contracts/mutation.d.ts.map +1 -0
  37. package/dist/contracts/mutation.js +55 -0
  38. package/dist/contracts/mutation.js.map +1 -0
  39. package/dist/contracts/presence.d.ts +46 -0
  40. package/dist/contracts/presence.d.ts.map +1 -0
  41. package/dist/contracts/presence.js +34 -0
  42. package/dist/contracts/presence.js.map +1 -0
  43. package/dist/contracts/resources.d.ts +52 -0
  44. package/dist/contracts/resources.d.ts.map +1 -0
  45. package/dist/contracts/resources.js +105 -0
  46. package/dist/contracts/resources.js.map +1 -0
  47. package/dist/contracts/snapshot.d.ts +24 -0
  48. package/dist/contracts/snapshot.d.ts.map +1 -0
  49. package/dist/contracts/snapshot.js +28 -0
  50. package/dist/contracts/snapshot.js.map +1 -0
  51. package/dist/contracts/validate.d.ts +32 -0
  52. package/dist/contracts/validate.d.ts.map +1 -0
  53. package/dist/contracts/validate.js +25 -0
  54. package/dist/contracts/validate.js.map +1 -0
  55. package/dist/detection/adapter-contract.d.ts +134 -0
  56. package/dist/detection/adapter-contract.d.ts.map +1 -0
  57. package/dist/detection/adapter-contract.js +162 -0
  58. package/dist/detection/adapter-contract.js.map +1 -0
  59. package/dist/detection/classify.d.ts +31 -0
  60. package/dist/detection/classify.d.ts.map +1 -0
  61. package/dist/detection/classify.js +28 -0
  62. package/dist/detection/classify.js.map +1 -0
  63. package/dist/detection/continuity.d.ts +54 -0
  64. package/dist/detection/continuity.d.ts.map +1 -0
  65. package/dist/detection/continuity.js +85 -0
  66. package/dist/detection/continuity.js.map +1 -0
  67. package/dist/detection/coverage.d.ts +43 -0
  68. package/dist/detection/coverage.d.ts.map +1 -0
  69. package/dist/detection/coverage.js +60 -0
  70. package/dist/detection/coverage.js.map +1 -0
  71. package/dist/detection/diff.d.ts +144 -0
  72. package/dist/detection/diff.d.ts.map +1 -0
  73. package/dist/detection/diff.js +187 -0
  74. package/dist/detection/diff.js.map +1 -0
  75. package/dist/detection/enrollment.d.ts +16 -0
  76. package/dist/detection/enrollment.d.ts.map +1 -0
  77. package/dist/detection/enrollment.js +70 -0
  78. package/dist/detection/enrollment.js.map +1 -0
  79. package/dist/detection/index.d.ts +29 -0
  80. package/dist/detection/index.d.ts.map +1 -0
  81. package/dist/detection/index.js +29 -0
  82. package/dist/detection/index.js.map +1 -0
  83. package/dist/detection/refusal.d.ts +33 -0
  84. package/dist/detection/refusal.d.ts.map +1 -0
  85. package/dist/detection/refusal.js +40 -0
  86. package/dist/detection/refusal.js.map +1 -0
  87. package/dist/entities/bytes.d.ts +18 -0
  88. package/dist/entities/bytes.d.ts.map +1 -0
  89. package/dist/entities/bytes.js +61 -0
  90. package/dist/entities/bytes.js.map +1 -0
  91. package/dist/entities/cloud.d.ts +82 -0
  92. package/dist/entities/cloud.d.ts.map +1 -0
  93. package/dist/entities/cloud.js +136 -0
  94. package/dist/entities/cloud.js.map +1 -0
  95. package/dist/entities/index.d.ts +23 -0
  96. package/dist/entities/index.d.ts.map +1 -0
  97. package/dist/entities/index.js +23 -0
  98. package/dist/entities/index.js.map +1 -0
  99. package/dist/entities/moves.d.ts +42 -0
  100. package/dist/entities/moves.d.ts.map +1 -0
  101. package/dist/entities/moves.js +82 -0
  102. package/dist/entities/moves.js.map +1 -0
  103. package/dist/entities/repo-states.d.ts +121 -0
  104. package/dist/entities/repo-states.d.ts.map +1 -0
  105. package/dist/entities/repo-states.js +127 -0
  106. package/dist/entities/repo-states.js.map +1 -0
  107. package/dist/entities/rules.d.ts +104 -0
  108. package/dist/entities/rules.d.ts.map +1 -0
  109. package/dist/entities/rules.js +200 -0
  110. package/dist/entities/rules.js.map +1 -0
  111. package/dist/entities/types.d.ts +94 -0
  112. package/dist/entities/types.d.ts.map +1 -0
  113. package/dist/entities/types.js +40 -0
  114. package/dist/entities/types.js.map +1 -0
  115. package/dist/index.d.ts +17 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +17 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/machines/arbitration.d.ts +36 -0
  120. package/dist/machines/arbitration.d.ts.map +1 -0
  121. package/dist/machines/arbitration.js +37 -0
  122. package/dist/machines/arbitration.js.map +1 -0
  123. package/dist/machines/backoff.d.ts +36 -0
  124. package/dist/machines/backoff.d.ts.map +1 -0
  125. package/dist/machines/backoff.js +34 -0
  126. package/dist/machines/backoff.js.map +1 -0
  127. package/dist/machines/bootstrap.d.ts +65 -0
  128. package/dist/machines/bootstrap.d.ts.map +1 -0
  129. package/dist/machines/bootstrap.js +105 -0
  130. package/dist/machines/bootstrap.js.map +1 -0
  131. package/dist/machines/chunks.d.ts +51 -0
  132. package/dist/machines/chunks.d.ts.map +1 -0
  133. package/dist/machines/chunks.js +67 -0
  134. package/dist/machines/chunks.js.map +1 -0
  135. package/dist/machines/index.d.ts +14 -0
  136. package/dist/machines/index.d.ts.map +1 -0
  137. package/dist/machines/index.js +14 -0
  138. package/dist/machines/index.js.map +1 -0
  139. package/dist/machines/journal.d.ts +63 -0
  140. package/dist/machines/journal.d.ts.map +1 -0
  141. package/dist/machines/journal.js +71 -0
  142. package/dist/machines/journal.js.map +1 -0
  143. package/dist/machines/ordering.d.ts +53 -0
  144. package/dist/machines/ordering.d.ts.map +1 -0
  145. package/dist/machines/ordering.js +87 -0
  146. package/dist/machines/ordering.js.map +1 -0
  147. package/dist/machines/presence.d.ts +26 -0
  148. package/dist/machines/presence.d.ts.map +1 -0
  149. package/dist/machines/presence.js +49 -0
  150. package/dist/machines/presence.js.map +1 -0
  151. package/dist/merge/index.d.ts +9 -0
  152. package/dist/merge/index.d.ts.map +1 -0
  153. package/dist/merge/index.js +9 -0
  154. package/dist/merge/index.js.map +1 -0
  155. package/dist/merge/merge3.d.ts +39 -0
  156. package/dist/merge/merge3.d.ts.map +1 -0
  157. package/dist/merge/merge3.js +188 -0
  158. package/dist/merge/merge3.js.map +1 -0
  159. package/package.json +48 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Resource identity — the names of live channels.
3
+ *
4
+ * A resource is a named channel over the local wire
5
+ * (local-live-protocol.md §1). The shipped grammar:
6
+ *
7
+ * tasks a well-known singleton table
8
+ * app:<appId>:<name> a per-app named resource
9
+ * doc:<base64url(path)> a live document, addressed by local path
10
+ * files:<base64url(dir)> a directory listing channel
11
+ *
12
+ * A shared resource additionally receives a cloud id that never depends on
13
+ * any user's local path (realtime-sdk.md §2); path-derived ids are for
14
+ * unshared local resources only. Renaming a materialized file must not
15
+ * change a shared id — which is exactly why the shared id is not derived
16
+ * from the path.
17
+ */
18
+ import { type Checked } from './validate.js';
19
+ export type ResourceName = string;
20
+ export type ParsedResource = {
21
+ readonly kind: 'table';
22
+ readonly name: string;
23
+ } | {
24
+ readonly kind: 'app';
25
+ readonly appId: string;
26
+ readonly name: string;
27
+ } | {
28
+ readonly kind: 'doc';
29
+ readonly path: string;
30
+ } | {
31
+ readonly kind: 'files';
32
+ readonly dir: string;
33
+ };
34
+ /** `doc:<base64url(path)>` for the document at a local path. */
35
+ export declare const docResource: (path: string) => ResourceName;
36
+ /** `files:<base64url(dir)>` for the listing channel of a directory. */
37
+ export declare const filesResource: (dir: string) => ResourceName;
38
+ /** `app:<appId>:<name>` for an app-scoped resource. */
39
+ export declare const appResource: (appId: string, name: string) => ResourceName;
40
+ /**
41
+ * Parse any shipped resource name into its addressed form.
42
+ *
43
+ * parseResource('doc:bm90ZXMubWQ') → { kind: 'doc', path: 'notes.md' }
44
+ * parseResource('app:canvas:board') → { kind: 'app', appId: 'canvas', name: 'board' }
45
+ * parseResource('tasks') → { kind: 'table', name: 'tasks' }
46
+ */
47
+ export declare function parseResource(resource: unknown): Checked<ParsedResource>;
48
+ /** UTF-8 → unpadded base64url. Portable: no Buffer, no btoa. */
49
+ export declare function encodeBase64Url(text: string): string;
50
+ /** Unpadded base64url → UTF-8, or null when the input is not base64url. */
51
+ export declare function decodeBase64Url(encoded: string): string | null;
52
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/contracts/resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAqC,MAAM,eAAe,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,gEAAgE;AAChE,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,YAA8C,CAAC;AAE1F,uEAAuE;AACvE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,YAA+C,CAAC;AAE5F,uDAAuD;AACvD,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,KAAG,YAAsC,CAAC;AAEjG;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CA6BxE;AAID,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAapD;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoB9D"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Resource identity — the names of live channels.
3
+ *
4
+ * A resource is a named channel over the local wire
5
+ * (local-live-protocol.md §1). The shipped grammar:
6
+ *
7
+ * tasks a well-known singleton table
8
+ * app:<appId>:<name> a per-app named resource
9
+ * doc:<base64url(path)> a live document, addressed by local path
10
+ * files:<base64url(dir)> a directory listing channel
11
+ *
12
+ * A shared resource additionally receives a cloud id that never depends on
13
+ * any user's local path (realtime-sdk.md §2); path-derived ids are for
14
+ * unshared local resources only. Renaming a materialized file must not
15
+ * change a shared id — which is exactly why the shared id is not derived
16
+ * from the path.
17
+ */
18
+ import { pass, failShape, isNonEmptyString } from './validate.js';
19
+ /** `doc:<base64url(path)>` for the document at a local path. */
20
+ export const docResource = (path) => `doc:${encodeBase64Url(path)}`;
21
+ /** `files:<base64url(dir)>` for the listing channel of a directory. */
22
+ export const filesResource = (dir) => `files:${encodeBase64Url(dir)}`;
23
+ /** `app:<appId>:<name>` for an app-scoped resource. */
24
+ export const appResource = (appId, name) => `app:${appId}:${name}`;
25
+ /**
26
+ * Parse any shipped resource name into its addressed form.
27
+ *
28
+ * parseResource('doc:bm90ZXMubWQ') → { kind: 'doc', path: 'notes.md' }
29
+ * parseResource('app:canvas:board') → { kind: 'app', appId: 'canvas', name: 'board' }
30
+ * parseResource('tasks') → { kind: 'table', name: 'tasks' }
31
+ */
32
+ export function parseResource(resource) {
33
+ if (!isNonEmptyString(resource)) {
34
+ return failShape(`a resource name like "tasks" or "doc:${encodeBase64Url('notes.md')}"`, `got ${typeof resource}`);
35
+ }
36
+ const [prefix] = resource.split(':', 1);
37
+ switch (prefix) {
38
+ case 'doc': {
39
+ const path = decodeBase64Url(resource.slice('doc:'.length));
40
+ return path === null
41
+ ? failShape(`"doc:${encodeBase64Url('notes.md')}" (base64url of the path)`, `"${resource}" carries invalid base64url`)
42
+ : pass({ kind: 'doc', path });
43
+ }
44
+ case 'files': {
45
+ const dir = decodeBase64Url(resource.slice('files:'.length));
46
+ return dir === null
47
+ ? failShape(`"files:${encodeBase64Url('notes')}" (base64url of the directory)`, `"${resource}" carries invalid base64url`)
48
+ : pass({ kind: 'files', dir });
49
+ }
50
+ case 'app': {
51
+ const rest = resource.slice('app:'.length);
52
+ const divider = rest.indexOf(':');
53
+ if (divider <= 0 || divider === rest.length - 1) {
54
+ return failShape('"app:<appId>:<name>", e.g. "app:canvas:board"', `"${resource}" is missing the appId or name segment`);
55
+ }
56
+ return pass({ kind: 'app', appId: rest.slice(0, divider), name: rest.slice(divider + 1) });
57
+ }
58
+ default:
59
+ return pass({ kind: 'table', name: resource });
60
+ }
61
+ }
62
+ const BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
63
+ /** UTF-8 → unpadded base64url. Portable: no Buffer, no btoa. */
64
+ export function encodeBase64Url(text) {
65
+ const bytes = new TextEncoder().encode(text);
66
+ let out = '';
67
+ for (let i = 0; i < bytes.length; i += 3) {
68
+ const a = bytes[i];
69
+ const b = bytes[i + 1];
70
+ const c = bytes[i + 2];
71
+ out += BASE64_ALPHABET[a >> 2];
72
+ out += BASE64_ALPHABET[((a & 0x03) << 4) | ((b ?? 0) >> 4)];
73
+ if (b !== undefined)
74
+ out += BASE64_ALPHABET[((b & 0x0f) << 2) | ((c ?? 0) >> 6)];
75
+ if (c !== undefined)
76
+ out += BASE64_ALPHABET[c & 0x3f];
77
+ }
78
+ return out;
79
+ }
80
+ /** Unpadded base64url → UTF-8, or null when the input is not base64url. */
81
+ export function decodeBase64Url(encoded) {
82
+ if (encoded.length % 4 === 1)
83
+ return null;
84
+ const bytes = [];
85
+ let buffer = 0;
86
+ let bits = 0;
87
+ for (const char of encoded) {
88
+ const value = BASE64_ALPHABET.indexOf(char);
89
+ if (value === -1)
90
+ return null;
91
+ buffer = (buffer << 6) | value;
92
+ bits += 6;
93
+ if (bits >= 8) {
94
+ bits -= 8;
95
+ bytes.push((buffer >> bits) & 0xff);
96
+ }
97
+ }
98
+ try {
99
+ return new TextDecoder('utf-8', { fatal: true }).decode(new Uint8Array(bytes));
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/contracts/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Snapshots — the resume point of every recovery path.
3
+ *
4
+ * A snapshot is the full value of each requested resource, consistent as of
5
+ * `seq` when `stable` is true (local-live-protocol.md §1). The builder may
6
+ * race writes; after 3 attempts it serves best-effort data with
7
+ * `stable: false`. Clients may treat an unstable snapshot like a stable one
8
+ * — the live stream repairs staleness — but must never cache it as a
9
+ * consistency proof.
10
+ *
11
+ * Recovery rule: every failure path (seq gap beyond the buffer, `reset`
12
+ * frame, failed backfill) converges on "fetch a snapshot and resume from
13
+ * its seq".
14
+ */
15
+ import { type Checked } from './validate.js';
16
+ import type { ResourceName } from './resources.js';
17
+ export interface Snapshot {
18
+ readonly seq: number;
19
+ /** False when every build attempt raced a write; data is best-effort at this seq. */
20
+ readonly stable: boolean;
21
+ readonly resources: Readonly<Record<ResourceName, unknown>>;
22
+ }
23
+ export declare function checkSnapshot(input: unknown): Checked<Snapshot>;
24
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/contracts/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAoC,MAAM,eAAe,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;CAC7D;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAQ/D"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Snapshots — the resume point of every recovery path.
3
+ *
4
+ * A snapshot is the full value of each requested resource, consistent as of
5
+ * `seq` when `stable` is true (local-live-protocol.md §1). The builder may
6
+ * race writes; after 3 attempts it serves best-effort data with
7
+ * `stable: false`. Clients may treat an unstable snapshot like a stable one
8
+ * — the live stream repairs staleness — but must never cache it as a
9
+ * consistency proof.
10
+ *
11
+ * Recovery rule: every failure path (seq gap beyond the buffer, `reset`
12
+ * frame, failed backfill) converges on "fetch a snapshot and resume from
13
+ * its seq".
14
+ */
15
+ import { pass, failShape, isRecord, isSeq } from './validate.js';
16
+ const EXAMPLE = '{ seq: 42, stable: true, resources: { tasks: [...] } }';
17
+ export function checkSnapshot(input) {
18
+ if (!isRecord(input))
19
+ return failShape(EXAMPLE, `got ${input === null ? 'null' : typeof input}`);
20
+ if (!isSeq(input.seq))
21
+ return failShape(EXAMPLE, `seq was ${JSON.stringify(input.seq)}, not a non-negative integer`);
22
+ if (!isRecord(input.resources)) {
23
+ return failShape(EXAMPLE, `resources was ${JSON.stringify(input.resources)}, not an object`);
24
+ }
25
+ const stable = input.stable !== false; // absent means stable: the field is an additive escape hatch
26
+ return pass({ seq: input.seq, stable, resources: input.resources });
27
+ }
28
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/contracts/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAgB,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAU/E,MAAM,OAAO,GAAG,wDAAwD,CAAC;AAEzE,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,OAAO,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IACjG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,OAAO,EAAE,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IACrH,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC,OAAO,EAAE,iBAAiB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,6DAA6D;IACpG,OAAO,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Shared validation vocabulary for every contract in this package.
3
+ *
4
+ * Validators never throw on bad wire data — a peer being wrong is an
5
+ * expected condition, not an exception (local-live-protocol.md: unknown
6
+ * frames mean "the other end is older"). They return a `Checked<T>` so
7
+ * callers must look at the outcome, and every failure message is
8
+ * example-first: it states what a correct value looks like before saying
9
+ * what was wrong (see PURPOSE.md axiom on error shape).
10
+ */
11
+ export type Checked<T> = {
12
+ readonly ok: true;
13
+ readonly value: T;
14
+ } | {
15
+ readonly ok: false;
16
+ readonly error: string;
17
+ };
18
+ export declare const pass: <T>(value: T) => Checked<T>;
19
+ export declare const fail: <T = never>(error: string) => Checked<T>;
20
+ /**
21
+ * Build an example-first failure: `expected` is a correct literal shape,
22
+ * `problem` names the specific field that broke it.
23
+ *
24
+ * failShape('{ seq: 42, resource: "tasks", op: "update" }',
25
+ * 'op was "patch", not one of insert|update|delete|replace|invalidate')
26
+ */
27
+ export declare const failShape: <T = never>(expected: string, problem: string) => Checked<T>;
28
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
29
+ export declare const isNonEmptyString: (value: unknown) => value is string;
30
+ /** A strictly increasing wire sequence number: a non-negative safe integer. */
31
+ export declare const isSeq: (value: unknown) => value is number;
32
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/contracts/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,OAAO,CAAC,CAAC,IACjB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACxC;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,OAAO,CAAC,CAAC,CAA0B,CAAC;AAEvE,eAAO,MAAM,IAAI,GAAI,CAAC,GAAG,KAAK,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,CAA2B,CAAC;AAErF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,GAAG,KAAK,EAAE,UAAU,MAAM,EAAE,SAAS,MAAM,KAAG,OAAO,CAAC,CAAC,CACvC,CAAC;AAE5C,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAEvE,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MACZ,CAAC;AAEhD,+EAA+E;AAC/E,eAAO,MAAM,KAAK,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MACwB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shared validation vocabulary for every contract in this package.
3
+ *
4
+ * Validators never throw on bad wire data — a peer being wrong is an
5
+ * expected condition, not an exception (local-live-protocol.md: unknown
6
+ * frames mean "the other end is older"). They return a `Checked<T>` so
7
+ * callers must look at the outcome, and every failure message is
8
+ * example-first: it states what a correct value looks like before saying
9
+ * what was wrong (see PURPOSE.md axiom on error shape).
10
+ */
11
+ export const pass = (value) => ({ ok: true, value });
12
+ export const fail = (error) => ({ ok: false, error });
13
+ /**
14
+ * Build an example-first failure: `expected` is a correct literal shape,
15
+ * `problem` names the specific field that broke it.
16
+ *
17
+ * failShape('{ seq: 42, resource: "tasks", op: "update" }',
18
+ * 'op was "patch", not one of insert|update|delete|replace|invalidate')
19
+ */
20
+ export const failShape = (expected, problem) => fail(`expected ${expected} — ${problem}`);
21
+ export const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
22
+ export const isNonEmptyString = (value) => typeof value === 'string' && value.length > 0;
23
+ /** A strictly increasing wire sequence number: a non-negative safe integer. */
24
+ export const isSeq = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
25
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/contracts/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAI,KAAQ,EAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAY,KAAa,EAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAErF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAY,QAAgB,EAAE,OAAe,EAAc,EAAE,CACpF,IAAI,CAAC,YAAY,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;AAE5C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAmB,EAAE,CAClE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAEhD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAc,EAAmB,EAAE,CACvD,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The adapter contract: what it means to serve an entity type.
3
+ *
4
+ * An adapter is how a KIND of entity rides the seven realtime rails —
5
+ * watch, detect, record, send, receive, apply, verify. The entity's
6
+ * `type` selects its adapter; the rails themselves never change shape
7
+ * per type. Ratified by entity-model.md ("Type selects the complete
8
+ * adapter cycle") and entity-implementation.md.
9
+ *
10
+ * Axioms:
11
+ *
12
+ * 1. ONE ADAPTER PER TYPE, EVERY TYPE ASSIGNED. The alphabet belongs
13
+ * to the registry; the adapter map covers it exactly — no type
14
+ * unassigned, no type claimed twice. Assigned is not yet
15
+ * operational: operational is earned rail by rail, and absence is
16
+ * honest.
17
+ * 2. ADAPTERS OWN BEHAVIOR; THE REGISTRY OWNS IDENTITY. A lawful type
18
+ * transition that crosses adapters is a handoff on the same UUID,
19
+ * never a rebirth.
20
+ * 3. ONE SOCKET PER RAIL. A rail's callable surfaces are ratified
21
+ * HERE, once, for every adapter (`SOCKETS`). An adapter binds a
22
+ * rail's whole socket or binds the rail not at all; a rail whose
23
+ * socket is not yet ratified cannot be bound by anyone.
24
+ * 4. A TRUTH READ NEVER LIES. Every assigned type names its source of
25
+ * truth in one sentence, and reading it produces exactly one of
26
+ * three honest answers: present, absent, or unsettled.
27
+ * 5. RAILS ARE HONEST. An unbound rail is absent — never stubbed,
28
+ * never defaulted.
29
+ * 6. THE CONTRACT IS FROZEN GROUND. A descriptor is immutable from
30
+ * the moment it loads.
31
+ * 7. THE BASE ORCHESTRATES; THE ADAPTER SUPPLIES TYPE BEHAVIOR. A
32
+ * rail earns a socket only when a real consumer proves that
33
+ * behavior differs by type — never for symmetry.
34
+ */
35
+ export type Rail = 'watch' | 'detect' | 'record' | 'send' | 'receive' | 'apply' | 'verify';
36
+ /** The seven rails, declared once, frozen, in journey order. */
37
+ export declare const RAILS: readonly Rail[];
38
+ /**
39
+ * The three honest answers of a truth read (axiom 4):
40
+ *
41
+ * { truth: 'present', version, state } the complete current truth,
42
+ * fingerprinted — equal versions mean equal truth, and equal truth
43
+ * is silence
44
+ * { truth: 'absent' } the ground genuinely is not
45
+ * there — a fact, not an error
46
+ * { truth: 'unsettled', reason } changing or unreadable right
47
+ * now; read again — never a partial answer
48
+ */
49
+ export type TruthReading = {
50
+ readonly truth: 'present';
51
+ readonly version: string;
52
+ readonly state?: unknown;
53
+ } | {
54
+ readonly truth: 'absent';
55
+ } | {
56
+ readonly truth: 'unsettled';
57
+ readonly reason?: string | undefined;
58
+ };
59
+ /** The one ratified socket: detect's truth read. */
60
+ export interface DetectSocket {
61
+ readonly truth: (path: string) => TruthReading;
62
+ }
63
+ /**
64
+ * The ratified sockets — for each rail that has one, the exact surfaces
65
+ * every binding adapter implements. Same names, same shapes, every
66
+ * type. ONE socket is ratified today (detect), derived from what
67
+ * production detection actually asks of a type. Watch and record earn
68
+ * none at this bar (adjudicated 2026-08-03 under axiom 7); apply and
69
+ * verify join only when the Send/Receive rails exist to derive their
70
+ * socket from. A socket is ratified from a real consumer or it is not
71
+ * ratified at all.
72
+ */
73
+ export declare const SOCKETS: Readonly<Partial<Record<Rail, readonly string[]>>>;
74
+ /**
75
+ * A lawful adapter descriptor. The shape is deliberately tiny:
76
+ *
77
+ * name — the adapter's one name
78
+ * types — { entityType: 'one-sentence source of truth', ... }
79
+ * rails — only rails whose ratified socket the adapter fully
80
+ * implements; detect is the only bindable rail today
81
+ */
82
+ export interface AdapterDescriptor {
83
+ readonly name: string;
84
+ readonly types: Readonly<Record<string, string>>;
85
+ readonly rails: {
86
+ readonly detect?: DetectSocket;
87
+ };
88
+ }
89
+ /**
90
+ * Convict a malformed adapter descriptor loudly; return it (typed)
91
+ * unchanged when lawful.
92
+ */
93
+ export declare function assertAdapter(adapter: unknown): AdapterDescriptor;
94
+ /**
95
+ * Build the one type → adapter map, convicting every violation of
96
+ * axiom 1: an adapter claiming a type outside the alphabet, two
97
+ * adapters claiming one type, or an alphabet type left unassigned.
98
+ * Pure — callers own where the alphabet and adapters come from.
99
+ */
100
+ export declare function buildTypeMap(adapters: Iterable<unknown>, alphabet: Iterable<string>): Map<string, AdapterDescriptor>;
101
+ /** A failed look at ground, as the host's filesystem reported it. */
102
+ export interface FailedLook {
103
+ readonly code?: string | undefined;
104
+ }
105
+ /**
106
+ * The three-state vocabulary's one shared judgment: what a FAILED look
107
+ * at ground means. ENOENT and ENOTDIR are the filesystem itself saying
108
+ * "not there" — honest ABSENCE, a fact. Every other failure means the
109
+ * LOOK failed, not the ground — UNSETTLED: no conclusion, read again.
110
+ *
111
+ * Every truth reader classifies through this one function so no reader
112
+ * can invent its own idea of absence: mistaking "could not look" for
113
+ * "not there" is the exact lie axiom 4 forbids. Only present or absent
114
+ * may produce a conclusion.
115
+ */
116
+ export declare const lookFailed: (error: FailedLook) => {
117
+ readonly truth: "absent";
118
+ } | {
119
+ readonly truth: "unsettled";
120
+ readonly reason: string | undefined;
121
+ };
122
+ /**
123
+ * The managed-reference adapter: Amalgm's OWN link kind, never
124
+ * conflated with a filesystem symlink. Its payload is the target
125
+ * entity's UUID — identity, not an address — and its local rendering as
126
+ * an ordinary symlink is DERIVED state (entity-model.md, symlink
127
+ * section). ASSIGNED, NOT YET OPERATIONAL — and that absence is the
128
+ * honest truth: no rail is bound because the projection lives inside
129
+ * the registration boundary today; its detect socket is ratified from
130
+ * that seam when the projection is extracted, never invented ahead of
131
+ * it.
132
+ */
133
+ export declare const referenceAdapter: AdapterDescriptor;
134
+ //# sourceMappingURL=adapter-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-contract.d.ts","sourceRoot":"","sources":["../../src/detection/adapter-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3F,gEAAgE;AAChE,eAAO,MAAM,KAAK,EAAE,SAAS,IAAI,EAE/B,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE1E,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC;CAChD;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAErE,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;CACpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,CA6CjE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAC3B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GACzB,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAsBhC;AAED,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,UAAU,KAChB;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAGpD,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,iBAM7B,CAAC"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The adapter contract: what it means to serve an entity type.
3
+ *
4
+ * An adapter is how a KIND of entity rides the seven realtime rails —
5
+ * watch, detect, record, send, receive, apply, verify. The entity's
6
+ * `type` selects its adapter; the rails themselves never change shape
7
+ * per type. Ratified by entity-model.md ("Type selects the complete
8
+ * adapter cycle") and entity-implementation.md.
9
+ *
10
+ * Axioms:
11
+ *
12
+ * 1. ONE ADAPTER PER TYPE, EVERY TYPE ASSIGNED. The alphabet belongs
13
+ * to the registry; the adapter map covers it exactly — no type
14
+ * unassigned, no type claimed twice. Assigned is not yet
15
+ * operational: operational is earned rail by rail, and absence is
16
+ * honest.
17
+ * 2. ADAPTERS OWN BEHAVIOR; THE REGISTRY OWNS IDENTITY. A lawful type
18
+ * transition that crosses adapters is a handoff on the same UUID,
19
+ * never a rebirth.
20
+ * 3. ONE SOCKET PER RAIL. A rail's callable surfaces are ratified
21
+ * HERE, once, for every adapter (`SOCKETS`). An adapter binds a
22
+ * rail's whole socket or binds the rail not at all; a rail whose
23
+ * socket is not yet ratified cannot be bound by anyone.
24
+ * 4. A TRUTH READ NEVER LIES. Every assigned type names its source of
25
+ * truth in one sentence, and reading it produces exactly one of
26
+ * three honest answers: present, absent, or unsettled.
27
+ * 5. RAILS ARE HONEST. An unbound rail is absent — never stubbed,
28
+ * never defaulted.
29
+ * 6. THE CONTRACT IS FROZEN GROUND. A descriptor is immutable from
30
+ * the moment it loads.
31
+ * 7. THE BASE ORCHESTRATES; THE ADAPTER SUPPLIES TYPE BEHAVIOR. A
32
+ * rail earns a socket only when a real consumer proves that
33
+ * behavior differs by type — never for symmetry.
34
+ */
35
+ /** The seven rails, declared once, frozen, in journey order. */
36
+ export const RAILS = Object.freeze([
37
+ 'watch', 'detect', 'record', 'send', 'receive', 'apply', 'verify',
38
+ ]);
39
+ /**
40
+ * The ratified sockets — for each rail that has one, the exact surfaces
41
+ * every binding adapter implements. Same names, same shapes, every
42
+ * type. ONE socket is ratified today (detect), derived from what
43
+ * production detection actually asks of a type. Watch and record earn
44
+ * none at this bar (adjudicated 2026-08-03 under axiom 7); apply and
45
+ * verify join only when the Send/Receive rails exist to derive their
46
+ * socket from. A socket is ratified from a real consumer or it is not
47
+ * ratified at all.
48
+ */
49
+ export const SOCKETS = Object.freeze({
50
+ detect: Object.freeze(['truth']),
51
+ });
52
+ /**
53
+ * Convict a malformed adapter descriptor loudly; return it (typed)
54
+ * unchanged when lawful.
55
+ */
56
+ export function assertAdapter(adapter) {
57
+ const isRecord = (value) => typeof value === 'object' && value !== null;
58
+ const where = isRecord(adapter) && typeof adapter['name'] === 'string' && adapter['name']
59
+ ? `adapter ${JSON.stringify(adapter['name'])}` : 'adapter';
60
+ if (!isRecord(adapter) || !Object.isFrozen(adapter)) {
61
+ throw new Error(`${where}: a descriptor is a frozen object`);
62
+ }
63
+ if (typeof adapter['name'] !== 'string' || adapter['name'].length === 0) {
64
+ throw new Error('adapter: name is a non-empty string');
65
+ }
66
+ const { types, rails } = adapter;
67
+ if (!isRecord(types) || !Object.isFrozen(types) || Object.keys(types).length === 0) {
68
+ throw new Error(`${where}: types is a frozen, non-empty map of entity type → declared truth`);
69
+ }
70
+ for (const [type, truth] of Object.entries(types)) {
71
+ if (typeof truth !== 'string' || truth.length === 0) {
72
+ throw new Error(`${where}: type ${JSON.stringify(type)} must declare its source of truth in one sentence`);
73
+ }
74
+ }
75
+ if (!isRecord(rails) || !Object.isFrozen(rails)) {
76
+ throw new Error(`${where}: rails is a frozen map (empty is honest; a stub is not)`);
77
+ }
78
+ for (const [rail, surfaces] of Object.entries(rails)) {
79
+ if (!RAILS.includes(rail)) {
80
+ throw new Error(`${where}: ${JSON.stringify(rail)} is not a rail — the rails are ${RAILS.join(', ')}`);
81
+ }
82
+ const socket = SOCKETS[rail];
83
+ if (!socket) {
84
+ throw new Error(`${where}: rail ${rail} has no ratified socket yet — a socket is ratified in the contract before anyone binds it`);
85
+ }
86
+ if (!isRecord(surfaces) || !Object.isFrozen(surfaces)) {
87
+ throw new Error(`${where}: rail ${rail} must bind a frozen map of its socket's surfaces`);
88
+ }
89
+ const bound = Object.keys(surfaces).sort();
90
+ if (bound.join(',') !== [...socket].sort().join(',')) {
91
+ throw new Error(`${where}: rail ${rail} binds [${bound.join(', ')}] but its socket is [${socket.join(', ')}] — an adapter implements a rail's whole socket or binds the rail not at all`);
92
+ }
93
+ for (const [surface, fn] of Object.entries(surfaces)) {
94
+ if (typeof fn !== 'function') {
95
+ throw new Error(`${where}: ${rail}.${surface} must be a function — an unbuilt surface is left absent, never stubbed`);
96
+ }
97
+ }
98
+ }
99
+ return adapter;
100
+ }
101
+ /**
102
+ * Build the one type → adapter map, convicting every violation of
103
+ * axiom 1: an adapter claiming a type outside the alphabet, two
104
+ * adapters claiming one type, or an alphabet type left unassigned.
105
+ * Pure — callers own where the alphabet and adapters come from.
106
+ */
107
+ export function buildTypeMap(adapters, alphabet) {
108
+ const known = new Set(alphabet);
109
+ const byType = new Map();
110
+ for (const candidate of adapters) {
111
+ const adapter = assertAdapter(candidate);
112
+ for (const type of Object.keys(adapter.types)) {
113
+ if (!known.has(type)) {
114
+ throw new Error(`adapter ${adapter.name} claims ${JSON.stringify(type)}, which is not in the registry's alphabet`);
115
+ }
116
+ const holder = byType.get(type);
117
+ if (holder) {
118
+ throw new Error(`entity type ${JSON.stringify(type)} is claimed by both ${holder.name} and ${adapter.name} — one adapter per type`);
119
+ }
120
+ byType.set(type, adapter);
121
+ }
122
+ }
123
+ for (const type of known) {
124
+ if (!byType.has(type)) {
125
+ throw new Error(`entity type ${JSON.stringify(type)} has no adapter — every type is assigned`);
126
+ }
127
+ }
128
+ return byType;
129
+ }
130
+ /**
131
+ * The three-state vocabulary's one shared judgment: what a FAILED look
132
+ * at ground means. ENOENT and ENOTDIR are the filesystem itself saying
133
+ * "not there" — honest ABSENCE, a fact. Every other failure means the
134
+ * LOOK failed, not the ground — UNSETTLED: no conclusion, read again.
135
+ *
136
+ * Every truth reader classifies through this one function so no reader
137
+ * can invent its own idea of absence: mistaking "could not look" for
138
+ * "not there" is the exact lie axiom 4 forbids. Only present or absent
139
+ * may produce a conclusion.
140
+ */
141
+ export const lookFailed = (error) => error.code === 'ENOENT' || error.code === 'ENOTDIR'
142
+ ? { truth: 'absent' }
143
+ : { truth: 'unsettled', reason: error.code };
144
+ /**
145
+ * The managed-reference adapter: Amalgm's OWN link kind, never
146
+ * conflated with a filesystem symlink. Its payload is the target
147
+ * entity's UUID — identity, not an address — and its local rendering as
148
+ * an ordinary symlink is DERIVED state (entity-model.md, symlink
149
+ * section). ASSIGNED, NOT YET OPERATIONAL — and that absence is the
150
+ * honest truth: no rail is bound because the projection lives inside
151
+ * the registration boundary today; its detect socket is ratified from
152
+ * that seam when the projection is extracted, never invented ahead of
153
+ * it.
154
+ */
155
+ export const referenceAdapter = Object.freeze({
156
+ name: 'reference',
157
+ types: Object.freeze({
158
+ reference: "its target entity's UUID — identity, not an address; the rendered symlink is derived state",
159
+ }),
160
+ rails: Object.freeze({}),
161
+ });
162
+ //# sourceMappingURL=adapter-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-contract.js","sourceRoot":"","sources":["../../src/detection/adapter-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,gEAAgE;AAChE,MAAM,CAAC,MAAM,KAAK,GAAoB,MAAM,CAAC,MAAM,CAAC;IAClD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ;CAClE,CAAC,CAAC;AAuBH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,OAAO,GAAuD,MAAM,CAAC,MAAM,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;CACjC,CAAC,CAAC;AAgBH;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;QACvF,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,mCAAmC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IACjC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,oEAAoE,CAAC,CAAC;IAChG,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,0DAA0D,CAAC,CAAC;IACtF,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,IAAI,CAAE,KAA2B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,kCAAkC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzG,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAY,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,UAAU,IAAI,2FAA2F,CAAC,CAAC;QACrI,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,UAAU,IAAI,kDAAkD,CAAC,CAAC;QAC5F,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,UAAU,IAAI,WAAW,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;QAC5L,CAAC;QACD,KAAK,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrD,IAAI,OAAO,EAAE,KAAK,UAAU,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,OAAO,wEAAwE,CAAC,CAAC;YACxH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,OAAuC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,QAA2B,EAC3B,QAA0B;IAE1B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IACpD,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACzC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,CAAC,IAAI,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;YACrH,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,IAAI,QAAQ,OAAO,CAAC,IAAI,yBAAyB,CAAC,CAAC;YACtI,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAOD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,KAAiB,EACoF,EAAE,CACvG,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;IACjD,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;IACrB,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC/D,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,4FAA4F;KACxG,CAAC;IACF,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;CACzB,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Amalgm's file-type policy: which physical type a piece of file ground
3
+ * takes. Ratified by entity-model.md ("Formats live underneath the file
4
+ * types"; text versus binary is an adapter difference, never an
5
+ * identity difference).
6
+ *
7
+ * Classification is an INJECTED policy everywhere it is used — the
8
+ * registration boundary and its lenses refuse to construct without one
9
+ * — so it lives in its own file with no other job: one definition,
10
+ * replaceable whole.
11
+ *
12
+ * The rule is the oldest one there is: bytes holding a NUL are not
13
+ * text. What matters is WHERE that fact comes from. It is not read
14
+ * here. Detect's single read of a file produces its fingerprint and
15
+ * this report together, and this policy only names the type that report
16
+ * implies.
17
+ *
18
+ * That is the whole law: A FILE'S HASH AND ITS TYPE DESCRIBE THE SAME
19
+ * OBSERVED BYTES. A policy that opened the ground itself would be a
20
+ * second look — and a second look can meet different bytes, or none at
21
+ * all, leaving a record whose type contradicts the payload beside it.
22
+ * So this function takes evidence, never a path; it is total, and it
23
+ * cannot fail.
24
+ */
25
+ export type FileType = 'file.binary' | 'file.text';
26
+ /** Detect's report on the bytes it hashed — the same read as the fingerprint. */
27
+ export interface ClassifyEvidence {
28
+ readonly binary: boolean;
29
+ }
30
+ export declare function classifyFile({ binary }: ClassifyEvidence): FileType;
31
+ //# sourceMappingURL=classify.d.ts.map