@amalgm/live 0.2.26 → 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PURPOSE.md +52 -29
- package/README.md +1 -2
- package/dist/contracts/index.d.ts +0 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +0 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/detection/record-proposal.d.ts +3 -2
- package/dist/detection/record-proposal.d.ts.map +1 -1
- package/dist/detection/record-proposal.js +9 -7
- package/dist/detection/record-proposal.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/machines/index.d.ts +0 -2
- package/dist/machines/index.d.ts.map +1 -1
- package/dist/machines/index.js +0 -2
- package/dist/machines/index.js.map +1 -1
- package/dist/records/authority.d.ts +23 -0
- package/dist/records/authority.d.ts.map +1 -0
- package/dist/records/authority.js +28 -0
- package/dist/records/authority.js.map +1 -0
- package/dist/records/codec.d.ts +6 -0
- package/dist/records/codec.d.ts.map +1 -0
- package/dist/records/codec.js +42 -0
- package/dist/records/codec.js.map +1 -0
- package/dist/records/contracts.d.ts +46 -0
- package/dist/records/contracts.d.ts.map +1 -0
- package/dist/records/contracts.js +114 -0
- package/dist/records/contracts.js.map +1 -0
- package/dist/records/inbox.d.ts +18 -0
- package/dist/records/inbox.d.ts.map +1 -0
- package/dist/records/inbox.js +34 -0
- package/dist/records/inbox.js.map +1 -0
- package/dist/records/index.d.ts +7 -0
- package/dist/records/index.d.ts.map +1 -0
- package/dist/records/index.js +7 -0
- package/dist/records/index.js.map +1 -0
- package/dist/records/outbox.d.ts +20 -0
- package/dist/records/outbox.d.ts.map +1 -0
- package/dist/records/outbox.js +44 -0
- package/dist/records/outbox.js.map +1 -0
- package/dist/registration/user-ground.d.ts +5 -2
- package/dist/registration/user-ground.d.ts.map +1 -1
- package/dist/registration/user-ground.js +14 -3
- package/dist/registration/user-ground.js.map +1 -1
- package/dist/watching/suspicion.d.ts.map +1 -1
- package/dist/watching/suspicion.js +29 -1
- package/dist/watching/suspicion.js.map +1 -1
- package/dist-cjs/contracts/binding.js +26 -0
- package/dist-cjs/contracts/binding.js.map +1 -0
- package/dist-cjs/contracts/content.js +99 -0
- package/dist-cjs/contracts/content.js.map +1 -0
- package/dist-cjs/contracts/docs.js +56 -0
- package/dist-cjs/contracts/docs.js.map +1 -0
- package/dist-cjs/contracts/events.js +44 -0
- package/dist-cjs/contracts/events.js.map +1 -0
- package/dist-cjs/contracts/frames/gateway.js +39 -0
- package/dist-cjs/contracts/frames/gateway.js.map +1 -0
- package/dist-cjs/contracts/frames/stream.js +20 -0
- package/dist-cjs/contracts/frames/stream.js.map +1 -0
- package/dist-cjs/contracts/frames/tunnel.js +60 -0
- package/dist-cjs/contracts/frames/tunnel.js.map +1 -0
- package/dist-cjs/contracts/index.js +34 -0
- package/dist-cjs/contracts/index.js.map +1 -0
- package/dist-cjs/contracts/presence.js +38 -0
- package/dist-cjs/contracts/presence.js.map +1 -0
- package/dist-cjs/contracts/resources.js +114 -0
- package/dist-cjs/contracts/resources.js.map +1 -0
- package/dist-cjs/contracts/snapshot.js +31 -0
- package/dist-cjs/contracts/snapshot.js.map +1 -0
- package/dist-cjs/contracts/validate.js +34 -0
- package/dist-cjs/contracts/validate.js.map +1 -0
- package/dist-cjs/detection/adapter-contract.js +168 -0
- package/dist-cjs/detection/adapter-contract.js.map +1 -0
- package/dist-cjs/detection/batch.js +71 -0
- package/dist-cjs/detection/batch.js.map +1 -0
- package/dist-cjs/detection/classify.js +48 -0
- package/dist-cjs/detection/classify.js.map +1 -0
- package/dist-cjs/detection/content.js +122 -0
- package/dist-cjs/detection/content.js.map +1 -0
- package/dist-cjs/detection/continuity.js +88 -0
- package/dist-cjs/detection/continuity.js.map +1 -0
- package/dist-cjs/detection/diff.js +193 -0
- package/dist-cjs/detection/diff.js.map +1 -0
- package/dist-cjs/detection/echo.js +25 -0
- package/dist-cjs/detection/echo.js.map +1 -0
- package/dist-cjs/detection/enrollment.js +189 -0
- package/dist-cjs/detection/enrollment.js.map +1 -0
- package/dist-cjs/detection/index.js +57 -0
- package/dist-cjs/detection/index.js.map +1 -0
- package/dist-cjs/detection/record-proposal.js +170 -0
- package/dist-cjs/detection/record-proposal.js.map +1 -0
- package/dist-cjs/detection/refusal.js +44 -0
- package/dist-cjs/detection/refusal.js.map +1 -0
- package/dist-cjs/detection/repository.js +67 -0
- package/dist-cjs/detection/repository.js.map +1 -0
- package/dist-cjs/detection/territory.js +82 -0
- package/dist-cjs/detection/territory.js.map +1 -0
- package/dist-cjs/detection/watch-boundary.js +51 -0
- package/dist-cjs/detection/watch-boundary.js.map +1 -0
- package/dist-cjs/entities/bytes.js +92 -0
- package/dist-cjs/entities/bytes.js.map +1 -0
- package/dist-cjs/entities/cloud.js +171 -0
- package/dist-cjs/entities/cloud.js.map +1 -0
- package/dist-cjs/entities/index.js +39 -0
- package/dist-cjs/entities/index.js.map +1 -0
- package/dist-cjs/entities/moves.js +85 -0
- package/dist-cjs/entities/moves.js.map +1 -0
- package/dist-cjs/entities/repo-states.js +256 -0
- package/dist-cjs/entities/repo-states.js.map +1 -0
- package/dist-cjs/entities/rules.js +216 -0
- package/dist-cjs/entities/rules.js.map +1 -0
- package/dist-cjs/entities/types.js +44 -0
- package/dist-cjs/entities/types.js.map +1 -0
- package/dist-cjs/files/commands.js +120 -0
- package/dist-cjs/files/commands.js.map +1 -0
- package/dist-cjs/files/index.js +19 -0
- package/dist-cjs/files/index.js.map +1 -0
- package/dist-cjs/index.js +39 -0
- package/dist-cjs/index.js.map +1 -0
- package/dist-cjs/machines/arbitration.js +41 -0
- package/dist-cjs/machines/arbitration.js.map +1 -0
- package/dist-cjs/machines/backoff.js +38 -0
- package/dist-cjs/machines/backoff.js.map +1 -0
- package/dist-cjs/machines/bootstrap.js +110 -0
- package/dist-cjs/machines/bootstrap.js.map +1 -0
- package/dist-cjs/machines/chunks.js +72 -0
- package/dist-cjs/machines/chunks.js.map +1 -0
- package/dist-cjs/machines/index.js +28 -0
- package/dist-cjs/machines/index.js.map +1 -0
- package/dist-cjs/machines/presence.js +53 -0
- package/dist-cjs/machines/presence.js.map +1 -0
- package/dist-cjs/merge/index.js +25 -0
- package/dist-cjs/merge/index.js.map +1 -0
- package/dist-cjs/merge/merge3.js +191 -0
- package/dist-cjs/merge/merge3.js.map +1 -0
- package/dist-cjs/package.json +1 -0
- package/dist-cjs/records/authority.js +31 -0
- package/dist-cjs/records/authority.js.map +1 -0
- package/dist-cjs/records/codec.js +48 -0
- package/dist-cjs/records/codec.js.map +1 -0
- package/dist-cjs/records/contracts.js +121 -0
- package/dist-cjs/records/contracts.js.map +1 -0
- package/dist-cjs/records/inbox.js +37 -0
- package/dist-cjs/records/inbox.js.map +1 -0
- package/dist-cjs/records/index.js +23 -0
- package/dist-cjs/records/index.js.map +1 -0
- package/dist-cjs/records/outbox.js +48 -0
- package/dist-cjs/records/outbox.js.map +1 -0
- package/dist-cjs/registration/index.js +19 -0
- package/dist-cjs/registration/index.js.map +1 -0
- package/dist-cjs/registration/user-ground.js +183 -0
- package/dist-cjs/registration/user-ground.js.map +1 -0
- package/dist-cjs/transfer/artifacts.js +75 -0
- package/dist-cjs/transfer/artifacts.js.map +1 -0
- package/dist-cjs/transfer/batches.js +44 -0
- package/dist-cjs/transfer/batches.js.map +1 -0
- package/dist-cjs/transfer/download.js +88 -0
- package/dist-cjs/transfer/download.js.map +1 -0
- package/dist-cjs/transfer/index.js +21 -0
- package/dist-cjs/transfer/index.js.map +1 -0
- package/dist-cjs/transfer/parallel.js +35 -0
- package/dist-cjs/transfer/parallel.js.map +1 -0
- package/dist-cjs/transfer/upload.js +161 -0
- package/dist-cjs/transfer/upload.js.map +1 -0
- package/dist-cjs/watching/coverage.js +54 -0
- package/dist-cjs/watching/coverage.js.map +1 -0
- package/dist-cjs/watching/index.js +24 -0
- package/dist-cjs/watching/index.js.map +1 -0
- package/dist-cjs/watching/suspicion.js +105 -0
- package/dist-cjs/watching/suspicion.js.map +1 -0
- package/dist-cjs/workspace/api.js +66 -0
- package/dist-cjs/workspace/api.js.map +1 -0
- package/dist-cjs/workspace/identity.js +32 -0
- package/dist-cjs/workspace/identity.js.map +1 -0
- package/dist-cjs/workspace/index.js +14 -0
- package/dist-cjs/workspace/index.js.map +1 -0
- package/dist-cjs/workspace/memory-store.js +21 -0
- package/dist-cjs/workspace/memory-store.js.map +1 -0
- package/dist-cjs/workspace/registry.js +98 -0
- package/dist-cjs/workspace/registry.js.map +1 -0
- package/dist-cjs/workspace/types.js +3 -0
- package/dist-cjs/workspace/types.js.map +1 -0
- package/package.json +30 -8
- package/dist/contracts/mutation.d.ts +0 -51
- package/dist/contracts/mutation.d.ts.map +0 -1
- package/dist/contracts/mutation.js +0 -55
- package/dist/contracts/mutation.js.map +0 -1
- package/dist/machines/journal.d.ts +0 -63
- package/dist/machines/journal.d.ts.map +0 -1
- package/dist/machines/journal.js +0 -71
- package/dist/machines/journal.js.map +0 -1
- package/dist/machines/ordering.d.ts +0 -53
- package/dist/machines/ordering.d.ts.map +0 -1
- package/dist/machines/ordering.js +0 -87
- package/dist/machines/ordering.js.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The adapter contract: what it means to serve an entity type.
|
|
4
|
+
*
|
|
5
|
+
* An adapter is how a KIND of entity rides the seven realtime rails —
|
|
6
|
+
* watch, detect, record, send, receive, apply, verify. The entity's
|
|
7
|
+
* `type` selects its adapter; the rails themselves never change shape
|
|
8
|
+
* per type. Ratified by entity-model.md ("Type selects the complete
|
|
9
|
+
* adapter cycle") and entity-implementation.md.
|
|
10
|
+
*
|
|
11
|
+
* Axioms:
|
|
12
|
+
*
|
|
13
|
+
* 1. ONE ADAPTER PER TYPE, EVERY TYPE ASSIGNED. The alphabet belongs
|
|
14
|
+
* to the registry; the adapter map covers it exactly — no type
|
|
15
|
+
* unassigned, no type claimed twice. Assigned is not yet
|
|
16
|
+
* operational: operational is earned rail by rail, and absence is
|
|
17
|
+
* honest.
|
|
18
|
+
* 2. ADAPTERS OWN BEHAVIOR; THE REGISTRY OWNS IDENTITY. A lawful type
|
|
19
|
+
* transition that crosses adapters is a handoff on the same UUID,
|
|
20
|
+
* never a rebirth.
|
|
21
|
+
* 3. ONE SOCKET PER RAIL. A rail's callable surfaces are ratified
|
|
22
|
+
* HERE, once, for every adapter (`SOCKETS`). An adapter binds a
|
|
23
|
+
* rail's whole socket or binds the rail not at all; a rail whose
|
|
24
|
+
* socket is not yet ratified cannot be bound by anyone.
|
|
25
|
+
* 4. A TRUTH READ NEVER LIES. Every assigned type names its source of
|
|
26
|
+
* truth in one sentence, and reading it produces exactly one of
|
|
27
|
+
* three honest answers: present, absent, or unsettled.
|
|
28
|
+
* 5. RAILS ARE HONEST. An unbound rail is absent — never stubbed,
|
|
29
|
+
* never defaulted.
|
|
30
|
+
* 6. THE CONTRACT IS FROZEN GROUND. A descriptor is immutable from
|
|
31
|
+
* the moment it loads.
|
|
32
|
+
* 7. THE BASE ORCHESTRATES; THE ADAPTER SUPPLIES TYPE BEHAVIOR. A
|
|
33
|
+
* rail earns a socket only when a real consumer proves that
|
|
34
|
+
* behavior differs by type — never for symmetry.
|
|
35
|
+
*/
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.referenceAdapter = exports.lookFailed = exports.SOCKETS = exports.RAILS = void 0;
|
|
38
|
+
exports.assertAdapter = assertAdapter;
|
|
39
|
+
exports.buildTypeMap = buildTypeMap;
|
|
40
|
+
/** The seven rails, declared once, frozen, in journey order. */
|
|
41
|
+
exports.RAILS = Object.freeze([
|
|
42
|
+
'watch', 'detect', 'record', 'send', 'receive', 'apply', 'verify',
|
|
43
|
+
]);
|
|
44
|
+
/**
|
|
45
|
+
* The ratified sockets — for each rail that has one, the exact surfaces
|
|
46
|
+
* every binding adapter implements. Same names, same shapes, every
|
|
47
|
+
* type. ONE socket is ratified today (detect), derived from what
|
|
48
|
+
* production detection actually asks of a type. Watch and record earn
|
|
49
|
+
* none at this bar (adjudicated 2026-08-03 under axiom 7); apply and
|
|
50
|
+
* verify join only when the Send/Receive rails exist to derive their
|
|
51
|
+
* socket from. A socket is ratified from a real consumer or it is not
|
|
52
|
+
* ratified at all.
|
|
53
|
+
*/
|
|
54
|
+
exports.SOCKETS = Object.freeze({
|
|
55
|
+
detect: Object.freeze(['truth']),
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* Convict a malformed adapter descriptor loudly; return it (typed)
|
|
59
|
+
* unchanged when lawful.
|
|
60
|
+
*/
|
|
61
|
+
function assertAdapter(adapter) {
|
|
62
|
+
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
63
|
+
const where = isRecord(adapter) && typeof adapter['name'] === 'string' && adapter['name']
|
|
64
|
+
? `adapter ${JSON.stringify(adapter['name'])}` : 'adapter';
|
|
65
|
+
if (!isRecord(adapter) || !Object.isFrozen(adapter)) {
|
|
66
|
+
throw new Error(`${where}: a descriptor is a frozen object`);
|
|
67
|
+
}
|
|
68
|
+
if (typeof adapter['name'] !== 'string' || adapter['name'].length === 0) {
|
|
69
|
+
throw new Error('adapter: name is a non-empty string');
|
|
70
|
+
}
|
|
71
|
+
const { types, rails } = adapter;
|
|
72
|
+
if (!isRecord(types) || !Object.isFrozen(types) || Object.keys(types).length === 0) {
|
|
73
|
+
throw new Error(`${where}: types is a frozen, non-empty map of entity type → declared truth`);
|
|
74
|
+
}
|
|
75
|
+
for (const [type, truth] of Object.entries(types)) {
|
|
76
|
+
if (typeof truth !== 'string' || truth.length === 0) {
|
|
77
|
+
throw new Error(`${where}: type ${JSON.stringify(type)} must declare its source of truth in one sentence`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!isRecord(rails) || !Object.isFrozen(rails)) {
|
|
81
|
+
throw new Error(`${where}: rails is a frozen map (empty is honest; a stub is not)`);
|
|
82
|
+
}
|
|
83
|
+
for (const [rail, surfaces] of Object.entries(rails)) {
|
|
84
|
+
if (!exports.RAILS.includes(rail)) {
|
|
85
|
+
throw new Error(`${where}: ${JSON.stringify(rail)} is not a rail — the rails are ${exports.RAILS.join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
const socket = exports.SOCKETS[rail];
|
|
88
|
+
if (!socket) {
|
|
89
|
+
throw new Error(`${where}: rail ${rail} has no ratified socket yet — a socket is ratified in the contract before anyone binds it`);
|
|
90
|
+
}
|
|
91
|
+
if (!isRecord(surfaces) || !Object.isFrozen(surfaces)) {
|
|
92
|
+
throw new Error(`${where}: rail ${rail} must bind a frozen map of its socket's surfaces`);
|
|
93
|
+
}
|
|
94
|
+
const bound = Object.keys(surfaces).sort();
|
|
95
|
+
if (bound.join(',') !== [...socket].sort().join(',')) {
|
|
96
|
+
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`);
|
|
97
|
+
}
|
|
98
|
+
for (const [surface, fn] of Object.entries(surfaces)) {
|
|
99
|
+
if (typeof fn !== 'function') {
|
|
100
|
+
throw new Error(`${where}: ${rail}.${surface} must be a function — an unbuilt surface is left absent, never stubbed`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return adapter;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build the one type → adapter map, convicting every violation of
|
|
108
|
+
* axiom 1: an adapter claiming a type outside the alphabet, two
|
|
109
|
+
* adapters claiming one type, or an alphabet type left unassigned.
|
|
110
|
+
* Pure — callers own where the alphabet and adapters come from.
|
|
111
|
+
*/
|
|
112
|
+
function buildTypeMap(adapters, alphabet) {
|
|
113
|
+
const known = new Set(alphabet);
|
|
114
|
+
const byType = new Map();
|
|
115
|
+
for (const candidate of adapters) {
|
|
116
|
+
const adapter = assertAdapter(candidate);
|
|
117
|
+
for (const type of Object.keys(adapter.types)) {
|
|
118
|
+
if (!known.has(type)) {
|
|
119
|
+
throw new Error(`adapter ${adapter.name} claims ${JSON.stringify(type)}, which is not in the registry's alphabet`);
|
|
120
|
+
}
|
|
121
|
+
const holder = byType.get(type);
|
|
122
|
+
if (holder) {
|
|
123
|
+
throw new Error(`entity type ${JSON.stringify(type)} is claimed by both ${holder.name} and ${adapter.name} — one adapter per type`);
|
|
124
|
+
}
|
|
125
|
+
byType.set(type, adapter);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
for (const type of known) {
|
|
129
|
+
if (!byType.has(type)) {
|
|
130
|
+
throw new Error(`entity type ${JSON.stringify(type)} has no adapter — every type is assigned`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return byType;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The three-state vocabulary's one shared judgment: what a FAILED look
|
|
137
|
+
* at ground means. ENOENT and ENOTDIR are the filesystem itself saying
|
|
138
|
+
* "not there" — honest ABSENCE, a fact. Every other failure means the
|
|
139
|
+
* LOOK failed, not the ground — UNSETTLED: no conclusion, read again.
|
|
140
|
+
*
|
|
141
|
+
* Every truth reader classifies through this one function so no reader
|
|
142
|
+
* can invent its own idea of absence: mistaking "could not look" for
|
|
143
|
+
* "not there" is the exact lie axiom 4 forbids. Only present or absent
|
|
144
|
+
* may produce a conclusion.
|
|
145
|
+
*/
|
|
146
|
+
const lookFailed = (error) => error.code === 'ENOENT' || error.code === 'ENOTDIR'
|
|
147
|
+
? { truth: 'absent' }
|
|
148
|
+
: { truth: 'unsettled', reason: error.code };
|
|
149
|
+
exports.lookFailed = lookFailed;
|
|
150
|
+
/**
|
|
151
|
+
* The managed-reference adapter: Amalgm's OWN link kind, never
|
|
152
|
+
* conflated with a filesystem symlink. Its payload is the target
|
|
153
|
+
* entity's UUID — identity, not an address — and its local rendering as
|
|
154
|
+
* an ordinary symlink is DERIVED state (entity-model.md, symlink
|
|
155
|
+
* section). ASSIGNED, NOT YET OPERATIONAL — and that absence is the
|
|
156
|
+
* honest truth: no rail is bound because the projection lives inside
|
|
157
|
+
* the registration boundary today; its detect socket is ratified from
|
|
158
|
+
* that seam when the projection is extracted, never invented ahead of
|
|
159
|
+
* it.
|
|
160
|
+
*/
|
|
161
|
+
exports.referenceAdapter = Object.freeze({
|
|
162
|
+
name: 'reference',
|
|
163
|
+
types: Object.freeze({
|
|
164
|
+
reference: "its target entity's UUID — identity, not an address; the rendered symlink is derived state",
|
|
165
|
+
}),
|
|
166
|
+
rails: Object.freeze({}),
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=adapter-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-contract.js","sourceRoot":"","sources":["../../src/detection/adapter-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Net-difference planning for one settled Watch batch.
|
|
4
|
+
*
|
|
5
|
+
* Identity reconciliation and type-specific capture happen before this seam.
|
|
6
|
+
* This seam makes cancellation, unsettled truth, lifecycle authority, coverage
|
|
7
|
+
* requests, and Watch settlement one total decision.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.planDetectionBatch = planDetectionBatch;
|
|
11
|
+
const types_js_1 = require("../entities/types.js");
|
|
12
|
+
const record_proposal_js_1 = require("./record-proposal.js");
|
|
13
|
+
const watch_boundary_js_1 = require("./watch-boundary.js");
|
|
14
|
+
const newlyDirectoryGround = (transition) => transition.relPath !== ''
|
|
15
|
+
&&
|
|
16
|
+
types_js_1.CONTAINERS.has(transition.result.type)
|
|
17
|
+
&& (transition.base === null || !types_js_1.CONTAINERS.has(transition.base.type));
|
|
18
|
+
/** Plan the complete net difference. No partial proposals escape an unsettled batch. */
|
|
19
|
+
function planDetectionBatch(batch, transitions) {
|
|
20
|
+
const unsettled = transitions.filter((transition) => transition.truth === 'unsettled');
|
|
21
|
+
if (unsettled.length > 0) {
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
kind: 'retry',
|
|
24
|
+
reasons: Object.freeze(unsettled.map((transition) => transition.reason ?? 'truth is unsettled')),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const proposals = [];
|
|
28
|
+
const missing = [];
|
|
29
|
+
const createdDirectories = [];
|
|
30
|
+
for (const transition of transitions) {
|
|
31
|
+
if (transition.truth === 'present') {
|
|
32
|
+
const proposal = (0, record_proposal_js_1.detectedChangeProposal)(transition);
|
|
33
|
+
if (proposal)
|
|
34
|
+
proposals.push(proposal);
|
|
35
|
+
if (newlyDirectoryGround(transition)) {
|
|
36
|
+
createdDirectories.push(transition.relPath);
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (transition.truth !== 'absent') {
|
|
41
|
+
throw new Error('unsettled truth escaped the batch retry gate');
|
|
42
|
+
}
|
|
43
|
+
if (transition.base === null)
|
|
44
|
+
continue; // absent before and after: no entity existed
|
|
45
|
+
if (transition.base.status !== 'active')
|
|
46
|
+
continue;
|
|
47
|
+
if (transition.lifecycleAuthorization !== 'trash') {
|
|
48
|
+
missing.push(transition.base);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!transition.trashedResult) {
|
|
52
|
+
throw new Error('authorized Trash requires the entity law\'s exact trashed result');
|
|
53
|
+
}
|
|
54
|
+
const proposal = (0, record_proposal_js_1.detectedChangeProposal)({
|
|
55
|
+
base: transition.base,
|
|
56
|
+
result: transition.trashedResult,
|
|
57
|
+
replay: { kind: 'structure' },
|
|
58
|
+
lifecycleAuthorization: 'trash',
|
|
59
|
+
});
|
|
60
|
+
if (proposal)
|
|
61
|
+
proposals.push(proposal);
|
|
62
|
+
}
|
|
63
|
+
return Object.freeze({
|
|
64
|
+
kind: 'ready',
|
|
65
|
+
proposals: Object.freeze(proposals),
|
|
66
|
+
missing: Object.freeze(missing),
|
|
67
|
+
coverage: (0, watch_boundary_js_1.directoryCoverageRequests)(batch, createdDirectories),
|
|
68
|
+
settle: batch,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/detection/batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Amalgm's file-type policy: which physical type a piece of file ground
|
|
4
|
+
* takes. Ratified by entity-model.md ("Formats live underneath the file
|
|
5
|
+
* types"; text versus binary is an adapter difference, never an
|
|
6
|
+
* identity difference).
|
|
7
|
+
*
|
|
8
|
+
* Classification is an INJECTED policy everywhere it is used — the
|
|
9
|
+
* registration boundary and its lenses refuse to construct without one
|
|
10
|
+
* — so it lives in its own file with no other job: one definition,
|
|
11
|
+
* replaceable whole.
|
|
12
|
+
*
|
|
13
|
+
* The rule is the oldest one there is: bytes holding a NUL are not
|
|
14
|
+
* text. What matters is WHERE that fact comes from. It is not read
|
|
15
|
+
* here. Detect's single read of a file produces its fingerprint and
|
|
16
|
+
* this report together, and this policy only names the type that report
|
|
17
|
+
* implies.
|
|
18
|
+
*
|
|
19
|
+
* That is the whole law: A FILE'S HASH AND ITS TYPE DESCRIBE THE SAME
|
|
20
|
+
* OBSERVED BYTES. A policy that opened the ground itself would be a
|
|
21
|
+
* second look — and a second look can meet different bytes, or none at
|
|
22
|
+
* all, leaving a record whose type contradicts the payload beside it.
|
|
23
|
+
* So this function takes evidence, never a path; it is total, and it
|
|
24
|
+
* cannot fail.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.classifyFile = classifyFile;
|
|
28
|
+
exports.classifyDirectory = classifyDirectory;
|
|
29
|
+
exports.classifyRegisteredRoot = classifyRegisteredRoot;
|
|
30
|
+
exports.isRepositoryMetadataEntry = isRepositoryMetadataEntry;
|
|
31
|
+
function classifyFile({ binary }) {
|
|
32
|
+
return binary ? 'file.binary' : 'file.text';
|
|
33
|
+
}
|
|
34
|
+
function classifyDirectory({ repository }) {
|
|
35
|
+
return repository ? 'repo.git' : 'folder';
|
|
36
|
+
}
|
|
37
|
+
/** A deliberately registered external directory remains a tree root. A Git
|
|
38
|
+
* root wears `repo.git`; an ordinary root wears `workspace`. */
|
|
39
|
+
function classifyRegisteredRoot({ repository }) {
|
|
40
|
+
return repository ? 'repo.git' : 'workspace';
|
|
41
|
+
}
|
|
42
|
+
/** `.git` is cargo of a repository entity, never one of its worktree
|
|
43
|
+
* children. Marker presence makes the parent a repository before this rule is
|
|
44
|
+
* asked, regardless of whether Git can currently consume that marker. */
|
|
45
|
+
function isRepositoryMetadataEntry(parentType, name) {
|
|
46
|
+
return parentType === 'repo.git' && name === '.git';
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/detection/classify.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;AAWH,oCAEC;AASD,8CAEC;AAID,wDAEC;AAKD,8DAEC;AA1BD,SAAgB,YAAY,CAAC,EAAE,MAAM,EAAoB;IACvD,OAAO,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;AAC9C,CAAC;AASD,SAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAsB;IAClE,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC5C,CAAC;AAED;gEACgE;AAChE,SAAgB,sBAAsB,CAAC,EAAE,UAAU,EAAsB;IACvE,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED;;yEAEyE;AACzE,SAAgB,yBAAyB,CAAC,UAA8C,EAAE,IAAY;IACpG,OAAO,UAAU,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Type-sensitive content capture from Detection's one settled byte read. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.textSplice = textSplice;
|
|
5
|
+
exports.captureTextChange = captureTextChange;
|
|
6
|
+
exports.reproduceTextChange = reproduceTextChange;
|
|
7
|
+
exports.captureBinaryChange = captureBinaryChange;
|
|
8
|
+
exports.captureLinkChange = captureLinkChange;
|
|
9
|
+
const content_js_1 = require("../contracts/content.js");
|
|
10
|
+
const bytes_js_1 = require("../entities/bytes.js");
|
|
11
|
+
const upload_js_1 = require("../transfer/upload.js");
|
|
12
|
+
const capturedArtifact = (entityId, entityType, kind, input, sha256Hex) => {
|
|
13
|
+
const bytes = input.slice();
|
|
14
|
+
const artifact = {
|
|
15
|
+
entityId,
|
|
16
|
+
entityType,
|
|
17
|
+
kind,
|
|
18
|
+
contentHash: sha256Hex(bytes),
|
|
19
|
+
};
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
artifact: Object.freeze(artifact),
|
|
22
|
+
bytes,
|
|
23
|
+
manifest: (0, upload_js_1.deriveUploadManifest)(artifact, bytes, sha256Hex),
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
/** The smallest single replacement span that transforms base bytes to result. */
|
|
27
|
+
function textSplice(base, result) {
|
|
28
|
+
let prefix = 0;
|
|
29
|
+
const shared = Math.min(base.byteLength, result.byteLength);
|
|
30
|
+
while (prefix < shared && base[prefix] === result[prefix])
|
|
31
|
+
prefix += 1;
|
|
32
|
+
let suffix = 0;
|
|
33
|
+
while (suffix < shared - prefix
|
|
34
|
+
&& base[base.byteLength - suffix - 1] === result[result.byteLength - suffix - 1]) {
|
|
35
|
+
suffix += 1;
|
|
36
|
+
}
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
offset: prefix,
|
|
39
|
+
deleteBytes: base.byteLength - prefix - suffix,
|
|
40
|
+
insert: result.slice(prefix, result.byteLength - suffix),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Capture text as one verified byte splice when that instruction is smaller
|
|
45
|
+
* than the result bytes. The immutable snapshot is always sealed as repair and
|
|
46
|
+
* cold-materialization truth.
|
|
47
|
+
*/
|
|
48
|
+
function captureTextChange(entityId, base, result, sha256Hex) {
|
|
49
|
+
const cargo = capturedArtifact(entityId, 'file.text', 'file', result, sha256Hex);
|
|
50
|
+
const basePayloadVersion = base === null ? null : sha256Hex(base);
|
|
51
|
+
if (basePayloadVersion === cargo.artifact.contentHash)
|
|
52
|
+
return null;
|
|
53
|
+
const delta = base === null ? null : textSplice(base, result);
|
|
54
|
+
// Two numeric fields are fixed overhead on the wire. This conservative
|
|
55
|
+
// estimate keeps a replace-all operation on the snapshot path.
|
|
56
|
+
const useDelta = delta !== null && delta.insert.byteLength + 16 < result.byteLength;
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
replay: Object.freeze({
|
|
59
|
+
kind: 'file.text',
|
|
60
|
+
mode: useDelta ? 'delta' : 'snapshot',
|
|
61
|
+
basePayloadVersion,
|
|
62
|
+
resultPayloadVersion: cargo.artifact.contentHash,
|
|
63
|
+
delta: useDelta ? delta : null,
|
|
64
|
+
}),
|
|
65
|
+
cargo,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Apply a text replay and verify its exact result, falling back to snapshot. */
|
|
69
|
+
function reproduceTextChange(base, replay, snapshot, sha256Hex) {
|
|
70
|
+
const verifiedSnapshot = () => {
|
|
71
|
+
if (sha256Hex(snapshot) !== replay.resultPayloadVersion) {
|
|
72
|
+
throw new Error('text snapshot does not match its declared result');
|
|
73
|
+
}
|
|
74
|
+
return snapshot.slice();
|
|
75
|
+
};
|
|
76
|
+
if (replay.mode !== 'delta' || replay.delta === null || base === null
|
|
77
|
+
|| sha256Hex(base) !== replay.basePayloadVersion) {
|
|
78
|
+
return verifiedSnapshot();
|
|
79
|
+
}
|
|
80
|
+
const { offset, deleteBytes, insert } = replay.delta;
|
|
81
|
+
if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(deleteBytes)
|
|
82
|
+
|| offset < 0 || deleteBytes < 0 || offset + deleteBytes > base.byteLength) {
|
|
83
|
+
return verifiedSnapshot();
|
|
84
|
+
}
|
|
85
|
+
const result = new Uint8Array(base.byteLength - deleteBytes + insert.byteLength);
|
|
86
|
+
result.set(base.subarray(0, offset), 0);
|
|
87
|
+
result.set(insert, offset);
|
|
88
|
+
result.set(base.subarray(offset + deleteBytes), offset + insert.byteLength);
|
|
89
|
+
return sha256Hex(result) === replay.resultPayloadVersion ? result : verifiedSnapshot();
|
|
90
|
+
}
|
|
91
|
+
/** Binary replay is the existing exact content manifest; Transfer moves gaps. */
|
|
92
|
+
function captureBinaryChange(entityId, previous, result, sha256Hex) {
|
|
93
|
+
if (previous !== null && !(0, content_js_1.checkContentManifest)(previous).ok) {
|
|
94
|
+
throw new Error('previous binary content manifest is invalid');
|
|
95
|
+
}
|
|
96
|
+
const cargo = capturedArtifact(entityId, 'file.binary', 'file', result, sha256Hex);
|
|
97
|
+
if (previous?.contentHash === cargo.artifact.contentHash)
|
|
98
|
+
return null;
|
|
99
|
+
return Object.freeze({
|
|
100
|
+
replay: Object.freeze({
|
|
101
|
+
kind: 'file.binary',
|
|
102
|
+
resultPayloadVersion: cargo.artifact.contentHash,
|
|
103
|
+
manifest: cargo.manifest,
|
|
104
|
+
}),
|
|
105
|
+
cargo,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** A symlink's portable content is the literal target text, never its target. */
|
|
109
|
+
function captureLinkChange(entityId, previousTarget, target, sha256Hex) {
|
|
110
|
+
if (previousTarget === target)
|
|
111
|
+
return null;
|
|
112
|
+
const cargo = capturedArtifact(entityId, 'link', 'link', (0, bytes_js_1.utf8Encode)(target), sha256Hex);
|
|
113
|
+
return Object.freeze({
|
|
114
|
+
replay: Object.freeze({
|
|
115
|
+
kind: 'link',
|
|
116
|
+
resultPayloadVersion: cargo.artifact.contentHash,
|
|
117
|
+
target,
|
|
118
|
+
}),
|
|
119
|
+
cargo,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/detection/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Root continuity verdicts: what a root's WITNESSED physical identity
|
|
4
|
+
* is, whether its recorded address still holds its ground, and whether
|
|
5
|
+
* a piece of ground rescues a moved root. Ratified by entity-model.md
|
|
6
|
+
* ("Ground that moves is rescued by continuity" — the directory law
|
|
7
|
+
* lifted to roots; "the follow rides witnessed continuity, never
|
|
8
|
+
* clairvoyance").
|
|
9
|
+
*
|
|
10
|
+
* Pure verdicts over injected answers — the host supplies the one look
|
|
11
|
+
* at an address (`statAt`) and the store's witnessed channel row
|
|
12
|
+
* (`channelIdentity`); the ACTIONS a verdict triggers (rebind, presence
|
|
13
|
+
* transitions, the undecided-address decision) stay in the host's
|
|
14
|
+
* wiring, because they re-aim watchers and scans.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createContinuity = createContinuity;
|
|
18
|
+
function createContinuity({ statAt, channelIdentity }) {
|
|
19
|
+
/**
|
|
20
|
+
* A root's WITNESSED physical identity, for continuity rescue.
|
|
21
|
+
* Directory roots carry their own device:inode (nothing replaces a
|
|
22
|
+
* directory's inode in place). A single-ground root's identity lives
|
|
23
|
+
* in its one channel row. Ground that changed inodes inside a
|
|
24
|
+
* still-open settle window is unwitnessed — no evidence, no claim.
|
|
25
|
+
*/
|
|
26
|
+
function rootIdentity(root) {
|
|
27
|
+
if (root.kind !== 'file') {
|
|
28
|
+
const { device, inode } = root;
|
|
29
|
+
return device == null || inode == null ? null : { device, inode };
|
|
30
|
+
}
|
|
31
|
+
return channelIdentity(root.rootId);
|
|
32
|
+
}
|
|
33
|
+
/** Orphaned means the recorded address no longer holds this ground. */
|
|
34
|
+
function orphanedAtAddress(root) {
|
|
35
|
+
const identity = rootIdentity(root);
|
|
36
|
+
if (!identity)
|
|
37
|
+
return false;
|
|
38
|
+
const stat = statAt(root.path);
|
|
39
|
+
if (!stat)
|
|
40
|
+
return true;
|
|
41
|
+
return stat.device !== identity.device || stat.inode !== identity.inode;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Continuity claims a root exactly like it claims the directories
|
|
45
|
+
* inside one: unique device:inode match, exactly one candidate, and
|
|
46
|
+
* only for a path-orphan — a root whose recorded address still holds
|
|
47
|
+
* its ground is never stolen by a lookalike.
|
|
48
|
+
*/
|
|
49
|
+
function findMovedRoot(stat, roots) {
|
|
50
|
+
const wantDir = stat.kind === 'dir';
|
|
51
|
+
const matches = roots.filter((root) => {
|
|
52
|
+
if (wantDir !== (root.kind !== 'file'))
|
|
53
|
+
return false;
|
|
54
|
+
const identity = rootIdentity(root);
|
|
55
|
+
return identity !== null && identity.device === stat.device && identity.inode === stat.inode;
|
|
56
|
+
});
|
|
57
|
+
const only = matches.length === 1 ? matches[0] : null;
|
|
58
|
+
return only && orphanedAtAddress(only) ? only : null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A scan's evidence horizon is the root's ground; the root's own
|
|
62
|
+
* address is the horizon's edge. Ground missing there — or a
|
|
63
|
+
* directory root's address wearing a different physical identity — is
|
|
64
|
+
* UNDECIDABLE from here: moved away, deleted, or replaced by a
|
|
65
|
+
* lookalike all present the same address, and concluding "deleted"
|
|
66
|
+
* would end every channel a rescue could have saved. So the scan
|
|
67
|
+
* concludes nothing: beliefs freeze, the referee convicts the
|
|
68
|
+
* divergence, and the next enrollment moment decides — naming the new
|
|
69
|
+
* address rescues, re-naming this one adopts, and explicit removal is
|
|
70
|
+
* the only deletion (an external filesystem change is never
|
|
71
|
+
* permission to end identity). A single-ground root's address
|
|
72
|
+
* lawfully churns inodes (atomic saves, retargets), so only absence —
|
|
73
|
+
* or foreign directory ground — freezes it; presence is the file
|
|
74
|
+
* laws' business.
|
|
75
|
+
*/
|
|
76
|
+
function addressUndecided(root) {
|
|
77
|
+
const stat = statAt(root.path);
|
|
78
|
+
if (!stat)
|
|
79
|
+
return true;
|
|
80
|
+
if (root.kind === 'file')
|
|
81
|
+
return stat.kind !== 'file' && stat.kind !== 'link';
|
|
82
|
+
if (stat.kind !== 'dir')
|
|
83
|
+
return true;
|
|
84
|
+
return root.device != null && (stat.device !== root.device || stat.inode !== root.inode);
|
|
85
|
+
}
|
|
86
|
+
return { rootIdentity, findMovedRoot, addressUndecided };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=continuity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity.js","sourceRoot":"","sources":["../../src/detection/continuity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AA8CH,4CAmEC;AAnED,SAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,eAAe,EAAmB;IAC3E;;;;;;OAMG;IACH,SAAS,YAAY,CAAC,IAAoB;QACxC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YAC/B,OAAO,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACpE,CAAC;QACD,OAAO,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,uEAAuE;IACvE,SAAS,iBAAiB,CAAC,IAAoB;QAC7C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC;IAC1E,CAAC;IAED;;;;;OAKG;IACH,SAAS,aAAa,CAAC,IAAgB,EAAE,KAAgC;QACvE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YACpC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAC;YACrD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC;QAC/F,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,OAAO,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,SAAS,gBAAgB,CAAC,IAAoB;QAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;QAC9E,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC;AAC3D,CAAC"}
|