@llblab/pi-kit 0.37.1 → 0.38.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.
- package/CHANGELOG.md +5 -0
- package/README.md +2 -2
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +7 -3
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +679 -2
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +17 -0
- package/node_modules/@llblab/pi-state-flow/README.md +30 -14
- package/node_modules/@llblab/pi-state-flow/api/modules.ts +11 -0
- package/node_modules/@llblab/pi-state-flow/dist/api/modules.d.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/api/modules.js +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +7 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +77 -36
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.js +26 -27
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +13 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +27 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +144 -46
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +14 -18
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +6 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +60 -50
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +1049 -310
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +4 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +15 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/memory.d.ts +3 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/memory.js +7 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +29 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +186 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/model-interface.d.ts +17 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/model-interface.js +158 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/module-registry.d.ts +21 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/module-registry.js +108 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/operation.js +3 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.d.ts +4 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/ownership.js +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/planes.d.ts +29 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/planes.js +84 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +6 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +33 -16
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +21 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +53 -13
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +5 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.d.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.js +10 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +84 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +570 -20
- package/node_modules/@llblab/pi-state-flow/dist/lib/selection.d.ts +10 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/selection.js +32 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/semantic-module.d.ts +79 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/semantic-module.js +187 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +98 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +398 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/skills.d.ts +7 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/skills.js +55 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +67 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +129 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +26 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +61 -19
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +14 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +59 -22
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +111 -10
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +728 -11
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +10 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +50 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +40 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +247 -43
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +41 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +132 -39
- package/node_modules/@llblab/pi-state-flow/dist/package.json +6 -1
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +28 -16
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +12 -8
- package/node_modules/@llblab/pi-state-flow/docs/README.md +9 -0
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +76 -43
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +9 -1
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +6 -0
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +23 -19
- package/node_modules/@llblab/pi-state-flow/docs/protocol-composition-decision.md +66 -0
- package/node_modules/@llblab/pi-state-flow/docs/public-module-contract.md +73 -0
- package/node_modules/@llblab/pi-state-flow/docs/scope-selection-contract.md +814 -0
- package/node_modules/@llblab/pi-state-flow/docs/semantic-compatibility-decision.md +212 -0
- package/node_modules/@llblab/pi-state-flow/docs/semantic-extensibility-decision.md +75 -0
- package/node_modules/@llblab/pi-state-flow/docs/semantic-handoff-contract.md +174 -0
- package/node_modules/@llblab/pi-state-flow/docs/semantic-memory-evaluation.md +166 -0
- package/node_modules/@llblab/pi-state-flow/docs/semantic-module-contract.md +84 -0
- package/node_modules/@llblab/pi-state-flow/docs/single-scope-interface-contract.md +201 -0
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +22 -1
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +32 -18
- package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +68 -31
- package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +21 -22
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +14 -1
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +142 -46
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +14 -17
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +53 -44
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +897 -297
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +16 -7
- package/node_modules/@llblab/pi-state-flow/lib/json.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/lib/memory.ts +10 -9
- package/node_modules/@llblab/pi-state-flow/lib/migration.ts +189 -0
- package/node_modules/@llblab/pi-state-flow/lib/model-interface.ts +136 -0
- package/node_modules/@llblab/pi-state-flow/lib/module-registry.ts +119 -0
- package/node_modules/@llblab/pi-state-flow/lib/operation.ts +3 -2
- package/node_modules/@llblab/pi-state-flow/lib/ownership.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/lib/planes.ts +98 -0
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +37 -16
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +59 -18
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +5 -2
- package/node_modules/@llblab/pi-state-flow/lib/rehydration.ts +10 -1
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +574 -21
- package/node_modules/@llblab/pi-state-flow/lib/selection.ts +39 -0
- package/node_modules/@llblab/pi-state-flow/lib/semantic-module.ts +239 -0
- package/node_modules/@llblab/pi-state-flow/lib/session.ts +387 -3
- package/node_modules/@llblab/pi-state-flow/lib/skills.ts +45 -4
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +156 -16
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +69 -28
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +65 -31
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +770 -18
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +58 -20
- package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +267 -50
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +184 -52
- package/node_modules/@llblab/pi-state-flow/package.json +6 -1
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +28 -16
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +12 -8
- package/package.json +2 -2
|
@@ -1,7 +1,44 @@
|
|
|
1
|
+
import { captureScopeSelection } from "./selection.js";
|
|
1
2
|
import { DEFAULT_HISTORY_LIMIT, MAX_HISTORY_LIMIT, validateRecentTransition } from "./history.js";
|
|
2
3
|
import { applyPatch, containsNull, isJsonValue, isObject, sameJson } from "./json.js";
|
|
3
|
-
import {
|
|
4
|
+
import { validateRetainedModules } from "./semantic-module.js";
|
|
5
|
+
import { validateExternalPlanes, emptyState, isSemanticState, overlayStates, projectSemanticState } from "./state.js";
|
|
4
6
|
const SCOPES = ["global", "cwd", "session"];
|
|
7
|
+
function selected(view) {
|
|
8
|
+
return Object.hasOwn(view, "selection");
|
|
9
|
+
}
|
|
10
|
+
function owners(view) {
|
|
11
|
+
return selected(view) ? view.selection : SCOPES;
|
|
12
|
+
}
|
|
13
|
+
function matchesOwnerKeys(value, selection) {
|
|
14
|
+
return isObject(value) && Object.keys(value).sort().join(",") === [...selection].sort().join(",");
|
|
15
|
+
}
|
|
16
|
+
function streamFor(view, scope) {
|
|
17
|
+
const stream = view.scopes[scope];
|
|
18
|
+
if (!stream)
|
|
19
|
+
throw new Error(`State Flow ${scope} scope is excluded or unavailable`);
|
|
20
|
+
return stream;
|
|
21
|
+
}
|
|
22
|
+
function validateCohort(view, historyLimit) {
|
|
23
|
+
if (selected(view))
|
|
24
|
+
validateSelectedTemporalState(view, historyLimit);
|
|
25
|
+
else
|
|
26
|
+
validateTemporalState(view, historyLimit);
|
|
27
|
+
}
|
|
28
|
+
function cloneCohort(view) {
|
|
29
|
+
const next = structuredClone(view);
|
|
30
|
+
if (selected(next))
|
|
31
|
+
next.selection = captureScopeSelection(next.selection);
|
|
32
|
+
return next;
|
|
33
|
+
}
|
|
34
|
+
function trimCausalBasis(view) {
|
|
35
|
+
if (!selected(view))
|
|
36
|
+
return;
|
|
37
|
+
const retained = new Set(view.lineage.slice(1).map((boundary) => boundary.id));
|
|
38
|
+
view.causalBasis = view.causalBasis.filter((witness) => retained.has(witness.transition.id));
|
|
39
|
+
for (const witness of view.causalBasis)
|
|
40
|
+
witness.owners = captureScopeSelection(witness.owners);
|
|
41
|
+
}
|
|
5
42
|
function validateHistoryLimit(limit) {
|
|
6
43
|
if (!Number.isSafeInteger(limit) || limit < 0 || limit > MAX_HISTORY_LIMIT) {
|
|
7
44
|
throw new Error(`State Flow history limit must be an integer from 0 to ${MAX_HISTORY_LIMIT}`);
|
|
@@ -16,9 +53,11 @@ function validateBoundary(boundary) {
|
|
|
16
53
|
throw new Error("Invalid State Flow temporal boundary");
|
|
17
54
|
}
|
|
18
55
|
}
|
|
19
|
-
function validateState(state, location) {
|
|
56
|
+
function validateState(state, location, modules) {
|
|
57
|
+
if (modules !== undefined)
|
|
58
|
+
validateExternalPlanes(state, modules);
|
|
20
59
|
const json = isJsonValue(state);
|
|
21
|
-
const hasNull = json && isObject(state) && Object.keys(emptyState()).some((key) => containsNull(state[key]));
|
|
60
|
+
const hasNull = json && isObject(state) && [...Object.keys(emptyState()), ...Object.keys(modules ?? {})].some((key) => containsNull(state[key]));
|
|
22
61
|
if (json && isSemanticState(state) && !hasNull)
|
|
23
62
|
return;
|
|
24
63
|
const reason = !json ? "expected finite, acyclic JSON data"
|
|
@@ -27,9 +66,11 @@ function validateState(state, location) {
|
|
|
27
66
|
: "invalid semantic fields or artifact metadata";
|
|
28
67
|
throw new Error(`Invalid temporal materialized semantic state${location ? ` in ${location}` : ""}: ${reason}`);
|
|
29
68
|
}
|
|
30
|
-
function apply(state, patch, location) {
|
|
69
|
+
function apply(state, patch, location, modules) {
|
|
70
|
+
if (modules !== undefined)
|
|
71
|
+
validateExternalPlanes(patch, modules, true);
|
|
31
72
|
const next = applyPatch(state, patch);
|
|
32
|
-
validateState(next, location);
|
|
73
|
+
validateState(next, location, modules);
|
|
33
74
|
return next;
|
|
34
75
|
}
|
|
35
76
|
function sameBoundary(left, right) {
|
|
@@ -40,7 +81,7 @@ export function validateScopeStream(value, scope, historyLimit = DEFAULT_HISTORY
|
|
|
40
81
|
validateHistoryLimit(historyLimit);
|
|
41
82
|
if (!SCOPES.includes(scope))
|
|
42
83
|
throw new Error("Unknown temporal scope");
|
|
43
|
-
if (!isJsonValue(value) || !isObject(value) || Object.keys(value).sort().join(",") !== "checkpoint,patches,revision"
|
|
84
|
+
if (!isJsonValue(value) || !isObject(value) || Object.keys(value).sort().join(",") !== (Object.hasOwn(value, "modules") ? "checkpoint,modules,patches,revision" : "checkpoint,patches,revision")
|
|
44
85
|
|| !Number.isSafeInteger(value.revision) || value.revision < 0
|
|
45
86
|
|| !isObject(value.checkpoint) || Object.keys(value.checkpoint).sort().join(",") !== "state,through"
|
|
46
87
|
|| !Array.isArray(value.patches)) {
|
|
@@ -48,7 +89,9 @@ export function validateScopeStream(value, scope, historyLimit = DEFAULT_HISTORY
|
|
|
48
89
|
}
|
|
49
90
|
const stream = value;
|
|
50
91
|
validateBoundary(stream.checkpoint.through);
|
|
51
|
-
|
|
92
|
+
if (Object.hasOwn(stream, "modules"))
|
|
93
|
+
validateRetainedModules(stream.modules);
|
|
94
|
+
validateState(stream.checkpoint.state, `${scope} checkpoint`, stream.modules);
|
|
52
95
|
if (stream.patches.length > historyLimit)
|
|
53
96
|
throw new Error(`Temporal scope tail exceeds configured history limit ${historyLimit}`);
|
|
54
97
|
if (stream.revision < stream.patches.length)
|
|
@@ -68,7 +111,7 @@ export function validateScopeStream(value, scope, historyLimit = DEFAULT_HISTORY
|
|
|
68
111
|
throw new Error("Disconnected State Flow temporal ancestry");
|
|
69
112
|
}
|
|
70
113
|
validateRecentTransition({ id: record.transition.id, at: 0, transitions: [{ scope, patch: record.patch }] });
|
|
71
|
-
const next = apply(state, record.patch, `${scope} tail
|
|
114
|
+
const next = apply(state, record.patch, `${scope} tail`, stream.modules);
|
|
72
115
|
state = next;
|
|
73
116
|
previous = record.transition;
|
|
74
117
|
identities.add(previous.id);
|
|
@@ -96,23 +139,71 @@ export function validateTemporalLineage(value, historyLimit = DEFAULT_HISTORY_LI
|
|
|
96
139
|
export function validateScopeLineage(stream, scope, lineage, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
97
140
|
validateTemporalLineage(lineage, historyLimit);
|
|
98
141
|
validateScopeStream(stream, scope, historyLimit);
|
|
142
|
+
const mismatch = scopeLineageMismatch(stream, lineage);
|
|
143
|
+
if (mismatch)
|
|
144
|
+
throw new Error(mismatch);
|
|
145
|
+
}
|
|
146
|
+
/** Classify live shared drift only after both stream and lineage have passed their own validators. */
|
|
147
|
+
export function scopeLineageMatches(stream, scope, lineage, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
148
|
+
validateTemporalLineage(lineage, historyLimit);
|
|
149
|
+
validateScopeStream(stream, scope, historyLimit);
|
|
150
|
+
return scopeLineageMismatch(stream, lineage) === undefined;
|
|
151
|
+
}
|
|
152
|
+
function scopeLineageMismatch(stream, lineage) {
|
|
99
153
|
const oldest = lineage[0];
|
|
100
154
|
const head = lineage.at(-1);
|
|
101
155
|
if (stream.checkpoint.through.position > oldest.position)
|
|
102
|
-
|
|
156
|
+
return "Scope checkpoint is newer than the guaranteed hot boundary";
|
|
103
157
|
const identities = new Map(lineage.map((boundary) => [boundary.id, boundary]));
|
|
104
158
|
for (const boundary of [stream.checkpoint.through, ...stream.patches.map((record) => record.transition)]) {
|
|
105
159
|
if (boundary.position > head.position)
|
|
106
|
-
|
|
160
|
+
return "Temporal scope patch is beyond the active head";
|
|
107
161
|
const identity = identities.get(boundary.id);
|
|
108
162
|
const position = lineage[boundary.position - oldest.position];
|
|
109
163
|
if ((identity && !sameBoundary(identity, boundary)) || (position && !sameBoundary(position, boundary))) {
|
|
110
|
-
|
|
164
|
+
return "Conflicting State Flow temporal lineage";
|
|
111
165
|
}
|
|
112
166
|
}
|
|
167
|
+
return undefined;
|
|
113
168
|
}
|
|
114
169
|
/** Validate one revision-selected cohort. Its older ancestry must be bound by the durable loader. */
|
|
115
170
|
export function validateTemporalState(view, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
171
|
+
if (Object.hasOwn(view, "selection") || Object.hasOwn(view, "causalBasis"))
|
|
172
|
+
throw new Error("Selected temporal state requires selected-cohort admission");
|
|
173
|
+
validateTemporalCohort(view, SCOPES, historyLimit);
|
|
174
|
+
}
|
|
175
|
+
/** Structural consistency only: storage must additionally bind witnesses to accepted source authority. */
|
|
176
|
+
export function validateSelectedTemporalState(view, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
177
|
+
if (!isObject(view) || Object.keys(view).sort().join(",") !== "causalBasis,lineage,scopes,selection"
|
|
178
|
+
|| !isObject(view.scopes) || !Array.isArray(view.causalBasis))
|
|
179
|
+
throw new Error("Invalid selected temporal envelope");
|
|
180
|
+
const selection = captureScopeSelection(view.selection);
|
|
181
|
+
if (!sameJson(selection, view.selection) || Object.keys(view.scopes).sort().join(",") !== [...selection].sort().join(",")) {
|
|
182
|
+
throw new Error("Selected temporal owners must match the canonical selection exactly");
|
|
183
|
+
}
|
|
184
|
+
validateTemporalLineage(view.lineage, historyLimit);
|
|
185
|
+
const boundaries = new Map(view.lineage.slice(1).map((boundary) => [boundary.id, boundary]));
|
|
186
|
+
const witnessed = new Set();
|
|
187
|
+
let position = view.lineage[0].position;
|
|
188
|
+
for (const witness of view.causalBasis) {
|
|
189
|
+
if (!isObject(witness) || Object.keys(witness).sort().join(",") !== "owners,transition")
|
|
190
|
+
throw new Error("Invalid excluded temporal witness");
|
|
191
|
+
validateBoundary(witness.transition);
|
|
192
|
+
const identity = boundaries.get(witness.transition.id);
|
|
193
|
+
const sourceOwners = captureScopeSelection(witness.owners);
|
|
194
|
+
if (!sameJson(sourceOwners, witness.owners) || sourceOwners.some((scope) => selection.includes(scope))
|
|
195
|
+
|| !identity || !sameBoundary(identity, witness.transition) || witness.transition.position <= position
|
|
196
|
+
|| witnessed.has(identity.id))
|
|
197
|
+
throw new Error("Invalid excluded temporal witness basis");
|
|
198
|
+
witnessed.add(identity.id);
|
|
199
|
+
position = witness.transition.position;
|
|
200
|
+
}
|
|
201
|
+
validateTemporalCohort(view, selection, historyLimit, witnessed);
|
|
202
|
+
if (view.causalBasis.some((witness) => selection.some((scope) => streamFor(view, scope).patches.some((record) => record.transition.id === witness.transition.id)))) {
|
|
203
|
+
throw new Error("Excluded temporal witness duplicates a selected patch");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function validateTemporalCohort(view, activeOwners, historyLimit, witnessed = new Set()) {
|
|
116
207
|
validateHistoryLimit(historyLimit);
|
|
117
208
|
validateTemporalLineage(view.lineage, historyLimit);
|
|
118
209
|
const oldest = view.lineage[0];
|
|
@@ -132,8 +223,8 @@ export function validateTemporalState(view, historyLimit = DEFAULT_HISTORY_LIMIT
|
|
|
132
223
|
for (const boundary of view.lineage)
|
|
133
224
|
remember(boundary);
|
|
134
225
|
const head = view.lineage.at(-1);
|
|
135
|
-
for (const scope of
|
|
136
|
-
const stream = view
|
|
226
|
+
for (const scope of activeOwners) {
|
|
227
|
+
const stream = streamFor(view, scope);
|
|
137
228
|
validateScopeStream(stream, scope, historyLimit);
|
|
138
229
|
remember(stream.checkpoint.through);
|
|
139
230
|
if (stream.checkpoint.through.position > oldest.position) {
|
|
@@ -151,7 +242,7 @@ export function validateTemporalState(view, historyLimit = DEFAULT_HISTORY_LIMIT
|
|
|
151
242
|
throw new Error("Disconnected State Flow temporal ancestry");
|
|
152
243
|
}
|
|
153
244
|
for (const boundary of view.lineage.slice(1)) {
|
|
154
|
-
if (!
|
|
245
|
+
if (!activeOwners.some((scope) => streamFor(view, scope).patches.some((record) => record.transition.id === boundary.id)) && !witnessed.has(boundary.id)) {
|
|
155
246
|
throw new Error("Temporal boundary has no semantic patch");
|
|
156
247
|
}
|
|
157
248
|
}
|
|
@@ -175,38 +266,143 @@ export function createTemporalState(states, id, historyLimit = DEFAULT_HISTORY_L
|
|
|
175
266
|
validateTemporalState(view, historyLimit);
|
|
176
267
|
return view;
|
|
177
268
|
}
|
|
269
|
+
/** Restrict a validated value cohort; expanding selection requires separately acquired current streams. */
|
|
270
|
+
export function selectTemporalState(source, selection, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
271
|
+
validateCohort(source, historyLimit);
|
|
272
|
+
const wanted = captureScopeSelection(selection);
|
|
273
|
+
if (wanted.some((scope) => !owners(source).includes(scope)))
|
|
274
|
+
throw new Error("Cannot select an unacquired temporal owner");
|
|
275
|
+
const inherited = new Map(selected(source) ? source.causalBasis.map((witness) => [witness.transition.id, witness]) : []);
|
|
276
|
+
const causalBasis = [];
|
|
277
|
+
for (const boundary of source.lineage.slice(1)) {
|
|
278
|
+
const live = owners(source).filter((scope) => streamFor(source, scope).patches.some((record) => record.transition.id === boundary.id));
|
|
279
|
+
if (live.some((scope) => wanted.includes(scope)))
|
|
280
|
+
continue;
|
|
281
|
+
const evidence = [...new Set([...live, ...(inherited.get(boundary.id)?.owners ?? [])])];
|
|
282
|
+
causalBasis.push({ transition: structuredClone(boundary), owners: captureScopeSelection(evidence) });
|
|
283
|
+
}
|
|
284
|
+
const view = {
|
|
285
|
+
selection: wanted, lineage: structuredClone(source.lineage),
|
|
286
|
+
scopes: Object.fromEntries(wanted.map((scope) => [scope, structuredClone(streamFor(source, scope))])), causalBasis,
|
|
287
|
+
};
|
|
288
|
+
validateSelectedTemporalState(view, historyLimit);
|
|
289
|
+
return view;
|
|
290
|
+
}
|
|
291
|
+
/** Complete retained witness skeleton, derived from validated semantic records/basis, never from lineage alone. */
|
|
292
|
+
export function temporalCausalWitnesses(view, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
293
|
+
validateCohort(view, historyLimit);
|
|
294
|
+
const inherited = new Map(selected(view) ? view.causalBasis.map((witness) => [witness.transition.id, witness]) : []);
|
|
295
|
+
return view.lineage.slice(1).map((transition) => {
|
|
296
|
+
const live = owners(view).filter((scope) => streamFor(view, scope).patches.some((record) => record.transition.id === transition.id));
|
|
297
|
+
return { transition: structuredClone(transition), owners: captureScopeSelection([...new Set([...live, ...(inherited.get(transition.id)?.owners ?? [])])]) };
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
/** Metadata syntax only; a skeleton is neither semantic replay nor acquisition/publication authority. */
|
|
301
|
+
export function captureTemporalWitnesses(lineage, witnesses, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
302
|
+
validateTemporalLineage(lineage, historyLimit);
|
|
303
|
+
if (!Array.isArray(witnesses))
|
|
304
|
+
throw new Error("Invalid accepted temporal witness array");
|
|
305
|
+
const boundaries = new Map(lineage.slice(1).map((boundary) => [boundary.id, boundary]));
|
|
306
|
+
const admitted = [];
|
|
307
|
+
let position = lineage[0].position;
|
|
308
|
+
for (const witness of witnesses) {
|
|
309
|
+
if (!isObject(witness) || Object.keys(witness).sort().join(",") !== "owners,transition")
|
|
310
|
+
throw new Error("Invalid accepted temporal witness");
|
|
311
|
+
const transition = witness.transition;
|
|
312
|
+
validateBoundary(transition);
|
|
313
|
+
const identity = boundaries.get(transition.id);
|
|
314
|
+
const sourceOwners = captureScopeSelection(witness.owners);
|
|
315
|
+
if (!identity || !sameBoundary(identity, transition) || transition.position <= position || !sameJson(sourceOwners, witness.owners)) {
|
|
316
|
+
throw new Error("Accepted temporal witness does not match its lineage");
|
|
317
|
+
}
|
|
318
|
+
admitted.push({ transition: structuredClone(transition), owners: sourceOwners });
|
|
319
|
+
position = transition.position;
|
|
320
|
+
}
|
|
321
|
+
return admitted;
|
|
322
|
+
}
|
|
323
|
+
/** Reconstruct selected values from caller-bound accepted evidence; this validates syntax/consistency, not physical authority. */
|
|
324
|
+
export function restoreSelectedTemporalState(scopes, selection, lineage, witnesses, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
325
|
+
const wanted = captureScopeSelection(selection);
|
|
326
|
+
if (!matchesOwnerKeys(scopes, wanted))
|
|
327
|
+
throw new Error("Selected temporal streams must match their owners exactly");
|
|
328
|
+
validateTemporalLineage(lineage, historyLimit);
|
|
329
|
+
for (const scope of wanted)
|
|
330
|
+
validateScopeLineage(scopes[scope], scope, lineage, historyLimit);
|
|
331
|
+
const skeleton = captureTemporalWitnesses(lineage, witnesses, historyLimit);
|
|
332
|
+
const admitted = new Map(skeleton.map((witness) => [witness.transition.id, witness]));
|
|
333
|
+
for (const witness of skeleton)
|
|
334
|
+
for (const scope of witness.owners.filter((owner) => wanted.includes(owner))) {
|
|
335
|
+
if (!scopes[scope].patches.some((record) => sameBoundary(record.transition, witness.transition)))
|
|
336
|
+
throw new Error("Accepted temporal witness is missing its selected owner patch");
|
|
337
|
+
}
|
|
338
|
+
const causalBasis = [];
|
|
339
|
+
for (const transition of lineage.slice(1)) {
|
|
340
|
+
if (wanted.some((scope) => scopes[scope].patches.some((record) => record.transition.id === transition.id)))
|
|
341
|
+
continue;
|
|
342
|
+
const witness = admitted.get(transition.id);
|
|
343
|
+
if (!witness)
|
|
344
|
+
throw new Error("Temporal boundary has no accepted owner witness");
|
|
345
|
+
causalBasis.push(witness);
|
|
346
|
+
}
|
|
347
|
+
const view = { selection: wanted, lineage: structuredClone([...lineage]), scopes: structuredClone(scopes), causalBasis };
|
|
348
|
+
validateSelectedTemporalState(view, historyLimit);
|
|
349
|
+
return view;
|
|
350
|
+
}
|
|
351
|
+
/** Explicit selected values at a new origin; this constructor grants no initialization/acquisition permission. */
|
|
352
|
+
export function createSelectedTemporalState(states, selection, id, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
353
|
+
const wanted = captureScopeSelection(selection);
|
|
354
|
+
if (!matchesOwnerKeys(states, wanted))
|
|
355
|
+
throw new Error("Selected temporal values must match their owners exactly");
|
|
356
|
+
const through = { id, position: 0, parent: null };
|
|
357
|
+
const view = {
|
|
358
|
+
selection: wanted, lineage: [through], causalBasis: [],
|
|
359
|
+
scopes: Object.fromEntries(wanted.map((scope) => [scope, { revision: 0, checkpoint: { through: structuredClone(through), state: structuredClone(states[scope]) }, patches: [] }])),
|
|
360
|
+
};
|
|
361
|
+
validateSelectedTemporalState(view, historyLimit);
|
|
362
|
+
return view;
|
|
363
|
+
}
|
|
364
|
+
/** Adopt explicitly admitted selected streams at current values only, without invented aligned history. */
|
|
365
|
+
export function adoptSelectedTemporalStreams(scopes, selection, id, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
366
|
+
const wanted = captureScopeSelection(selection);
|
|
367
|
+
if (!matchesOwnerKeys(scopes, wanted))
|
|
368
|
+
throw new Error("Selected temporal streams must match their owners exactly");
|
|
369
|
+
for (const scope of wanted)
|
|
370
|
+
validateScopeStream(scopes[scope], scope, MAX_HISTORY_LIMIT);
|
|
371
|
+
const boundaries = wanted.flatMap((scope) => [scopes[scope].checkpoint.through, ...scopes[scope].patches.map((record) => record.transition)]);
|
|
372
|
+
const origin = { id, position: Math.max(...boundaries.map((boundary) => boundary.position)) + 1, parent: null };
|
|
373
|
+
const view = { selection: wanted, lineage: [origin], scopes: structuredClone(scopes), causalBasis: [] };
|
|
374
|
+
return constrainTemporalState(view, historyLimit);
|
|
375
|
+
}
|
|
178
376
|
function scopeAt(stream, boundary) {
|
|
179
377
|
let state = structuredClone(stream.checkpoint.state);
|
|
180
378
|
for (const record of stream.patches) {
|
|
181
379
|
if (record.transition.position > boundary.position)
|
|
182
380
|
break;
|
|
183
|
-
state = apply(state, record.patch);
|
|
381
|
+
state = apply(state, record.patch, undefined, stream.modules);
|
|
184
382
|
}
|
|
185
383
|
return state;
|
|
186
384
|
}
|
|
187
385
|
/** Fold retained tails to a lower configured limit without inventing history. */
|
|
188
386
|
export function constrainTemporalState(view, historyLimit) {
|
|
189
387
|
validateHistoryLimit(historyLimit);
|
|
190
|
-
|
|
191
|
-
const next =
|
|
192
|
-
for (const scope of
|
|
193
|
-
const stream = next
|
|
388
|
+
validateCohort(view, MAX_HISTORY_LIMIT);
|
|
389
|
+
const next = cloneCohort(view);
|
|
390
|
+
for (const scope of owners(next)) {
|
|
391
|
+
const stream = streamFor(next, scope);
|
|
194
392
|
while (stream.patches.length > historyLimit) {
|
|
195
393
|
const folded = stream.patches.shift();
|
|
196
|
-
stream.checkpoint = { through: folded.transition, state: apply(stream.checkpoint.state, folded.patch) };
|
|
394
|
+
stream.checkpoint = { through: folded.transition, state: apply(stream.checkpoint.state, folded.patch, undefined, stream.modules) };
|
|
197
395
|
}
|
|
198
396
|
}
|
|
199
397
|
next.lineage = next.lineage.slice(-(historyLimit + 1));
|
|
200
|
-
|
|
398
|
+
trimCausalBasis(next);
|
|
399
|
+
validateCohort(next, historyLimit);
|
|
201
400
|
return next;
|
|
202
401
|
}
|
|
203
|
-
/** Current independent scope revisions; Effective uses this vector rather than inventing a scalar owner. */
|
|
204
402
|
export function temporalScopeRevisions(view) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
session: view.scopes.session.revision,
|
|
209
|
-
};
|
|
403
|
+
if (selected(view))
|
|
404
|
+
validateSelectedTemporalState(view, MAX_HISTORY_LIMIT);
|
|
405
|
+
const revisions = Object.fromEntries(owners(view).map((scope) => [scope, streamFor(view, scope).revision]));
|
|
210
406
|
if (Object.values(revisions).some((revision) => !Number.isSafeInteger(revision) || revision < 0)) {
|
|
211
407
|
throw new Error("Invalid State Flow scope revision vector");
|
|
212
408
|
}
|
|
@@ -217,24 +413,29 @@ function readBoundary(view, offset, historyLimit) {
|
|
|
217
413
|
if (!Number.isSafeInteger(offset) || offset < 0 || offset > historyLimit) {
|
|
218
414
|
throw new Error(`State Flow hot-history offset must be an integer from 0 to ${historyLimit}`);
|
|
219
415
|
}
|
|
220
|
-
|
|
416
|
+
validateCohort(view, historyLimit);
|
|
221
417
|
const boundary = view.lineage[view.lineage.length - 1 - offset];
|
|
222
418
|
if (!boundary)
|
|
223
419
|
throw new Error("Requested history predates the proven temporal origin");
|
|
224
420
|
return boundary;
|
|
225
421
|
}
|
|
226
|
-
/** Exact scope semantics for authored staging; defaults must never become implicit writes. */
|
|
227
422
|
export function readTemporalScopes(view, offset = 0, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
228
423
|
const boundary = readBoundary(view, offset, historyLimit);
|
|
229
|
-
return
|
|
424
|
+
return Object.fromEntries(owners(view).map((scope) => [scope, scopeAt(streamFor(view, scope), boundary)]));
|
|
230
425
|
}
|
|
231
426
|
/** Sparse current/historical view: unknown planes and absent values never become effective data. */
|
|
232
427
|
export function readTemporalView(view, offset = 0, scope, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
233
428
|
if (scope !== undefined && !SCOPES.includes(scope))
|
|
234
429
|
throw new Error("Unknown temporal scope");
|
|
430
|
+
if (scope !== undefined && !owners(view).includes(scope))
|
|
431
|
+
throw new Error(`State Flow ${scope} scope is excluded`);
|
|
235
432
|
const boundary = readBoundary(view, offset, historyLimit);
|
|
236
|
-
const
|
|
237
|
-
return
|
|
433
|
+
const active = scope === undefined ? owners(view) : [scope];
|
|
434
|
+
return active.reduce((state, owner) => {
|
|
435
|
+
const stream = streamFor(view, owner), raw = scopeAt(stream, boundary);
|
|
436
|
+
const projected = projectSemanticState(raw, stream.modules);
|
|
437
|
+
return applyPatch(state, projected);
|
|
438
|
+
}, {});
|
|
238
439
|
}
|
|
239
440
|
/** Internal defaulted materialization for consumers that require object registries. */
|
|
240
441
|
export function readTemporalState(view, offset = 0, scope, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
@@ -243,45 +444,48 @@ export function readTemporalState(view, offset = 0, scope, historyLimit = DEFAUL
|
|
|
243
444
|
/** Allocate the identity outside this algebra; only materially effective patches accept it. */
|
|
244
445
|
export function advanceTemporalState(view, transitions, id, historyLimit = DEFAULT_HISTORY_LIMIT) {
|
|
245
446
|
validateHistoryLimit(historyLimit);
|
|
246
|
-
|
|
447
|
+
validateCohort(view, historyLimit);
|
|
247
448
|
if (transitions.length === 0)
|
|
248
449
|
return view;
|
|
249
450
|
validateRecentTransition({ id, at: 0, transitions });
|
|
451
|
+
if (transitions.some(({ scope }) => !owners(view).includes(scope)))
|
|
452
|
+
throw new Error("State Flow patch contains an excluded temporal owner");
|
|
250
453
|
const head = view.lineage.at(-1);
|
|
251
454
|
const changes = transitions.filter(({ scope, patch }) => {
|
|
252
|
-
const current = scopeAt(view
|
|
253
|
-
return !sameJson(current, apply(current, patch));
|
|
455
|
+
const current = scopeAt(streamFor(view, scope), head);
|
|
456
|
+
return !sameJson(current, apply(current, patch, undefined, streamFor(view, scope).modules));
|
|
254
457
|
});
|
|
255
458
|
if (changes.length === 0)
|
|
256
459
|
return view;
|
|
257
460
|
const knownIds = new Set(view.lineage.map((boundary) => boundary.id));
|
|
258
|
-
for (const scope of
|
|
259
|
-
knownIds.add(view
|
|
260
|
-
for (const record of view
|
|
461
|
+
for (const scope of owners(view)) {
|
|
462
|
+
knownIds.add(streamFor(view, scope).checkpoint.through.id);
|
|
463
|
+
for (const record of streamFor(view, scope).patches)
|
|
261
464
|
knownIds.add(record.transition.id);
|
|
262
465
|
}
|
|
263
466
|
if (knownIds.has(id))
|
|
264
467
|
throw new Error("State Flow transition identity has already been used");
|
|
265
468
|
const boundary = { id, position: head.position + 1, parent: head.id };
|
|
266
469
|
validateBoundary(boundary);
|
|
267
|
-
const next =
|
|
470
|
+
const next = cloneCohort(view);
|
|
268
471
|
for (const { scope, patch } of changes) {
|
|
269
|
-
const stream = next
|
|
472
|
+
const stream = streamFor(next, scope);
|
|
270
473
|
if (stream.revision >= Number.MAX_SAFE_INTEGER)
|
|
271
474
|
throw new Error(`State Flow ${scope} scope revision is exhausted`);
|
|
272
475
|
stream.revision += 1;
|
|
273
476
|
if (historyLimit === 0) {
|
|
274
|
-
stream.checkpoint = { through: structuredClone(boundary), state: apply(scopeAt(stream, head), patch) };
|
|
477
|
+
stream.checkpoint = { through: structuredClone(boundary), state: apply(scopeAt(stream, head), patch, undefined, stream.modules) };
|
|
275
478
|
stream.patches = [];
|
|
276
479
|
continue;
|
|
277
480
|
}
|
|
278
481
|
while (stream.patches.length >= historyLimit) {
|
|
279
482
|
const folded = stream.patches.shift();
|
|
280
|
-
stream.checkpoint = { through: folded.transition, state: apply(stream.checkpoint.state, folded.patch) };
|
|
483
|
+
stream.checkpoint = { through: folded.transition, state: apply(stream.checkpoint.state, folded.patch, undefined, stream.modules) };
|
|
281
484
|
}
|
|
282
485
|
stream.patches.push({ transition: structuredClone(boundary), patch: structuredClone(patch) });
|
|
283
486
|
}
|
|
284
487
|
next.lineage = [...next.lineage, boundary].slice(-(historyLimit + 1));
|
|
285
|
-
|
|
488
|
+
trimCausalBasis(next);
|
|
489
|
+
validateCohort(next, historyLimit);
|
|
286
490
|
return next;
|
|
287
491
|
}
|
|
@@ -1,29 +1,62 @@
|
|
|
1
1
|
import { type ArtifactProvenance } from "./artifact.ts";
|
|
2
2
|
import type { SuccessfulArtifactRead } from "./acquisition.ts";
|
|
3
3
|
import { type AcceptedTransition } from "./history.ts";
|
|
4
|
-
import { type MissingDeletion } from "./json.ts";
|
|
4
|
+
import { type JsonObject, type MissingDeletion } from "./json.ts";
|
|
5
5
|
import { type OwnedPath } from "./ownership.ts";
|
|
6
6
|
import { type SuccessfulSkillRead } from "./skills.ts";
|
|
7
7
|
import type { Snapshot } from "./snapshot.ts";
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { type ScopeSelection } from "./selection.ts";
|
|
9
|
+
import { type RetainedModules, type StateFlowModule } from "./semantic-module.ts";
|
|
10
|
+
import type { JsonValue } from "./json.ts";
|
|
11
|
+
import type { AtomicScopePatches, ScopedSemanticStates, ScopeStateValues, StateScope, TerminalTransition } from "./state.ts";
|
|
12
|
+
interface StagedTransition<States extends ScopeStateValues> {
|
|
13
|
+
nextStates: States;
|
|
11
14
|
/** Authored no-op deletions; presentation evidence only, never replay input. */
|
|
12
15
|
missingDeletions: MissingDeletion[];
|
|
13
|
-
/** Scope-local targets
|
|
14
|
-
cascades:
|
|
15
|
-
|
|
16
|
+
/** Scope-local targets cleared before other writes; may be recreated, never replay input. */
|
|
17
|
+
cascades: {
|
|
18
|
+
[Owner in keyof States]: OwnedPath[];
|
|
19
|
+
};
|
|
20
|
+
stateHashes: {
|
|
21
|
+
[Owner in keyof States]: string;
|
|
22
|
+
};
|
|
16
23
|
/** Fresh runtime-owned provenance for artifacts compiled in this transition. */
|
|
17
|
-
provenanceUpdates:
|
|
24
|
+
provenanceUpdates: {
|
|
25
|
+
[Owner in keyof States]: Record<string, ArtifactProvenance>;
|
|
26
|
+
};
|
|
18
27
|
causalBasis: string;
|
|
19
28
|
committed: boolean;
|
|
29
|
+
moduleAdditions?: Partial<Record<StateScope, RetainedModules>>;
|
|
30
|
+
}
|
|
31
|
+
export type StagedScopedTransition = StagedTransition<ScopedSemanticStates> & {
|
|
32
|
+
selection?: never;
|
|
33
|
+
};
|
|
34
|
+
export type StagedSelectedTransition = StagedTransition<ScopeStateValues> & {
|
|
35
|
+
selection: ScopeSelection;
|
|
36
|
+
};
|
|
37
|
+
/** Internal host proposals only; never accepted from model tool arguments. */
|
|
38
|
+
export interface ModuleReplacement {
|
|
39
|
+
scope: StateScope;
|
|
40
|
+
id: string;
|
|
41
|
+
content: JsonObject;
|
|
42
|
+
}
|
|
43
|
+
export interface SelectedSemanticBasis {
|
|
44
|
+
selection: ScopeSelection;
|
|
45
|
+
states: ScopeStateValues;
|
|
46
|
+
modules?: Partial<Record<StateScope, RetainedModules>>;
|
|
20
47
|
}
|
|
21
48
|
/** Stage one canonical atomic scope cohort without changing the finalized response. */
|
|
22
49
|
export declare function stageAtomicScopePatches(currentStates: ScopedSemanticStates, patches: AtomicScopePatches, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedScopedTransition;
|
|
23
50
|
export declare function stageScopedTransition(currentStates: ScopedSemanticStates, transition: TerminalTransition, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedScopedTransition;
|
|
51
|
+
/** Value-only selected staging; a selection or causal token is not physical publication authority. */
|
|
52
|
+
export declare function stageSelectedScopePatches(current: SelectedSemanticBasis, patches: AtomicScopePatches, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>, definitions?: readonly StateFlowModule<JsonObject, JsonValue>[], replacements?: readonly ModuleReplacement[]): StagedSelectedTransition;
|
|
53
|
+
/** Excluded Session suppresses capture, not ordinary-answer delivery or lifecycle completion. */
|
|
54
|
+
export declare function stageSelectedScopedTransition(current: SelectedSemanticBasis, transition: TerminalTransition, successfulSkillReads: Iterable<SuccessfulSkillRead>, causalBasis: string, successfulArtifactReads?: Iterable<SuccessfulArtifactRead>): StagedSelectedTransition;
|
|
24
55
|
/** Commit one accepted transition; durable publication receives all changed scopes as one cohort. */
|
|
25
56
|
export interface CommitScopedTransitionOptions {
|
|
26
57
|
/** Runtime response reconciliation finalizes bootstrap lifecycle state. */
|
|
27
58
|
finalizeRun?: boolean;
|
|
28
59
|
}
|
|
29
60
|
export declare function commitScopedTransition(snapshot: Snapshot, states: ScopedSemanticStates, stage: StagedScopedTransition, publishDurable: (accepted: AcceptedTransition | undefined, nextSnapshot: Snapshot) => void, causalBasis: string, options?: CommitScopedTransitionOptions): boolean;
|
|
61
|
+
export declare function commitSelectedTransition(snapshot: Snapshot, current: SelectedSemanticBasis, stage: StagedSelectedTransition, publishDurable: (accepted: AcceptedTransition | undefined, nextSnapshot: Snapshot) => void, causalBasis: string, options?: CommitScopedTransitionOptions): boolean;
|
|
62
|
+
export {};
|