@astrosheep/keiyaku 4.5.20 → 4.5.21
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/README.md +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +22 -8
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +237 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +6 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +2 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
- package/build/src/akuma/akuma-handle.d.ts +5 -1
- package/build/src/akuma/akuma-handle.js +4 -1
- package/build/src/akuma/akuma-instance.d.ts +7 -2
- package/build/src/akuma/akuma-instance.js +14 -7
- package/build/src/akuma/akuma-observe.d.ts +11 -0
- package/build/src/akuma/akuma-observe.js +22 -0
- package/build/src/akuma/akuma-product.d.ts +1 -0
- package/build/src/akuma/akuma-product.js +3 -0
- package/build/src/akuma/akuma.d.ts +1 -0
- package/build/src/akuma/body.d.ts +25 -5
- package/build/src/akuma/body.js +65 -8
- package/build/src/akuma/call-request.d.ts +2 -0
- package/build/src/akuma/call-request.js +2 -0
- package/build/src/akuma/fleet-execution.d.ts +28 -0
- package/build/src/akuma/fleet-execution.js +36 -4
- package/build/src/akuma/fleet-request.d.ts +10 -0
- package/build/src/akuma/fleet-request.js +11 -2
- package/build/src/akuma/heart/facts.d.ts +2 -0
- package/build/src/akuma/heart/index.d.ts +1 -0
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/rows.d.ts +2 -0
- package/build/src/akuma/heart/rows.js +7 -5
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +3 -1
- package/build/src/akuma/heart/tells.js +6 -5
- package/build/src/akuma/heart/timeline.js +1 -1
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +1 -1
- package/build/src/akuma/providers/acp/core.js +3 -6
- package/build/src/akuma/providers/claude/index.js +9 -12
- package/build/src/akuma/providers/codex-app-server/index.js +4 -11
- package/build/src/akuma/providers/execution-environment.d.ts +6 -0
- package/build/src/akuma/providers/execution-environment.js +24 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +30 -23
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +8 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +6 -5
- package/build/src/akuma/providers/pi/events.js +7 -2
- package/build/src/akuma/providers/pi/index.js +3 -2
- package/build/src/akuma/request-rendezvous.js +8 -3
- package/build/src/akuma/turn-drive.d.ts +1 -0
- package/build/src/akuma/turn-drive.js +2 -0
- package/build/src/akuma-body.js +2 -0
- package/build/src/body/amend.js +6 -4
- package/build/src/body/decode.d.ts +3 -1
- package/build/src/body/decode.js +53 -17
- package/build/src/body/region.d.ts +9 -1
- package/build/src/body/region.js +87 -12
- package/build/src/body/render.js +1 -1
- package/build/src/body/verification.d.ts +3 -1
- package/build/src/body/verification.js +4 -1
- package/build/src/cli/accepted.js +19 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
- package/build/src/cli/commands/akuma-invoke.js +133 -13
- package/build/src/cli/commands/akuma.js +11 -4
- package/build/src/cli/commands/contract-help.js +17 -4
- package/build/src/cli/commands/contract.js +6 -4
- package/build/src/cli/commands/status-set.js +15 -24
- package/build/src/cli/main.js +5 -0
- package/build/src/cli/parse.d.ts +2 -0
- package/build/src/cli/parse.js +5 -0
- package/build/src/cli/render/akuma-activity.d.ts +99 -2
- package/build/src/cli/render/akuma-activity.js +484 -40
- package/build/src/cli/render/akuma.d.ts +10 -0
- package/build/src/cli/render/akuma.js +28 -21
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/board.js +1 -1
- package/build/src/cli/render/catalog.js +16 -13
- package/build/src/cli/render/contract-history.js +39 -10
- package/build/src/cli/render/contract-observation.js +10 -6
- package/build/src/cli/render/contract.js +109 -106
- package/build/src/cli/render/execution-progress.d.ts +23 -1
- package/build/src/cli/render/execution-progress.js +151 -28
- package/build/src/cli/render/kanshi-akuma.js +27 -39
- package/build/src/cli/render/kanshi.js +33 -26
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/render/receipt.d.ts +1 -1
- package/build/src/cli/render/receipt.js +5 -5
- package/build/src/cli/render/refusal.js +10 -7
- package/build/src/cli/render/region.js +1 -1
- package/build/src/cli/render/settings.js +12 -2
- package/build/src/cli/render/status-line.d.ts +30 -0
- package/build/src/cli/render/status-line.js +58 -0
- package/build/src/cli/render/status-set.js +1 -1
- package/build/src/cli/render/task.d.ts +2 -0
- package/build/src/cli/render/task.js +11 -7
- package/build/src/cli/render/terminal.d.ts +0 -1
- package/build/src/cli/render/terminal.js +47 -15
- package/build/src/cli/result.d.ts +1 -0
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +13 -7
- package/build/src/cli/usage.js +2 -2
- package/build/src/cli/version.d.ts +1 -0
- package/build/src/cli/version.js +25 -0
- package/build/src/git/workspace.d.ts +1 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/identity/mint.d.ts +13 -0
- package/build/src/identity/mint.js +26 -0
- package/build/src/identity/normalize.d.ts +4 -0
- package/build/src/identity/normalize.js +30 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/kanshi/read.js +17 -4
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/akuma-creation.d.ts +2 -0
- package/build/src/library/akuma-creation.js +33 -17
- package/build/src/library/bind.js +18 -16
- package/build/src/library/contract-bind.d.ts +3 -1
- package/build/src/library/contract-bind.js +5 -3
- package/build/src/library/contract-operations.d.ts +2 -2
- package/build/src/library/contract-operations.js +1 -1
- package/build/src/library/contract-types.d.ts +1 -0
- package/build/src/library/fleet.d.ts +4 -1
- package/build/src/library/fleet.js +32 -8
- package/build/src/plugin/akuma-signals.d.ts +6 -0
- package/build/src/plugin/akuma-signals.js +8 -0
- package/build/src/plugin/public.d.ts +4 -0
- package/build/src/plugin/runtime.js +4 -1
- package/build/src/protocol/amend.js +4 -3
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/bind.js +41 -14
- package/build/src/protocol/completion.d.ts +3 -0
- package/build/src/protocol/completion.js +7 -1
- package/build/src/protocol/deliver.js +165 -92
- package/build/src/protocol/execution-observation.d.ts +0 -4
- package/build/src/protocol/intent.d.ts +15 -20
- package/build/src/protocol/intent.js +29 -17
- package/build/src/protocol/operations.d.ts +2 -0
- package/build/src/protocol/placement.js +5 -1
- package/build/src/protocol/read/status.d.ts +1 -0
- package/build/src/protocol/read/status.js +10 -2
- package/build/src/protocol/reintegrate.d.ts +1 -1
- package/build/src/protocol/reintegrate.js +70 -43
- package/build/src/protocol/result-codec.js +9 -7
- package/build/src/protocol/review.js +53 -30
- package/build/src/protocol/run.d.ts +83 -36
- package/build/src/protocol/run.js +90 -75
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settings.js +5 -14
- package/build/src/task/document.d.ts +5 -1
- package/build/src/task/document.js +6 -1
- package/build/src/verification/execution.d.ts +0 -1
- package/build/src/verification/execution.js +0 -24
- package/build/src/verification/observation.d.ts +0 -4
- package/build/src/verification/observation.js +1 -2
- package/package.json +3 -1
- package/build/src/git/verification-environment.d.ts +0 -10
- package/build/src/git/verification-environment.js +0 -281
|
@@ -2,7 +2,7 @@ import { materializeIntegrationSnapshot, materializeJudgedConflict, planIntegrat
|
|
|
2
2
|
import { captureTender, dirtyTenderRefusal, materializeTenderSnapshot, prepareDeliveryCommitMetadata, } from "../git/tender.js";
|
|
3
3
|
import { checkoutDetachedSnapshot, recordConflictHandoff, retireConflictHandoff, workspaceMergeStatePresent, worktreePath, conflictRecovery, } from "../git/workspace.js";
|
|
4
4
|
import { observeContractsForAdmissionAt } from "../git/observe.js";
|
|
5
|
-
import {
|
|
5
|
+
import { contractStateWitness, privateStateSeatAttempt, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
|
|
6
6
|
import { contractState } from "../core/facts/observation.js";
|
|
7
7
|
import { decideDeliver } from "../core/verbs/deliver.js";
|
|
8
8
|
import { currentVerifiedAttestation } from "./intent.js";
|
|
@@ -134,52 +134,132 @@ function hasSupersedingVerification(state, journal) {
|
|
|
134
134
|
const verificationIndex = journal.findIndex((entry) => entry.entry === current.entry);
|
|
135
135
|
return deliveryIndex >= 0 && verificationIndex > deliveryIndex;
|
|
136
136
|
}
|
|
137
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Repeatable physical delivery work outside the publication seat: locate the appointed worktree from
|
|
139
|
+
* one non-authoritative private-state read, capture its bytes, and materialize the prepared artifacts.
|
|
140
|
+
*/
|
|
141
|
+
async function prepareExternalDelivery(input) {
|
|
138
142
|
const observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
139
143
|
const state = contractState(observation.decision, input.contractId);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
if (state === null)
|
|
145
|
+
return { kind: "unavailable" };
|
|
146
|
+
return {
|
|
147
|
+
kind: "artifacts",
|
|
148
|
+
witness: contractStateWitness(state),
|
|
149
|
+
artifacts: await prepareDeliveryArtifacts(input, observation, state),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async function prepareDeliveryArtifacts(input, observation, state) {
|
|
153
|
+
const derivation = input.deriveDocument(state);
|
|
154
|
+
if (derivation.verification.kind === "refused")
|
|
155
|
+
return { kind: "defer" };
|
|
156
|
+
if (reusesCurrentCandidate(input, state, derivation))
|
|
157
|
+
return { kind: "defer" };
|
|
158
|
+
if (input.materializeConflict === true && state.terminal === null)
|
|
159
|
+
return { kind: "defer" };
|
|
160
|
+
const captured = await captureAuthorizedDeliveryTender(input.scope, { contractId: state.id, coordinates: state.coordinates }, input.includeDirty);
|
|
161
|
+
if (captured.kind === "refused")
|
|
162
|
+
return { kind: "refused", refusal: captured.refusal };
|
|
163
|
+
const worktree = await worktreeInput(input.scope, state, captured.data);
|
|
164
|
+
if (state.terminal === null &&
|
|
165
|
+
state.delivery !== null &&
|
|
166
|
+
worktree.changeId === state.delivery.data.integration.changeId &&
|
|
167
|
+
!hasSupersedingVerification(state, observation.journals.get(state.id)?.entries ?? [])) {
|
|
168
|
+
return {
|
|
169
|
+
kind: "continuation",
|
|
170
|
+
worktree,
|
|
171
|
+
};
|
|
143
172
|
}
|
|
173
|
+
const prepared = await mechanicalDeliveryPreparation(input, state, derivation, captured.data);
|
|
174
|
+
return prepared.kind === "prepared"
|
|
175
|
+
? { kind: "mechanical", data: prepared.data, worktree: prepared.worktree }
|
|
176
|
+
: { kind: "refused", refusal: prepared.refusal };
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Assemble the in-custody decision input from the fresh Contract. State-derived choices are recomputed
|
|
180
|
+
* here; artifacts the fresh state cannot justify are spent, which restarts the whole preparation.
|
|
181
|
+
*/
|
|
182
|
+
async function assembleDeliveryAttempt(input, observation, external) {
|
|
183
|
+
const state = contractState(observation.decision, input.contractId);
|
|
184
|
+
if (external.kind === "unavailable") {
|
|
185
|
+
return state === null
|
|
186
|
+
? { kind: "assembled", state: null, preparation: { kind: "unavailable" } }
|
|
187
|
+
: { kind: "stale" };
|
|
188
|
+
}
|
|
189
|
+
if (state === null)
|
|
190
|
+
return { kind: "stale" };
|
|
191
|
+
if (external.witness.head !== state.head)
|
|
192
|
+
return { kind: "stale" };
|
|
193
|
+
const derivation = input.deriveDocument(state);
|
|
144
194
|
if (derivation.verification.kind === "refused") {
|
|
145
195
|
return {
|
|
146
|
-
|
|
196
|
+
kind: "assembled",
|
|
147
197
|
state,
|
|
148
198
|
derivation,
|
|
149
199
|
preparation: { kind: "refused", document: derivation.document, refusal: derivation.verification.refusal },
|
|
150
200
|
};
|
|
151
201
|
}
|
|
152
202
|
if (reusesCurrentCandidate(input, state, derivation))
|
|
153
|
-
return {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (
|
|
203
|
+
return { kind: "assembled", state, derivation };
|
|
204
|
+
const artifacts = external.artifacts;
|
|
205
|
+
if (artifacts.kind === "defer")
|
|
206
|
+
return await completeDeferredDelivery(input, state, derivation);
|
|
207
|
+
if (artifacts.kind === "refused") {
|
|
158
208
|
return {
|
|
159
|
-
|
|
209
|
+
kind: "assembled",
|
|
160
210
|
state,
|
|
161
211
|
derivation,
|
|
162
|
-
preparation: { kind: "refused", document: derivation.document, refusal:
|
|
212
|
+
preparation: { kind: "refused", document: derivation.document, refusal: artifacts.refusal },
|
|
163
213
|
};
|
|
164
214
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
215
|
+
if (!sameWorktreeWitness(artifacts.worktree, await recaptureDeliveryWorktree(input, state))) {
|
|
216
|
+
return { kind: "stale" };
|
|
217
|
+
}
|
|
218
|
+
if (artifacts.kind === "continuation") {
|
|
219
|
+
const delivery = state.delivery;
|
|
220
|
+
if (delivery === null)
|
|
221
|
+
return { kind: "stale" };
|
|
170
222
|
return {
|
|
171
|
-
|
|
223
|
+
kind: "assembled",
|
|
172
224
|
state,
|
|
173
225
|
derivation,
|
|
174
|
-
preparation: { kind: "prepared", document: derivation.document, data:
|
|
175
|
-
worktree: capturedWorktree,
|
|
226
|
+
preparation: { kind: "prepared", document: derivation.document, data: delivery.data },
|
|
176
227
|
continuation: true,
|
|
177
228
|
};
|
|
178
229
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
230
|
+
return {
|
|
231
|
+
kind: "assembled",
|
|
232
|
+
state,
|
|
233
|
+
derivation,
|
|
234
|
+
preparation: { kind: "prepared", document: derivation.document, data: artifacts.data },
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Complete a preparation the outside phase could not settle. A requested conflict materialization
|
|
239
|
+
* must retire its owned handoff and then capture the worktree that follows, so it only runs under
|
|
240
|
+
* this custody; every other deferred state is decided by reuse above or refuses on its own.
|
|
241
|
+
*/
|
|
242
|
+
async function completeDeferredDelivery(input, state, derivation) {
|
|
243
|
+
if (input.materializeConflict !== true || state.terminal !== null)
|
|
244
|
+
return { kind: "assembled", state, derivation };
|
|
245
|
+
const materialization = await materializationMergeStateRefusal(input);
|
|
246
|
+
if (materialization !== undefined) {
|
|
247
|
+
return {
|
|
248
|
+
kind: "assembled",
|
|
249
|
+
state,
|
|
250
|
+
derivation,
|
|
251
|
+
preparation: { kind: "refused", document: derivation.document, refusal: materialization },
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
const prepared = await mechanicalDeliveryPreparation(input, state, derivation);
|
|
255
|
+
return {
|
|
256
|
+
kind: "assembled",
|
|
257
|
+
state,
|
|
258
|
+
derivation,
|
|
259
|
+
preparation: prepared.kind === "prepared"
|
|
260
|
+
? { kind: "prepared", document: derivation.document, data: prepared.data }
|
|
261
|
+
: prepared,
|
|
262
|
+
};
|
|
183
263
|
}
|
|
184
264
|
function reusesCurrentCandidate(input, state, derivation) {
|
|
185
265
|
return (input.overwrite !== true &&
|
|
@@ -189,60 +269,54 @@ function reusesCurrentCandidate(input, state, derivation) {
|
|
|
189
269
|
derivation.verification.data !== null &&
|
|
190
270
|
currentVerifiedAttestation(state) === undefined);
|
|
191
271
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
return
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
272
|
+
/** Accept a delivery whose current candidate is already admitted, without admitting it again. */
|
|
273
|
+
function currentCandidateDeliveryDecision(input, observation, assembled) {
|
|
274
|
+
const state = assembled.state;
|
|
275
|
+
if (state === null || assembled.derivation === undefined)
|
|
276
|
+
return undefined;
|
|
277
|
+
if (!reusesCurrentCandidate(input, state, assembled.derivation))
|
|
278
|
+
return undefined;
|
|
279
|
+
const record = observation.journals.get(input.contractId);
|
|
280
|
+
const delivery = record?.entries.findLast((entry) => entry.kind === "deliver");
|
|
281
|
+
if (record === undefined || delivery === undefined)
|
|
282
|
+
throw new Error("current delivery is missing its journal fact");
|
|
283
|
+
input.progress?.recordAdmission({ kind: "accepted", facts: [], state, journal: record.entries });
|
|
284
|
+
return {
|
|
285
|
+
kind: "accepted",
|
|
286
|
+
facts: [],
|
|
287
|
+
state,
|
|
288
|
+
journal: record.entries,
|
|
289
|
+
value: {
|
|
290
|
+
...state.delivery.data,
|
|
291
|
+
leading: { kind: "already-admitted", fact: delivery.entry },
|
|
292
|
+
},
|
|
293
|
+
};
|
|
205
294
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const delivery = record?.entries.findLast((entry) => entry.kind === "deliver");
|
|
213
|
-
if (record === undefined || delivery === undefined)
|
|
214
|
-
throw new Error("current delivery is missing its journal fact");
|
|
215
|
-
input.progress?.recordAdmission({ kind: "accepted", facts: [], state: currentState, journal: record.entries });
|
|
216
|
-
return {
|
|
217
|
-
kind: "accepted",
|
|
218
|
-
facts: [],
|
|
219
|
-
state: currentState,
|
|
220
|
-
journal: record.entries,
|
|
221
|
-
value: {
|
|
222
|
-
...currentState.delivery.data,
|
|
223
|
-
leading: { kind: "already-admitted", fact: delivery.entry },
|
|
224
|
-
},
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
if (speculated.continuation === true) {
|
|
228
|
-
const record = observation.journals.get(input.contractId);
|
|
229
|
-
if (record === undefined ||
|
|
230
|
-
record.state === null ||
|
|
231
|
-
record.state.delivery === null ||
|
|
232
|
-
speculated.derivation === undefined) {
|
|
233
|
-
return { kind: "redecide" };
|
|
234
|
-
}
|
|
235
|
-
const state = record.state;
|
|
236
|
-
input.progress?.recordAdmission({ kind: "accepted", facts: [], state, journal: record.entries });
|
|
237
|
-
return {
|
|
238
|
-
kind: "accepted",
|
|
239
|
-
facts: [],
|
|
240
|
-
state,
|
|
241
|
-
journal: record.entries,
|
|
242
|
-
value: record.state.delivery.data,
|
|
243
|
-
};
|
|
295
|
+
/** Continue the admitted integration this worktree already carries, without a new offer. */
|
|
296
|
+
function continuationDeliveryDecision(input, observation, assembled) {
|
|
297
|
+
const record = observation.journals.get(input.contractId);
|
|
298
|
+
const state = record?.state ?? null;
|
|
299
|
+
if (record === undefined || state === null || state.delivery === null || assembled.derivation === undefined) {
|
|
300
|
+
return { kind: "redecide" };
|
|
244
301
|
}
|
|
245
|
-
|
|
302
|
+
input.progress?.recordAdmission({ kind: "accepted", facts: [], state, journal: record.entries });
|
|
303
|
+
return {
|
|
304
|
+
kind: "accepted",
|
|
305
|
+
facts: [],
|
|
306
|
+
state,
|
|
307
|
+
journal: record.entries,
|
|
308
|
+
value: state.delivery.data,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
async function decideAndAdmitDelivery(input, attempt, seat, observation, assembled) {
|
|
312
|
+
const current = currentCandidateDeliveryDecision(input, observation, assembled);
|
|
313
|
+
if (current !== undefined)
|
|
314
|
+
return current;
|
|
315
|
+
if (assembled.continuation === true)
|
|
316
|
+
return continuationDeliveryDecision(input, observation, assembled);
|
|
317
|
+
const preparation = assembled.preparation ?? STALE_PRIVATE_STATE_PREPARATION;
|
|
318
|
+
if (preparation.kind === "stale")
|
|
319
|
+
return preparation;
|
|
246
320
|
const decision = decideDeliver({
|
|
247
321
|
input: {
|
|
248
322
|
contractId: input.contractId,
|
|
@@ -274,22 +348,19 @@ async function decideAndAdmitDelivery(input, attempt, seat, observation, specula
|
|
|
274
348
|
value: preparation.data,
|
|
275
349
|
};
|
|
276
350
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const state = contractState(fresh.decision, input.contractId);
|
|
282
|
-
if (state === null)
|
|
283
|
-
return false;
|
|
284
|
-
return sameSpeculativeWorktreeInput(speculated.worktree, await recaptureDeliveryWorktree(input, state));
|
|
285
|
-
});
|
|
286
|
-
return "kind" in observation
|
|
287
|
-
? observation
|
|
288
|
-
: await decideAndAdmitDelivery(input, attempt, seat, observation, speculated);
|
|
289
|
-
}
|
|
351
|
+
/**
|
|
352
|
+
* One delivery attempt: the repeatable physical preparation happens outside custody, then a single
|
|
353
|
+
* in-custody observation, witness validation, assembly, decision, and atomic publication.
|
|
354
|
+
*/
|
|
290
355
|
async function deliverAttempt(input, attempt) {
|
|
291
|
-
const
|
|
292
|
-
return await privateStateSeatAttempt(input.scope, async (seat) =>
|
|
356
|
+
const external = await prepareExternalDelivery(input);
|
|
357
|
+
return await privateStateSeatAttempt(input.scope, async (seat) => {
|
|
358
|
+
const observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
359
|
+
const assembled = await assembleDeliveryAttempt(input, observation, external);
|
|
360
|
+
if (assembled.kind === "stale")
|
|
361
|
+
return STALE_PRIVATE_STATE_PREPARATION;
|
|
362
|
+
return await decideAndAdmitDelivery(input, attempt, seat, observation, assembled);
|
|
363
|
+
}, attemptDecisionWithSeatClose);
|
|
293
364
|
}
|
|
294
365
|
function isIntegrationConflict(refusal) {
|
|
295
366
|
return refusal.kind === "integration-failed" && refusal.reason === "conflict";
|
|
@@ -417,6 +488,8 @@ export async function admitDeliveryOperation(input) {
|
|
|
417
488
|
return await finishDeliverRefusal(input, result.refusal);
|
|
418
489
|
if (result.kind === "publication-failed")
|
|
419
490
|
return { kind: "retry", reason: result };
|
|
491
|
+
if (result.kind === "stale" || result.kind === "redecide")
|
|
492
|
+
continue;
|
|
420
493
|
if (result.kind === "collision" && index + 1 === attempts.length)
|
|
421
494
|
return { kind: "retry", reason: result };
|
|
422
495
|
}
|
|
@@ -128,12 +128,10 @@ declare const observationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
128
128
|
phase: z.ZodEnum<{
|
|
129
129
|
cleanup: "cleanup";
|
|
130
130
|
materialize: "materialize";
|
|
131
|
-
environment: "environment";
|
|
132
131
|
setup: "setup";
|
|
133
132
|
declaration: "declaration";
|
|
134
133
|
}>;
|
|
135
134
|
cwd: z.ZodOptional<z.ZodString>;
|
|
136
|
-
source: z.ZodOptional<z.ZodString>;
|
|
137
135
|
name: z.ZodOptional<z.ZodString>;
|
|
138
136
|
command: z.ZodOptional<z.ZodString>;
|
|
139
137
|
index: z.ZodOptional<z.ZodNumber>;
|
|
@@ -148,12 +146,10 @@ declare const observationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
148
146
|
phase: z.ZodEnum<{
|
|
149
147
|
cleanup: "cleanup";
|
|
150
148
|
materialize: "materialize";
|
|
151
|
-
environment: "environment";
|
|
152
149
|
setup: "setup";
|
|
153
150
|
declaration: "declaration";
|
|
154
151
|
}>;
|
|
155
152
|
cwd: z.ZodOptional<z.ZodString>;
|
|
156
|
-
source: z.ZodOptional<z.ZodString>;
|
|
157
153
|
name: z.ZodOptional<z.ZodString>;
|
|
158
154
|
command: z.ZodOptional<z.ZodString>;
|
|
159
155
|
index: z.ZodOptional<z.ZodNumber>;
|
|
@@ -2,7 +2,6 @@ import type { ExecutionProgress } from "./progress.js";
|
|
|
2
2
|
import type { GitDecisionObservation } from "../git/observe.js";
|
|
3
3
|
import type { GitDecodeChannel, GitTreeSelection } from "../git/read-observation.js";
|
|
4
4
|
import type { GitRepository } from "../git/process.js";
|
|
5
|
-
import type { GitRefAssertion } from "../git/repository.js";
|
|
6
5
|
import { type WorktreeLeak } from "../git/scratch.js";
|
|
7
6
|
import type { HookFailure } from "../git/hooks.js";
|
|
8
7
|
import type { DecideInput, OfferDecision } from "../core/decide.js";
|
|
@@ -10,36 +9,32 @@ import type { ActorId, ContractId, ContractState, EntryUlid, SnapshotId } from "
|
|
|
10
9
|
import { type AttestationRefusal } from "../core/verbs/attestation.js";
|
|
11
10
|
import { type CapturedOutput } from "../verification/execution.js";
|
|
12
11
|
import { type VerificationDefinition } from "../verification/declaration.js";
|
|
13
|
-
import { type CompanionDecorator, type ProtocolResult } from "./run.js";
|
|
14
|
-
type
|
|
12
|
+
import { type CompanionDecorator, type ProtocolPreparation, type ProtocolResult } from "./run.js";
|
|
13
|
+
type CommonIntentAdmissionOptions<Refusal> = Readonly<{
|
|
15
14
|
progress?: ExecutionProgress;
|
|
16
15
|
observedContracts?: readonly ContractId[];
|
|
17
16
|
observe?: (repository: GitRepository, channel: GitDecodeChannel, contracts: readonly ContractId[]) => Promise<GitDecisionObservation>;
|
|
18
17
|
decorateOffer?: CompanionDecorator;
|
|
19
18
|
validateAdmission?: (observation: GitDecisionObservation) => Refusal | undefined | Promise<Refusal | undefined>;
|
|
20
19
|
observationSelection?: GitTreeSelection;
|
|
21
|
-
prepareInput?: (observation: GitDecisionObservation, input: Seed) => Readonly<{
|
|
22
|
-
kind: "prepared";
|
|
23
|
-
input: Input;
|
|
24
|
-
assertions?: readonly GitRefAssertion[];
|
|
25
|
-
}> | Readonly<{
|
|
26
|
-
kind: "refused";
|
|
27
|
-
refusal: Refusal;
|
|
28
|
-
}> | Promise<Readonly<{
|
|
29
|
-
kind: "prepared";
|
|
30
|
-
input: Input;
|
|
31
|
-
assertions?: readonly GitRefAssertion[];
|
|
32
|
-
}> | Readonly<{
|
|
33
|
-
kind: "refused";
|
|
34
|
-
refusal: Refusal;
|
|
35
|
-
}>>;
|
|
36
20
|
}>;
|
|
37
|
-
|
|
21
|
+
type IntentAdmissionOptions<Refusal = never> = CommonIntentAdmissionOptions<Refusal>;
|
|
22
|
+
type PreparedIntentAdmissionOptions<Input, Refusal, Seed, Prepared> = CommonIntentAdmissionOptions<Refusal> & Readonly<{
|
|
23
|
+
preparation: ProtocolPreparation<Input, Refusal, Seed, Prepared>;
|
|
24
|
+
}>;
|
|
25
|
+
/** Observe, decide, and atomically admit one intent whose invocation already is its decision input. */
|
|
38
26
|
export declare function admitIntent<Input extends Readonly<{
|
|
39
27
|
contractId: ContractId;
|
|
28
|
+
}>, Refusal>(channel: GitDecodeChannel, repository: GitRepository, input: Input, decide: (input: DecideInput<Input>) => OfferDecision<Refusal>, options?: IntentAdmissionOptions<Refusal>): Promise<ProtocolResult<Refusal>>;
|
|
29
|
+
/**
|
|
30
|
+
* Observe, decide, and atomically admit one intent whose repeatable preparation happens outside
|
|
31
|
+
* the publication seat and whose decision input is assembled from the fresh in-custody observation.
|
|
32
|
+
*/
|
|
33
|
+
export declare function admitPreparedIntent<Input extends Readonly<{
|
|
34
|
+
contractId: ContractId;
|
|
40
35
|
}>, Refusal, Seed extends Readonly<{
|
|
41
36
|
contractId: ContractId;
|
|
42
|
-
}
|
|
37
|
+
}>, Prepared>(channel: GitDecodeChannel, repository: GitRepository, input: Seed, decide: (input: DecideInput<Input>) => OfferDecision<Refusal>, options: PreparedIntentAdmissionOptions<Input, Refusal, Seed, Prepared>): Promise<ProtocolResult<Refusal>>;
|
|
43
38
|
type VerifyDeliveryInput = Readonly<{
|
|
44
39
|
channel: GitDecodeChannel;
|
|
45
40
|
repository: GitRepository;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { materializeScratchCandidate } from "../git/scratch.js";
|
|
2
2
|
import { projectSettings } from "../settings.js";
|
|
3
|
-
import { readManagedWorktreeAppointment } from "../workspace-place.js";
|
|
4
3
|
import { dependencyKeySet } from "../core/subject.js";
|
|
5
4
|
import { latestCurrentAttestations } from "../core/facts/gate.js";
|
|
6
5
|
import { decideAttestation } from "../core/verbs/attestation.js";
|
|
@@ -8,22 +7,44 @@ import { executeVerification, capturedOutput, } from "../verification/execution.
|
|
|
8
7
|
import { VERIFIED } from "../verification/declaration.js";
|
|
9
8
|
import { runProtocol } from "./run.js";
|
|
10
9
|
import { mintAttempts } from "./attempt.js";
|
|
11
|
-
|
|
10
|
+
function admissionOptions(options) {
|
|
11
|
+
return {
|
|
12
|
+
...(options.progress === undefined ? {} : { progress: options.progress }),
|
|
13
|
+
...(options.observedContracts === undefined ? {} : { observedContracts: options.observedContracts }),
|
|
14
|
+
...(options.observe === undefined ? {} : { observe: options.observe }),
|
|
15
|
+
...(options.decorateOffer === undefined ? {} : { decorateOffer: options.decorateOffer }),
|
|
16
|
+
...(options.validateAdmission === undefined ? {} : { validateAdmission: options.validateAdmission }),
|
|
17
|
+
...(options.observationSelection === undefined ? {} : { observationSelection: options.observationSelection }),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** Observe, decide, and atomically admit one intent whose invocation already is its decision input. */
|
|
12
21
|
export function admitIntent(channel, repository, input, decide, options = {}) {
|
|
13
22
|
const contracts = options.observedContracts ?? [input.contractId];
|
|
14
23
|
return runProtocol({
|
|
24
|
+
...admissionOptions(options),
|
|
15
25
|
input,
|
|
16
26
|
channel,
|
|
17
27
|
repository,
|
|
18
28
|
contracts,
|
|
19
29
|
attempts: mintAttempts({ entryCount: 2 }),
|
|
20
30
|
decide,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Observe, decide, and atomically admit one intent whose repeatable preparation happens outside
|
|
35
|
+
* the publication seat and whose decision input is assembled from the fresh in-custody observation.
|
|
36
|
+
*/
|
|
37
|
+
export function admitPreparedIntent(channel, repository, input, decide, options) {
|
|
38
|
+
const contracts = options.observedContracts ?? [input.contractId];
|
|
39
|
+
return runProtocol({
|
|
40
|
+
...admissionOptions(options),
|
|
41
|
+
input,
|
|
42
|
+
preparation: options.preparation,
|
|
43
|
+
channel,
|
|
44
|
+
repository,
|
|
45
|
+
contracts,
|
|
46
|
+
attempts: mintAttempts({ entryCount: 2 }),
|
|
47
|
+
decide,
|
|
27
48
|
});
|
|
28
49
|
}
|
|
29
50
|
function runtimeStop(outcome) {
|
|
@@ -98,21 +119,12 @@ export async function verifyDelivery(input) {
|
|
|
98
119
|
{ kind: "snapshot", value: snapshot },
|
|
99
120
|
{ kind: "segment", value: input.verification.segment },
|
|
100
121
|
]);
|
|
101
|
-
const appointment = await readManagedWorktreeAppointment(input.repository, input.contractId);
|
|
102
|
-
if (appointment.kind !== "appointed")
|
|
103
|
-
return {
|
|
104
|
-
step: {
|
|
105
|
-
failure: "environment-failure",
|
|
106
|
-
diagnostic: appointment.kind === "failed" ? appointment.diagnostic : "Verification environment source is not appointed",
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
122
|
const execution = await executeVerification({
|
|
110
123
|
repository: input.repository,
|
|
111
124
|
candidate: snapshot,
|
|
112
125
|
declarations: input.verification.declarations,
|
|
113
126
|
materializeScratchCandidate,
|
|
114
127
|
projectSettings,
|
|
115
|
-
environmentSource: appointment.path,
|
|
116
128
|
observe: (observation) => input.progress?.observe({ kind: "verification", contractId: input.contractId, snapshot, observation }),
|
|
117
129
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
118
130
|
});
|
|
@@ -103,6 +103,8 @@ export type AttemptDecision<Value, Refusal = IntentRefusal> = (AcceptedAdmission
|
|
|
103
103
|
refusal: Refusal;
|
|
104
104
|
}> | Readonly<{
|
|
105
105
|
kind: "redecide";
|
|
106
|
+
}> | Readonly<{
|
|
107
|
+
kind: "stale";
|
|
106
108
|
}> | Readonly<{
|
|
107
109
|
kind: "collision";
|
|
108
110
|
}> | Extract<DecidedOfferResult, {
|
|
@@ -49,7 +49,7 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
49
49
|
const result = placementResultWithSeatClose(await withPrivateStatePublicationSeat(repository, async (seat) => {
|
|
50
50
|
// The hint carries no acceptance authority. Form a fresh semantic offer under the seat.
|
|
51
51
|
const prepared = await prepareProtocolAttempt(protocol, protocol.attempts[index]);
|
|
52
|
-
if (prepared.kind
|
|
52
|
+
if (prepared.kind !== "offered")
|
|
53
53
|
return prepared;
|
|
54
54
|
const state = contractState(prepared.observation.decision, input.contractId);
|
|
55
55
|
if (state === null)
|
|
@@ -68,6 +68,8 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
68
68
|
observedTreeEqualsCandidate: await observedTreeEqualsCandidate(repository, observed, target.newOid),
|
|
69
69
|
};
|
|
70
70
|
if (changes?.predecessor !== target.expectedOid || changes.candidate !== target.newOid)
|
|
71
|
+
// A target preparation computed before custody is spent once the fresh offer names another
|
|
72
|
+
// movement. Re-derive it on the next attempt; never publish a preparation for stale bytes.
|
|
71
73
|
return { kind: "changed-preparation", target };
|
|
72
74
|
const physical = await prepareTargetPlacement(repository, state, target, changes);
|
|
73
75
|
if (physical.kind === "refused")
|
|
@@ -92,6 +94,8 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
92
94
|
}
|
|
93
95
|
if (result.kind === "redecide")
|
|
94
96
|
continue;
|
|
97
|
+
if (result.kind === "stale")
|
|
98
|
+
continue;
|
|
95
99
|
if (result.kind === "collision" && index + 1 < protocol.attempts.length)
|
|
96
100
|
continue;
|
|
97
101
|
if (result.kind !== "accepted")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { observeActiveContractWorld, observeContractsForAdmissionInObservationAt, observeDeliveryTargetAt, withContractReadObservationAt, } from "../../git/observe.js";
|
|
2
2
|
import { decodeContractDocument, verificationDefinition } from "../../body/decode.js";
|
|
3
|
+
import { dependencyKeys } from "../../core/subject.js";
|
|
3
4
|
import { observeTargetLag, observeWorkspace, conflictHandoffFor, conflictRecovery, worktreePath, } from "../../git/workspace.js";
|
|
4
5
|
import { appointmentFor, readPlaceRegister } from "../../workspace-place.js";
|
|
5
6
|
import { gateReports, latestCurrentAttestations } from "../../core/facts/gate.js";
|
|
@@ -36,8 +37,15 @@ function verificationFor(state, document) {
|
|
|
36
37
|
return { kind: "undeclared" };
|
|
37
38
|
const verifiedGate = gate("verified");
|
|
38
39
|
const current = latestCurrentAttestations(state, new Set([verifiedGate])).get(verifiedGate);
|
|
39
|
-
if (current !== undefined)
|
|
40
|
-
|
|
40
|
+
if (current !== undefined) {
|
|
41
|
+
const snapshot = dependencyKeys(current.data.subject).find((key) => key.kind === "snapshot")?.value;
|
|
42
|
+
return {
|
|
43
|
+
kind: "recorded",
|
|
44
|
+
verdict: current.data.verdict,
|
|
45
|
+
at: current.at,
|
|
46
|
+
...(snapshot === undefined ? {} : { snapshot: snapshot }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
41
49
|
return state.delivery === null ? undefined : { kind: "unrecorded" };
|
|
42
50
|
}
|
|
43
51
|
export function phaseAtFor(state, bindAt) {
|
|
@@ -5,7 +5,7 @@ import { type IntegrationPreparationRefusal } from "../git/integration.js";
|
|
|
5
5
|
import type { GitRepository } from "../git/process.js";
|
|
6
6
|
import type { GitDecodeChannel } from "../git/read-observation.js";
|
|
7
7
|
import { type AcceptedAdmission } from "./attempt.js";
|
|
8
|
-
import type
|
|
8
|
+
import { type ProtocolTerminal } from "./run.js";
|
|
9
9
|
import { type PlacementExecutionFailure } from "./placement.js";
|
|
10
10
|
type TargetMissing = Readonly<{
|
|
11
11
|
kind: "target-missing";
|