@dbsp/core 3.2.0 → 3.3.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/dist/index.d.ts +51 -13
- package/dist/index.js +391 -172
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3430,8 +3430,15 @@ function capabilityAvailable(descriptor, context) {
|
|
|
3430
3430
|
}
|
|
3431
3431
|
}
|
|
3432
3432
|
}
|
|
3433
|
+
var RETIRED_CONNECTION_OWNERSHIP_MEMBERS = ["checkout", "release"];
|
|
3434
|
+
function retiredConnectionOwnershipMember(value) {
|
|
3435
|
+
return RETIRED_CONNECTION_OWNERSHIP_MEMBERS.find((member) => member in value);
|
|
3436
|
+
}
|
|
3433
3437
|
function isOperationRuntime(semantics) {
|
|
3434
|
-
|
|
3438
|
+
if (retiredConnectionOwnershipMember(semantics) !== void 0) {
|
|
3439
|
+
return false;
|
|
3440
|
+
}
|
|
3441
|
+
return "writeIntentJournal" in semantics && "begin" in semantics && "setLockTimeout" in semantics && "acquireLocks" in semantics && "observeContext" in semantics && "observeOperation" in semantics && "checkGuard" in semantics && "executeOperation" in semantics && "writeCompletionJournal" in semantics && "commit" in semantics && "rollback" in semantics && "writeObservedJournal" in semantics && "isLockTimeout" in semantics;
|
|
3435
3442
|
}
|
|
3436
3443
|
function validateRulePrecedenceFacts(facts, rules) {
|
|
3437
3444
|
const rulesByKey = new Map(rules.map((rule) => [ruleKey(rule), rule]));
|
|
@@ -3574,6 +3581,12 @@ var PackRegistry = class {
|
|
|
3574
3581
|
compositionFactOwnerByKind.set(kind, owner);
|
|
3575
3582
|
};
|
|
3576
3583
|
for (const pack of packs) {
|
|
3584
|
+
const retiredMember = pack.executionCoordinator ? retiredConnectionOwnershipMember(pack.executionCoordinator) : void 0;
|
|
3585
|
+
if (retiredMember !== void 0) {
|
|
3586
|
+
throw new Error(
|
|
3587
|
+
`transition pack executionCoordinator declares retired connection ownership member ${retiredMember}`
|
|
3588
|
+
);
|
|
3589
|
+
}
|
|
3577
3590
|
const transactionDomain = pack.transactionDomain ?? pack.executionCoordinator?.transactionDomain;
|
|
3578
3591
|
if (pack.executionCoordinator && !transactionDomain) {
|
|
3579
3592
|
throw new Error(
|
|
@@ -3892,6 +3905,129 @@ function assumptionAccepted(assumption, policy) {
|
|
|
3892
3905
|
// src/transition/resume.ts
|
|
3893
3906
|
import { createHash as createHash2 } from "crypto";
|
|
3894
3907
|
|
|
3908
|
+
// src/transition/transition-lessor.ts
|
|
3909
|
+
var TRANSITION_LESSOR_BRAND = /* @__PURE__ */ Symbol.for("dbsp.transition.lessor");
|
|
3910
|
+
var TRANSITION_LESSOR_PROTOCOL_VERSION = 1;
|
|
3911
|
+
var TRANSITION_LESSOR_REJECTION = "transition target must be a core-minted lessor";
|
|
3912
|
+
async function captureLease(value) {
|
|
3913
|
+
const { query, release } = leaseMembers(value);
|
|
3914
|
+
if (typeof query !== "function" || typeof release !== "function") {
|
|
3915
|
+
const rejection = new Error(
|
|
3916
|
+
"A transition lessor must acquire a lease exposing query() and release(). This acquisition returned an unusable member pair."
|
|
3917
|
+
);
|
|
3918
|
+
releaseMalformedAcquisition(value, release, rejection);
|
|
3919
|
+
throw rejection;
|
|
3920
|
+
}
|
|
3921
|
+
return {
|
|
3922
|
+
raw: value,
|
|
3923
|
+
query,
|
|
3924
|
+
release
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3927
|
+
async function acquireTransitionLease(target) {
|
|
3928
|
+
const { raw: raw2, query, release } = await captureLease(await target.acquire());
|
|
3929
|
+
let closed = false;
|
|
3930
|
+
const session = Object.freeze({
|
|
3931
|
+
query: (sql2, params) => {
|
|
3932
|
+
if (closed) {
|
|
3933
|
+
return Promise.reject(
|
|
3934
|
+
new Error("transition lease was already given back")
|
|
3935
|
+
);
|
|
3936
|
+
}
|
|
3937
|
+
return query.call(raw2, sql2, params);
|
|
3938
|
+
}
|
|
3939
|
+
});
|
|
3940
|
+
const releaseLease = (failure) => {
|
|
3941
|
+
if (closed) {
|
|
3942
|
+
return Promise.resolve();
|
|
3943
|
+
}
|
|
3944
|
+
closed = true;
|
|
3945
|
+
try {
|
|
3946
|
+
const returned = failure ? release.call(raw2, releaseArgument(failure)) : release.call(raw2);
|
|
3947
|
+
void Promise.resolve(returned).catch(() => void 0);
|
|
3948
|
+
} catch {
|
|
3949
|
+
}
|
|
3950
|
+
return Promise.resolve();
|
|
3951
|
+
};
|
|
3952
|
+
return Object.freeze({
|
|
3953
|
+
session,
|
|
3954
|
+
release: releaseLease
|
|
3955
|
+
});
|
|
3956
|
+
}
|
|
3957
|
+
function leaseMembers(value) {
|
|
3958
|
+
if (value == null || typeof value !== "object" && typeof value !== "function") {
|
|
3959
|
+
return { query: void 0, release: void 0 };
|
|
3960
|
+
}
|
|
3961
|
+
const release = readMember(value, "release");
|
|
3962
|
+
return { query: readMember(value, "query"), release };
|
|
3963
|
+
}
|
|
3964
|
+
function readMember(value, member) {
|
|
3965
|
+
try {
|
|
3966
|
+
return value[member];
|
|
3967
|
+
} catch {
|
|
3968
|
+
return void 0;
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
function releaseMalformedAcquisition(value, release, rejection) {
|
|
3972
|
+
if (typeof release !== "function") {
|
|
3973
|
+
return;
|
|
3974
|
+
}
|
|
3975
|
+
try {
|
|
3976
|
+
void Promise.resolve(release.call(value, rejection)).catch(() => void 0);
|
|
3977
|
+
} catch {
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
function createTransitionLessor(acquire) {
|
|
3981
|
+
const lessor = { acquire };
|
|
3982
|
+
Object.defineProperty(lessor, TRANSITION_LESSOR_BRAND, {
|
|
3983
|
+
value: Object.freeze({
|
|
3984
|
+
protocolVersion: TRANSITION_LESSOR_PROTOCOL_VERSION
|
|
3985
|
+
}),
|
|
3986
|
+
writable: false,
|
|
3987
|
+
configurable: false
|
|
3988
|
+
});
|
|
3989
|
+
return Object.freeze(lessor);
|
|
3990
|
+
}
|
|
3991
|
+
function isTransitionLessor(value) {
|
|
3992
|
+
try {
|
|
3993
|
+
if (value == null || typeof value !== "object" && typeof value !== "function" || Array.isArray(value)) {
|
|
3994
|
+
return false;
|
|
3995
|
+
}
|
|
3996
|
+
const brand = value[TRANSITION_LESSOR_BRAND];
|
|
3997
|
+
return brand != null && typeof brand === "object" && brand.protocolVersion === TRANSITION_LESSOR_PROTOCOL_VERSION && typeof value.acquire === "function";
|
|
3998
|
+
} catch {
|
|
3999
|
+
return false;
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
var TransitionLeaseFailureError = class extends Error {
|
|
4003
|
+
constructor(cause) {
|
|
4004
|
+
super("transition lease released after a failure", { cause });
|
|
4005
|
+
this.name = "TransitionLeaseFailureError";
|
|
4006
|
+
}
|
|
4007
|
+
};
|
|
4008
|
+
function releaseArgument(failure) {
|
|
4009
|
+
return failure.error ? failure.error : new TransitionLeaseFailureError(failure.error);
|
|
4010
|
+
}
|
|
4011
|
+
function transitionLessorRejectionAssessment(artifact, lifecycle = "planned") {
|
|
4012
|
+
return {
|
|
4013
|
+
decision: "blocked",
|
|
4014
|
+
assurance: "unproven",
|
|
4015
|
+
lifecycle,
|
|
4016
|
+
continuation: "human-intervention-required",
|
|
4017
|
+
reasons: [
|
|
4018
|
+
{
|
|
4019
|
+
code: "context-mismatch",
|
|
4020
|
+
artifact,
|
|
4021
|
+
fact: {
|
|
4022
|
+
key: "transition-lessor",
|
|
4023
|
+
value: TRANSITION_LESSOR_REJECTION
|
|
4024
|
+
},
|
|
4025
|
+
scope: []
|
|
4026
|
+
}
|
|
4027
|
+
]
|
|
4028
|
+
};
|
|
4029
|
+
}
|
|
4030
|
+
|
|
3895
4031
|
// src/transition/validation.ts
|
|
3896
4032
|
function sameTrustRoot2(left, right) {
|
|
3897
4033
|
return stableJson(left) === stableJson(right);
|
|
@@ -4787,6 +4923,11 @@ function latestIntent(step, events) {
|
|
|
4787
4923
|
recordedAt: recordedAt()
|
|
4788
4924
|
};
|
|
4789
4925
|
}
|
|
4926
|
+
function orderedPlanSteps(plan2, stepById) {
|
|
4927
|
+
return plan2.segments.flatMap(
|
|
4928
|
+
(segment) => segment.stepIds.map((stepId2) => stepById.get(stepId2)).filter((step) => step !== void 0)
|
|
4929
|
+
);
|
|
4930
|
+
}
|
|
4790
4931
|
function resumeRequiredResult(params) {
|
|
4791
4932
|
const hasCompleted = params.completed.length > 0;
|
|
4792
4933
|
return {
|
|
@@ -4925,80 +5066,71 @@ function completedJournal(intent, completion, observations) {
|
|
|
4925
5066
|
observedOutcome
|
|
4926
5067
|
};
|
|
4927
5068
|
}
|
|
4928
|
-
async function
|
|
5069
|
+
async function withObservedStep(registry, step, target, baseContext, phase, use) {
|
|
4929
5070
|
const resolution = registry.resolveOperation(step.operation);
|
|
4930
5071
|
if (!resolution.ok || !isOperationRuntime(resolution.semantics)) {
|
|
4931
|
-
return { ok: false, detail: "operation runtime missing" };
|
|
5072
|
+
return use({ ok: false, detail: "operation runtime missing" });
|
|
4932
5073
|
}
|
|
4933
5074
|
const runtime = resolution.semantics;
|
|
4934
5075
|
const issuer = registry.resolveIssuer(step.operation.operationKind.artifact);
|
|
4935
5076
|
if (!issuer) {
|
|
4936
|
-
return { ok: false, detail: "operation observation issuer missing" };
|
|
5077
|
+
return use({ ok: false, detail: "operation observation issuer missing" });
|
|
4937
5078
|
}
|
|
4938
|
-
let
|
|
5079
|
+
let lease;
|
|
5080
|
+
let failed = false;
|
|
5081
|
+
let failure;
|
|
4939
5082
|
try {
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
);
|
|
4946
|
-
context = registry.contextWithDerivedCapabilities(context);
|
|
4947
|
-
const liveContextMatch = matchLiveObservationContext({
|
|
4948
|
-
expected: baseContext,
|
|
4949
|
-
actual: context
|
|
4950
|
-
});
|
|
4951
|
-
if (!liveContextMatch.ok) {
|
|
4952
|
-
await runtimeSafeRelease(runtime, client);
|
|
4953
|
-
return { ok: false, detail: liveContextMatch.detail };
|
|
4954
|
-
}
|
|
4955
|
-
const observed = await runtime.observeOperation(
|
|
4956
|
-
client,
|
|
4957
|
-
step.operation,
|
|
4958
|
-
context,
|
|
4959
|
-
phase,
|
|
4960
|
-
issuer
|
|
4961
|
-
);
|
|
4962
|
-
return {
|
|
4963
|
-
ok: true,
|
|
4964
|
-
observations: observed.observations,
|
|
4965
|
-
fingerprint: observed.fingerprint,
|
|
4966
|
-
client,
|
|
4967
|
-
runtime
|
|
4968
|
-
};
|
|
4969
|
-
} catch (error) {
|
|
4970
|
-
if (client) {
|
|
4971
|
-
await runtimeSafeRelease(
|
|
4972
|
-
resolution.ok && isOperationRuntime(resolution.semantics) ? resolution.semantics : void 0,
|
|
5083
|
+
let observation;
|
|
5084
|
+
try {
|
|
5085
|
+
lease = await acquireTransitionLease(target);
|
|
5086
|
+
const client = { opaqueClient: lease.session };
|
|
5087
|
+
let context = await runtime.observeContext(
|
|
4973
5088
|
client,
|
|
4974
|
-
|
|
5089
|
+
step.operation,
|
|
5090
|
+
baseContext
|
|
4975
5091
|
);
|
|
5092
|
+
context = registry.contextWithDerivedCapabilities(context);
|
|
5093
|
+
const liveContextMatch = matchLiveObservationContext({
|
|
5094
|
+
expected: baseContext,
|
|
5095
|
+
actual: context
|
|
5096
|
+
});
|
|
5097
|
+
if (!liveContextMatch.ok) {
|
|
5098
|
+
observation = { ok: false, detail: liveContextMatch.detail };
|
|
5099
|
+
} else {
|
|
5100
|
+
const observed = await runtime.observeOperation(
|
|
5101
|
+
client,
|
|
5102
|
+
step.operation,
|
|
5103
|
+
context,
|
|
5104
|
+
phase,
|
|
5105
|
+
issuer
|
|
5106
|
+
);
|
|
5107
|
+
observation = {
|
|
5108
|
+
ok: true,
|
|
5109
|
+
observations: observed.observations,
|
|
5110
|
+
fingerprint: observed.fingerprint,
|
|
5111
|
+
writeJournal: async (journal) => runtime.writeObservedJournal(client, journal)
|
|
5112
|
+
};
|
|
5113
|
+
}
|
|
5114
|
+
} catch (error) {
|
|
5115
|
+
failed = true;
|
|
5116
|
+
failure = error;
|
|
5117
|
+
observation = {
|
|
5118
|
+
ok: false,
|
|
5119
|
+
detail: error instanceof Error ? error.message : "observation failed"
|
|
5120
|
+
};
|
|
5121
|
+
}
|
|
5122
|
+
try {
|
|
5123
|
+
return await use(observation);
|
|
5124
|
+
} catch (error) {
|
|
5125
|
+
failed = true;
|
|
5126
|
+
failure = error;
|
|
5127
|
+
throw error;
|
|
5128
|
+
}
|
|
5129
|
+
} finally {
|
|
5130
|
+
if (lease) {
|
|
5131
|
+
await lease.release(failed ? { error: failure } : void 0);
|
|
4976
5132
|
}
|
|
4977
|
-
return {
|
|
4978
|
-
ok: false,
|
|
4979
|
-
detail: error instanceof Error ? error.message : "observation failed"
|
|
4980
|
-
};
|
|
4981
|
-
}
|
|
4982
|
-
}
|
|
4983
|
-
async function runtimeSafeRelease(runtime, client, error) {
|
|
4984
|
-
if (!runtime) {
|
|
4985
|
-
return;
|
|
4986
|
-
}
|
|
4987
|
-
try {
|
|
4988
|
-
await runtime.release(client, error);
|
|
4989
|
-
} catch {
|
|
4990
|
-
}
|
|
4991
|
-
}
|
|
4992
|
-
async function releaseObservedAttempt(attempt, error) {
|
|
4993
|
-
if (attempt.ok) {
|
|
4994
|
-
await runtimeSafeRelease(attempt.runtime, attempt.client, error);
|
|
4995
|
-
}
|
|
4996
|
-
}
|
|
4997
|
-
async function writeObserved(attempt, journal) {
|
|
4998
|
-
if (!attempt.ok) {
|
|
4999
|
-
return;
|
|
5000
5133
|
}
|
|
5001
|
-
await attempt.runtime.writeObservedJournal(attempt.client, journal);
|
|
5002
5134
|
}
|
|
5003
5135
|
function stepAssumption(plan2, assumptionId2) {
|
|
5004
5136
|
return plan2.assumptions.find((assumption) => assumption.id === assumptionId2);
|
|
@@ -5035,6 +5167,43 @@ async function resumeTransitionRun(registry, input) {
|
|
|
5035
5167
|
if (!evidenceContext) {
|
|
5036
5168
|
return contextMismatch("loaded plan contains no durable evidence context");
|
|
5037
5169
|
}
|
|
5170
|
+
const referencedAssumptions = /* @__PURE__ */ new Set();
|
|
5171
|
+
for (const step of loaded.plan.steps) {
|
|
5172
|
+
for (const assumptionId2 of step.restsOnAssumptions) {
|
|
5173
|
+
referencedAssumptions.add(assumptionId2);
|
|
5174
|
+
}
|
|
5175
|
+
const policyFailure = validatePolicyForStep(
|
|
5176
|
+
loaded.plan,
|
|
5177
|
+
step,
|
|
5178
|
+
input.policy
|
|
5179
|
+
);
|
|
5180
|
+
if (policyFailure) {
|
|
5181
|
+
return policyFailure;
|
|
5182
|
+
}
|
|
5183
|
+
}
|
|
5184
|
+
for (const assumption of loaded.plan.assumptions) {
|
|
5185
|
+
if (!referencedAssumptions.has(assumption.id) && !assumptionAccepted(assumption, input.policy)) {
|
|
5186
|
+
return unacceptedPlanAssumption(loaded.plan, assumption);
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
const stepById = new Map(
|
|
5190
|
+
loaded.plan.steps.map((step) => [step.stepId, step])
|
|
5191
|
+
);
|
|
5192
|
+
const groupedResult = groupEvents(loaded.events, loaded.run.runId, stepById);
|
|
5193
|
+
if (!groupedResult.ok) {
|
|
5194
|
+
return contextMismatch(groupedResult.detail);
|
|
5195
|
+
}
|
|
5196
|
+
const grouped = groupedResult.grouped;
|
|
5197
|
+
if (!isTransitionLessor(input.target)) {
|
|
5198
|
+
return {
|
|
5199
|
+
assessment: transitionLessorRejectionAssessment(
|
|
5200
|
+
RESUMER_ARTIFACT,
|
|
5201
|
+
loaded.events.length === 0 ? "planned" : "outcome-unknown"
|
|
5202
|
+
),
|
|
5203
|
+
journals: [],
|
|
5204
|
+
observations: []
|
|
5205
|
+
};
|
|
5206
|
+
}
|
|
5038
5207
|
const baseContext = await input.readContext(input.target, loaded.run);
|
|
5039
5208
|
const runContextMatch = matchRunObservationContext({
|
|
5040
5209
|
run: loaded.run,
|
|
@@ -5074,36 +5243,7 @@ async function resumeTransitionRun(registry, input) {
|
|
|
5074
5243
|
`loaded plan failed semantic invariant validation: ${semanticDiagnostic.detail}`
|
|
5075
5244
|
);
|
|
5076
5245
|
}
|
|
5077
|
-
const
|
|
5078
|
-
for (const step of loaded.plan.steps) {
|
|
5079
|
-
for (const assumptionId2 of step.restsOnAssumptions) {
|
|
5080
|
-
referencedAssumptions.add(assumptionId2);
|
|
5081
|
-
}
|
|
5082
|
-
const policyFailure = validatePolicyForStep(
|
|
5083
|
-
loaded.plan,
|
|
5084
|
-
step,
|
|
5085
|
-
input.policy
|
|
5086
|
-
);
|
|
5087
|
-
if (policyFailure) {
|
|
5088
|
-
return policyFailure;
|
|
5089
|
-
}
|
|
5090
|
-
}
|
|
5091
|
-
for (const assumption of loaded.plan.assumptions) {
|
|
5092
|
-
if (!referencedAssumptions.has(assumption.id) && !assumptionAccepted(assumption, input.policy)) {
|
|
5093
|
-
return unacceptedPlanAssumption(loaded.plan, assumption);
|
|
5094
|
-
}
|
|
5095
|
-
}
|
|
5096
|
-
const stepById = new Map(
|
|
5097
|
-
loaded.plan.steps.map((step) => [step.stepId, step])
|
|
5098
|
-
);
|
|
5099
|
-
const groupedResult = groupEvents(loaded.events, loaded.run.runId, stepById);
|
|
5100
|
-
if (!groupedResult.ok) {
|
|
5101
|
-
return contextMismatch(groupedResult.detail);
|
|
5102
|
-
}
|
|
5103
|
-
const grouped = groupedResult.grouped;
|
|
5104
|
-
const orderedSteps = loaded.plan.segments.flatMap(
|
|
5105
|
-
(segment) => segment.stepIds.map((stepId2) => stepById.get(stepId2)).filter(Boolean)
|
|
5106
|
-
);
|
|
5246
|
+
const orderedSteps = orderedPlanSteps(loaded.plan, stepById);
|
|
5107
5247
|
const completed = [];
|
|
5108
5248
|
const observations = [];
|
|
5109
5249
|
for (const step of orderedSteps) {
|
|
@@ -5138,65 +5278,90 @@ async function resumeTransitionRun(registry, input) {
|
|
|
5138
5278
|
}
|
|
5139
5279
|
const transactional = effects.effects.execution.transaction !== "forbids-transaction";
|
|
5140
5280
|
if (observedJournal?.outcome === "completed" || completion) {
|
|
5141
|
-
const after2 = await
|
|
5281
|
+
const after2 = await withObservedStep(
|
|
5142
5282
|
registry,
|
|
5143
5283
|
step,
|
|
5144
5284
|
input.target,
|
|
5145
5285
|
baseContext,
|
|
5146
|
-
"after"
|
|
5286
|
+
"after",
|
|
5287
|
+
async (observation) => {
|
|
5288
|
+
if (!observation.ok || !fingerprintMatches(step.expectedAfter, observation.fingerprint)) {
|
|
5289
|
+
return {
|
|
5290
|
+
kind: "unmatched",
|
|
5291
|
+
detail: observation.ok ? "current fingerprint no longer matches expectedAfter" : observation.detail
|
|
5292
|
+
};
|
|
5293
|
+
}
|
|
5294
|
+
const journal = observedJournal?.outcome === "completed" ? observedJournal : completedJournal(intent, completion, observation.observations);
|
|
5295
|
+
if (!observedJournal) {
|
|
5296
|
+
await observation.writeJournal(journal);
|
|
5297
|
+
}
|
|
5298
|
+
return {
|
|
5299
|
+
kind: "completed",
|
|
5300
|
+
observations: observation.observations,
|
|
5301
|
+
journal
|
|
5302
|
+
};
|
|
5303
|
+
}
|
|
5147
5304
|
);
|
|
5148
|
-
if (after2.
|
|
5305
|
+
if (after2.kind === "completed") {
|
|
5149
5306
|
observations.push(...after2.observations);
|
|
5150
|
-
|
|
5151
|
-
if (!observedJournal) {
|
|
5152
|
-
await writeObserved(after2, journal);
|
|
5153
|
-
}
|
|
5154
|
-
await releaseObservedAttempt(after2);
|
|
5155
|
-
completed.push(journal);
|
|
5307
|
+
completed.push(after2.journal);
|
|
5156
5308
|
continue;
|
|
5157
5309
|
}
|
|
5158
|
-
await releaseObservedAttempt(after2);
|
|
5159
5310
|
return unknownResult({
|
|
5160
5311
|
step,
|
|
5161
5312
|
completed,
|
|
5162
5313
|
observations,
|
|
5163
|
-
detail: after2.
|
|
5314
|
+
detail: after2.detail
|
|
5164
5315
|
});
|
|
5165
5316
|
}
|
|
5166
5317
|
if (transactional) {
|
|
5167
|
-
const before2 = await
|
|
5318
|
+
const before2 = await withObservedStep(
|
|
5168
5319
|
registry,
|
|
5169
5320
|
step,
|
|
5170
5321
|
input.target,
|
|
5171
5322
|
baseContext,
|
|
5172
|
-
"before"
|
|
5323
|
+
"before",
|
|
5324
|
+
async (observation) => ({
|
|
5325
|
+
kind: observation.ok && fingerprintMatches(step.expectedBefore, observation.fingerprint) ? "resume-required" : "unmatched",
|
|
5326
|
+
observations: observation.ok ? observation.observations : []
|
|
5327
|
+
})
|
|
5173
5328
|
);
|
|
5174
|
-
if (before2.
|
|
5329
|
+
if (before2.kind === "resume-required") {
|
|
5175
5330
|
observations.push(...before2.observations);
|
|
5176
|
-
await releaseObservedAttempt(before2);
|
|
5177
5331
|
return resumeRequiredResult({
|
|
5178
5332
|
step,
|
|
5179
5333
|
completed,
|
|
5180
5334
|
observations
|
|
5181
5335
|
});
|
|
5182
5336
|
}
|
|
5183
|
-
await
|
|
5184
|
-
const after2 = await observeStep(
|
|
5337
|
+
const after2 = await withObservedStep(
|
|
5185
5338
|
registry,
|
|
5186
5339
|
step,
|
|
5187
5340
|
input.target,
|
|
5188
5341
|
baseContext,
|
|
5189
|
-
"after"
|
|
5342
|
+
"after",
|
|
5343
|
+
async (observation) => {
|
|
5344
|
+
if (!observation.ok || !fingerprintMatches(step.expectedAfter, observation.fingerprint)) {
|
|
5345
|
+
return { kind: "unmatched" };
|
|
5346
|
+
}
|
|
5347
|
+
const journal = completedJournal(
|
|
5348
|
+
intent,
|
|
5349
|
+
void 0,
|
|
5350
|
+
observation.observations
|
|
5351
|
+
);
|
|
5352
|
+
await observation.writeJournal(journal);
|
|
5353
|
+
return {
|
|
5354
|
+
kind: "completed",
|
|
5355
|
+
observations: observation.observations,
|
|
5356
|
+
journal
|
|
5357
|
+
};
|
|
5358
|
+
}
|
|
5190
5359
|
);
|
|
5191
|
-
if (after2.
|
|
5360
|
+
if (after2.kind === "completed") {
|
|
5192
5361
|
observations.push(...after2.observations);
|
|
5193
|
-
|
|
5194
|
-
await writeObserved(after2, journal);
|
|
5195
|
-
await releaseObservedAttempt(after2);
|
|
5196
|
-
completed.push(journal);
|
|
5362
|
+
completed.push(after2.journal);
|
|
5197
5363
|
continue;
|
|
5198
5364
|
}
|
|
5199
|
-
await releaseObservedAttempt(after2);
|
|
5200
5365
|
return unknownResult({
|
|
5201
5366
|
step,
|
|
5202
5367
|
completed,
|
|
@@ -5204,39 +5369,53 @@ async function resumeTransitionRun(registry, input) {
|
|
|
5204
5369
|
detail: "transactional intent had no completion and current state matches neither expectedBefore nor expectedAfter"
|
|
5205
5370
|
});
|
|
5206
5371
|
}
|
|
5207
|
-
const after = await
|
|
5372
|
+
const after = await withObservedStep(
|
|
5208
5373
|
registry,
|
|
5209
5374
|
step,
|
|
5210
5375
|
input.target,
|
|
5211
5376
|
baseContext,
|
|
5212
|
-
"after"
|
|
5377
|
+
"after",
|
|
5378
|
+
async (observation) => {
|
|
5379
|
+
if (!observation.ok || !fingerprintMatches(step.expectedAfter, observation.fingerprint)) {
|
|
5380
|
+
return { kind: "unmatched" };
|
|
5381
|
+
}
|
|
5382
|
+
const journal = completedJournal(
|
|
5383
|
+
intent,
|
|
5384
|
+
void 0,
|
|
5385
|
+
observation.observations
|
|
5386
|
+
);
|
|
5387
|
+
await observation.writeJournal(journal);
|
|
5388
|
+
return {
|
|
5389
|
+
kind: "completed",
|
|
5390
|
+
observations: observation.observations,
|
|
5391
|
+
journal
|
|
5392
|
+
};
|
|
5393
|
+
}
|
|
5213
5394
|
);
|
|
5214
|
-
if (after.
|
|
5395
|
+
if (after.kind === "completed") {
|
|
5215
5396
|
observations.push(...after.observations);
|
|
5216
|
-
|
|
5217
|
-
await writeObserved(after, journal);
|
|
5218
|
-
await releaseObservedAttempt(after);
|
|
5219
|
-
completed.push(journal);
|
|
5397
|
+
completed.push(after.journal);
|
|
5220
5398
|
continue;
|
|
5221
5399
|
}
|
|
5222
|
-
await
|
|
5223
|
-
const before = await observeStep(
|
|
5400
|
+
const before = await withObservedStep(
|
|
5224
5401
|
registry,
|
|
5225
5402
|
step,
|
|
5226
5403
|
input.target,
|
|
5227
5404
|
baseContext,
|
|
5228
|
-
"before"
|
|
5405
|
+
"before",
|
|
5406
|
+
async (observation) => ({
|
|
5407
|
+
kind: observation.ok && fingerprintMatches(step.expectedBefore, observation.fingerprint) ? "resume-required" : "unmatched",
|
|
5408
|
+
observations: observation.ok ? observation.observations : []
|
|
5409
|
+
})
|
|
5229
5410
|
);
|
|
5230
|
-
if (before.
|
|
5411
|
+
if (before.kind === "resume-required") {
|
|
5231
5412
|
observations.push(...before.observations);
|
|
5232
|
-
await releaseObservedAttempt(before);
|
|
5233
5413
|
return resumeRequiredResult({
|
|
5234
5414
|
step,
|
|
5235
5415
|
completed,
|
|
5236
5416
|
observations
|
|
5237
5417
|
});
|
|
5238
5418
|
}
|
|
5239
|
-
await releaseObservedAttempt(before);
|
|
5240
5419
|
return unknownResult({
|
|
5241
5420
|
step,
|
|
5242
5421
|
completed,
|
|
@@ -5801,16 +5980,25 @@ function createApplier(registry) {
|
|
|
5801
5980
|
);
|
|
5802
5981
|
}
|
|
5803
5982
|
let client;
|
|
5983
|
+
let lease;
|
|
5804
5984
|
let committed = false;
|
|
5805
5985
|
let transactionStarted = false;
|
|
5806
|
-
let
|
|
5986
|
+
let releaseFailure;
|
|
5807
5987
|
let active = first;
|
|
5808
5988
|
let activeContext = runtimeContext;
|
|
5809
5989
|
let activeOperationAttempted = false;
|
|
5810
5990
|
let activeNonRollbackableOperationExecuted = false;
|
|
5811
5991
|
const completedInSegment = [];
|
|
5992
|
+
if (!isTransitionLessor(target)) {
|
|
5993
|
+
return resultWithCommittedJournals({
|
|
5994
|
+
assessment: transitionLessorRejectionAssessment(APPLIER_ARTIFACT),
|
|
5995
|
+
journals: [],
|
|
5996
|
+
observations: []
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5812
5999
|
try {
|
|
5813
|
-
|
|
6000
|
+
lease = await acquireTransitionLease(target);
|
|
6001
|
+
client = { opaqueClient: lease.session };
|
|
5814
6002
|
const executionClient = client;
|
|
5815
6003
|
if (transactional) {
|
|
5816
6004
|
await segmentCoordinator.begin(executionClient);
|
|
@@ -6361,7 +6549,7 @@ function createApplier(registry) {
|
|
|
6361
6549
|
journals.push(journal);
|
|
6362
6550
|
}
|
|
6363
6551
|
} catch (error) {
|
|
6364
|
-
|
|
6552
|
+
releaseFailure = { error };
|
|
6365
6553
|
if (error instanceof CommitOutcomeUncertainError) {
|
|
6366
6554
|
if (client && transactionStarted) {
|
|
6367
6555
|
await segmentCoordinator.rollback(client).catch(() => void 0);
|
|
@@ -6608,11 +6796,8 @@ function createApplier(registry) {
|
|
|
6608
6796
|
outcomeDurable: true
|
|
6609
6797
|
});
|
|
6610
6798
|
} finally {
|
|
6611
|
-
if (
|
|
6612
|
-
|
|
6613
|
-
await segmentCoordinator.release(client, releaseError);
|
|
6614
|
-
} catch {
|
|
6615
|
-
}
|
|
6799
|
+
if (lease) {
|
|
6800
|
+
await lease.release(releaseFailure);
|
|
6616
6801
|
}
|
|
6617
6802
|
}
|
|
6618
6803
|
}
|
|
@@ -9674,22 +9859,8 @@ function validateIssuedObservation(observation, context) {
|
|
|
9674
9859
|
detail: `observation ${observation.id ?? "unknown"} has an invalid role`
|
|
9675
9860
|
};
|
|
9676
9861
|
}
|
|
9677
|
-
function transitionPool(target) {
|
|
9678
|
-
if (isJsonObject3(target) && typeof target.connect === "function" && typeof target.release !== "function") {
|
|
9679
|
-
return target;
|
|
9680
|
-
}
|
|
9681
|
-
throw new Error(
|
|
9682
|
-
"transition proof target must be a Pool-like object with connect(); checked-out clients are not accepted"
|
|
9683
|
-
);
|
|
9684
|
-
}
|
|
9685
9862
|
async function checkoutProofClient(target) {
|
|
9686
|
-
|
|
9687
|
-
if (!isJsonObject3(client) || typeof client.query !== "function" || typeof client.release !== "function") {
|
|
9688
|
-
throw new Error(
|
|
9689
|
-
"transition proof pool returned a client without query() and release()"
|
|
9690
|
-
);
|
|
9691
|
-
}
|
|
9692
|
-
return client;
|
|
9863
|
+
return acquireTransitionLease(target);
|
|
9693
9864
|
}
|
|
9694
9865
|
function conclusionForObligation(obligation, evidence, expectedContext) {
|
|
9695
9866
|
const result = concludeEvidenceForObligation({
|
|
@@ -10326,13 +10497,15 @@ async function proveTransitions(registry, compare, target, context, initialState
|
|
|
10326
10497
|
let minServerVersionRequests = /* @__PURE__ */ new Map();
|
|
10327
10498
|
const obligationClaimByCanonicalKey = /* @__PURE__ */ new Map();
|
|
10328
10499
|
const multiCandidateSnapshot = !initialState && compare.candidates.length > 1;
|
|
10500
|
+
let sharedLease;
|
|
10329
10501
|
let sharedClient;
|
|
10330
|
-
let
|
|
10502
|
+
let sharedReleaseFailure;
|
|
10331
10503
|
const sharedIssuedRequestKeys = /* @__PURE__ */ new Set();
|
|
10332
10504
|
let sharedIssued = { evidence: [], advisory: [] };
|
|
10333
10505
|
try {
|
|
10334
10506
|
if (multiCandidateSnapshot) {
|
|
10335
|
-
|
|
10507
|
+
sharedLease = await checkoutProofClient(target);
|
|
10508
|
+
sharedClient = sharedLease.session;
|
|
10336
10509
|
const allRequiredObservations = [];
|
|
10337
10510
|
for (const candidate of compare.candidates) {
|
|
10338
10511
|
const rule = registry.resolveRule(candidate.rule);
|
|
@@ -10506,10 +10679,12 @@ async function proveTransitions(registry, compare, target, context, initialState
|
|
|
10506
10679
|
issued = appendIssued(sharedIssued, additional);
|
|
10507
10680
|
sharedIssued = appendIssued(sharedIssued, additional);
|
|
10508
10681
|
} else {
|
|
10682
|
+
let lease;
|
|
10509
10683
|
let client;
|
|
10510
|
-
let
|
|
10684
|
+
let releaseFailure;
|
|
10511
10685
|
try {
|
|
10512
|
-
|
|
10686
|
+
lease = await checkoutProofClient(target);
|
|
10687
|
+
client = lease.session;
|
|
10513
10688
|
proofContext = issuer.readContext ? await issuer.readContext(client, context, requiredObservations) : context;
|
|
10514
10689
|
proofContext = registry.contextWithDerivedCapabilities(proofContext);
|
|
10515
10690
|
const supportMismatch = ruleSupportMismatch(rule, proofContext);
|
|
@@ -10529,7 +10704,7 @@ async function proveTransitions(registry, compare, target, context, initialState
|
|
|
10529
10704
|
proofContext
|
|
10530
10705
|
);
|
|
10531
10706
|
} catch (error) {
|
|
10532
|
-
|
|
10707
|
+
releaseFailure = { error };
|
|
10533
10708
|
return {
|
|
10534
10709
|
kind: "blocked",
|
|
10535
10710
|
assessment: artifactMismatch(
|
|
@@ -10538,8 +10713,8 @@ async function proveTransitions(registry, compare, target, context, initialState
|
|
|
10538
10713
|
)
|
|
10539
10714
|
};
|
|
10540
10715
|
} finally {
|
|
10541
|
-
if (
|
|
10542
|
-
|
|
10716
|
+
if (lease) {
|
|
10717
|
+
await lease.release(releaseFailure);
|
|
10543
10718
|
}
|
|
10544
10719
|
}
|
|
10545
10720
|
}
|
|
@@ -10886,7 +11061,7 @@ async function proveTransitions(registry, compare, target, context, initialState
|
|
|
10886
11061
|
planAssumptions.push(...assumptions2);
|
|
10887
11062
|
}
|
|
10888
11063
|
} catch (error) {
|
|
10889
|
-
|
|
11064
|
+
sharedReleaseFailure = { error };
|
|
10890
11065
|
return {
|
|
10891
11066
|
kind: "blocked",
|
|
10892
11067
|
assessment: artifactMismatch(
|
|
@@ -10895,8 +11070,8 @@ async function proveTransitions(registry, compare, target, context, initialState
|
|
|
10895
11070
|
)
|
|
10896
11071
|
};
|
|
10897
11072
|
} finally {
|
|
10898
|
-
if (
|
|
10899
|
-
|
|
11073
|
+
if (sharedLease) {
|
|
11074
|
+
await sharedLease.release(sharedReleaseFailure);
|
|
10900
11075
|
}
|
|
10901
11076
|
}
|
|
10902
11077
|
let assumptions;
|
|
@@ -11041,11 +11216,13 @@ async function retryUnknownRecognition(registry, compare, target, context) {
|
|
|
11041
11216
|
]);
|
|
11042
11217
|
const issuer = registry.resolveIssuer(recognition.rule.pack);
|
|
11043
11218
|
if (issuer) {
|
|
11219
|
+
let lease;
|
|
11044
11220
|
let client;
|
|
11045
|
-
let
|
|
11221
|
+
let releaseFailure;
|
|
11046
11222
|
const issuedRequestKeys = /* @__PURE__ */ new Set();
|
|
11047
11223
|
try {
|
|
11048
|
-
|
|
11224
|
+
lease = await checkoutProofClient(target);
|
|
11225
|
+
client = lease.session;
|
|
11049
11226
|
let proofContext2 = issuer.readContext ? await issuer.readContext(client, context, recognitionRequests) : context;
|
|
11050
11227
|
proofContext2 = registry.contextWithDerivedCapabilities(proofContext2);
|
|
11051
11228
|
const supportMismatch2 = ruleSupportMismatch(rule, proofContext2);
|
|
@@ -11152,7 +11329,7 @@ async function retryUnknownRecognition(registry, compare, target, context) {
|
|
|
11152
11329
|
}
|
|
11153
11330
|
);
|
|
11154
11331
|
} catch (error) {
|
|
11155
|
-
|
|
11332
|
+
releaseFailure = { error };
|
|
11156
11333
|
return {
|
|
11157
11334
|
kind: "blocked",
|
|
11158
11335
|
assessment: artifactMismatch(
|
|
@@ -11161,8 +11338,8 @@ async function retryUnknownRecognition(registry, compare, target, context) {
|
|
|
11161
11338
|
)
|
|
11162
11339
|
};
|
|
11163
11340
|
} finally {
|
|
11164
|
-
if (
|
|
11165
|
-
|
|
11341
|
+
if (lease) {
|
|
11342
|
+
await lease.release(releaseFailure);
|
|
11166
11343
|
}
|
|
11167
11344
|
}
|
|
11168
11345
|
}
|
|
@@ -11259,7 +11436,7 @@ function createProver(registry) {
|
|
|
11259
11436
|
case "unsupported":
|
|
11260
11437
|
return { kind: "blocked", assessment: unsupported(compare) };
|
|
11261
11438
|
case "unknown":
|
|
11262
|
-
|
|
11439
|
+
break;
|
|
11263
11440
|
case "ambiguous":
|
|
11264
11441
|
return { kind: "blocked", assessment: ambiguous(compare) };
|
|
11265
11442
|
case "uncomposable":
|
|
@@ -11267,7 +11444,13 @@ function createProver(registry) {
|
|
|
11267
11444
|
case "transitions":
|
|
11268
11445
|
break;
|
|
11269
11446
|
}
|
|
11270
|
-
|
|
11447
|
+
if (!isTransitionLessor(target)) {
|
|
11448
|
+
return {
|
|
11449
|
+
kind: "blocked",
|
|
11450
|
+
assessment: transitionLessorRejectionAssessment(PROVER_ARTIFACT)
|
|
11451
|
+
};
|
|
11452
|
+
}
|
|
11453
|
+
return compare.kind === "unknown" ? retryUnknownRecognition(registry, compare, target, context) : proveTransitions(registry, compare, target, context);
|
|
11271
11454
|
}
|
|
11272
11455
|
};
|
|
11273
11456
|
}
|
|
@@ -11521,6 +11704,10 @@ function projectCompareToSingleCandidate(compare, entry) {
|
|
|
11521
11704
|
}
|
|
11522
11705
|
|
|
11523
11706
|
// src/transition/staged-orchestrator.ts
|
|
11707
|
+
var STAGED_ORCHESTRATOR_ARTIFACT = {
|
|
11708
|
+
id: semanticArtifactId("dbsp.core.transition.staged-orchestrator"),
|
|
11709
|
+
version: "0.1.0"
|
|
11710
|
+
};
|
|
11524
11711
|
function uniqueResources2(resources) {
|
|
11525
11712
|
const byKey = /* @__PURE__ */ new Map();
|
|
11526
11713
|
for (const resource of resources) {
|
|
@@ -11679,6 +11866,20 @@ function createStagedTransitionOrchestrator(registry) {
|
|
|
11679
11866
|
const observations = [];
|
|
11680
11867
|
const completedProgress = /* @__PURE__ */ new Set();
|
|
11681
11868
|
const maxIterations = input.maxIterations ?? 32;
|
|
11869
|
+
const targetRejectionResult = () => resultWithAggregate(
|
|
11870
|
+
transitionLessorRejectionAssessment(STAGED_ORCHESTRATOR_ARTIFACT),
|
|
11871
|
+
journals,
|
|
11872
|
+
observations
|
|
11873
|
+
);
|
|
11874
|
+
const proveAtTargetBoundary = async (compare, context) => {
|
|
11875
|
+
if (!isTransitionLessor(input.target)) {
|
|
11876
|
+
return { kind: "target-rejected" };
|
|
11877
|
+
}
|
|
11878
|
+
return {
|
|
11879
|
+
kind: "proof",
|
|
11880
|
+
proof: await prover.prove(compare, input.target, context)
|
|
11881
|
+
};
|
|
11882
|
+
};
|
|
11682
11883
|
for (let iteration = 0; iteration < maxIterations; iteration += 1) {
|
|
11683
11884
|
const context = await input.readContext();
|
|
11684
11885
|
const current = await input.loadCurrent();
|
|
@@ -11696,7 +11897,14 @@ function createStagedTransitionOrchestrator(registry) {
|
|
|
11696
11897
|
}
|
|
11697
11898
|
if (compare.kind !== "transitions") {
|
|
11698
11899
|
if (compare.kind === "unknown" && hasAppliedWork(journals)) {
|
|
11699
|
-
const
|
|
11900
|
+
const proofAtBoundary2 = await proveAtTargetBoundary(
|
|
11901
|
+
compare,
|
|
11902
|
+
context
|
|
11903
|
+
);
|
|
11904
|
+
if (proofAtBoundary2.kind === "target-rejected") {
|
|
11905
|
+
return targetRejectionResult();
|
|
11906
|
+
}
|
|
11907
|
+
const { proof: proof2 } = proofAtBoundary2;
|
|
11700
11908
|
switch (proof2.kind) {
|
|
11701
11909
|
case "no-drift":
|
|
11702
11910
|
return {
|
|
@@ -11750,7 +11958,14 @@ function createStagedTransitionOrchestrator(registry) {
|
|
|
11750
11958
|
);
|
|
11751
11959
|
}
|
|
11752
11960
|
const segmentCompare = projectCompareToSingleCandidate(compare, ready);
|
|
11753
|
-
const
|
|
11961
|
+
const proofAtBoundary = await proveAtTargetBoundary(
|
|
11962
|
+
segmentCompare,
|
|
11963
|
+
context
|
|
11964
|
+
);
|
|
11965
|
+
if (proofAtBoundary.kind === "target-rejected") {
|
|
11966
|
+
return targetRejectionResult();
|
|
11967
|
+
}
|
|
11968
|
+
const { proof } = proofAtBoundary;
|
|
11754
11969
|
if (proof.kind !== "proven") {
|
|
11755
11970
|
return resultWithAggregate(proof.assessment, journals, observations);
|
|
11756
11971
|
}
|
|
@@ -21559,6 +21774,7 @@ export {
|
|
|
21559
21774
|
SubqueryBuilder,
|
|
21560
21775
|
SubqueryExpression,
|
|
21561
21776
|
TABLE_META,
|
|
21777
|
+
TRANSITION_LESSOR_REJECTION,
|
|
21562
21778
|
TableNotFoundError,
|
|
21563
21779
|
UnhandledTypeInDialect,
|
|
21564
21780
|
UnknownDialectError,
|
|
@@ -21569,6 +21785,7 @@ export {
|
|
|
21569
21785
|
UpdateBuilder,
|
|
21570
21786
|
UpsertBuilder,
|
|
21571
21787
|
WindowBuilder,
|
|
21788
|
+
acquireTransitionLease,
|
|
21572
21789
|
advisoryObservationId,
|
|
21573
21790
|
aggOrderBy,
|
|
21574
21791
|
and,
|
|
@@ -21630,6 +21847,7 @@ export {
|
|
|
21630
21847
|
createRawCteBuilder,
|
|
21631
21848
|
createRecursiveMetadata,
|
|
21632
21849
|
createStagedTransitionOrchestrator,
|
|
21850
|
+
createTransitionLessor,
|
|
21633
21851
|
decapitalize,
|
|
21634
21852
|
defaultIndexName,
|
|
21635
21853
|
defaultLogger,
|
|
@@ -21702,6 +21920,7 @@ export {
|
|
|
21702
21920
|
isSubqueryExpression,
|
|
21703
21921
|
export_isSubqueryRef as isSubqueryRef,
|
|
21704
21922
|
isTableRef,
|
|
21923
|
+
isTransitionLessor,
|
|
21705
21924
|
export_isUpdateIntent as isUpdateIntent,
|
|
21706
21925
|
export_isUpsertIntent as isUpsertIntent,
|
|
21707
21926
|
export_isWhereAnd as isWhereAnd,
|