@astrosheep/keiyaku 4.0.0 → 4.0.2
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 +133 -8
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +50 -33
- package/build/src/akuma/akuma.js +175 -127
- package/build/src/akuma/archetype.d.ts +14 -5
- package/build/src/akuma/archetype.js +85 -39
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +490 -183
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +88 -45
- package/build/src/akuma/heart/facts.js +19 -8
- package/build/src/akuma/heart/index.d.ts +64 -55
- package/build/src/akuma/heart/index.js +172 -252
- package/build/src/akuma/heart/rows.d.ts +38 -83
- package/build/src/akuma/heart/rows.js +117 -155
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +61 -22
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +47 -0
- package/build/src/akuma/heart/storage.js +224 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +10 -3
- package/build/src/akuma/index.js +7 -1
- package/build/src/akuma/projection.d.ts +176 -0
- package/build/src/akuma/projection.js +256 -0
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +67 -13
- package/build/src/akuma/provider.js +172 -105
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +238 -0
- package/build/src/akuma/providers/claude/index.d.ts +47 -0
- package/build/src/akuma/providers/claude/index.js +279 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +15 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
- package/build/src/akuma/providers/codex-app-server/index.js +77 -33
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +35 -56
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +166 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +191 -0
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -6
- package/build/src/akuma/requests.js +95 -65
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +12 -13
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +18 -12
- package/build/src/cli/accepted.js +73 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
- package/build/src/cli/commands/akuma-invoke.js +101 -52
- package/build/src/cli/commands/akuma.d.ts +27 -9
- package/build/src/cli/commands/akuma.js +151 -80
- package/build/src/cli/commands/contract.d.ts +155 -0
- package/build/src/cli/commands/contract.js +20 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +19 -4
- package/build/src/cli/commands/task-invoke.js +65 -17
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +52 -14
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +9 -3
- package/build/src/cli/invoke.js +287 -108
- package/build/src/cli/main.js +54 -7
- package/build/src/cli/parse.d.ts +21 -117
- package/build/src/cli/parse.js +79 -84
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +4 -2
- package/build/src/cli/render/akuma-tool.js +35 -5
- package/build/src/cli/render/akuma.d.ts +3 -1
- package/build/src/cli/render/akuma.js +247 -212
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +200 -54
- package/build/src/cli/render/kanshi.js +272 -129
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -3
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +20 -0
- package/build/src/cli/render/terminal.js +121 -0
- package/build/src/cli/render/text.js +11 -3
- package/build/src/cli/result.d.ts +126 -19
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +44 -0
- package/build/src/contract-worktree.js +251 -0
- package/build/src/coordination/durable-file.d.ts +5 -1
- package/build/src/coordination/durable-file.js +57 -10
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +3 -18
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +14 -4
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +7 -9
- package/build/src/dispatch/index.d.ts +5 -3
- package/build/src/dispatch/index.js +30 -21
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +33 -23
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +70 -18
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +48 -0
- package/build/src/git/integration.js +250 -0
- package/build/src/git/observe.d.ts +29 -15
- package/build/src/git/observe.js +185 -76
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +17 -5
- package/build/src/git/reconcile.js +305 -109
- package/build/src/git/repository.d.ts +41 -18
- package/build/src/git/repository.js +220 -114
- package/build/src/git/scratch.d.ts +17 -0
- package/build/src/git/scratch.js +73 -0
- package/build/src/git/target-placement.d.ts +92 -0
- package/build/src/git/target-placement.js +375 -0
- package/build/src/git/tender.d.ts +49 -0
- package/build/src/git/tender.js +63 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +89 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +53 -0
- package/build/src/git/workspace.js +139 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +7 -3
- package/build/src/kanshi/read.js +245 -45
- package/build/src/kanshi/report.d.ts +81 -6
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +33 -1
- package/build/src/library/address.d.ts +57 -0
- package/build/src/library/address.js +165 -0
- package/build/src/library/akuma-creation.d.ts +16 -7
- package/build/src/library/akuma-creation.js +96 -22
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +69 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +23 -49
- package/build/src/library/contract.js +171 -185
- package/build/src/library/delivery.d.ts +24 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +153 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +18 -3
- package/build/src/library/keiyaku.js +12 -1
- package/build/src/library/mutation.d.ts +39 -0
- package/build/src/library/mutation.js +37 -0
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +14 -1
- package/build/src/library/region.js +18 -4
- package/build/src/library/repo.d.ts +4 -13
- package/build/src/library/repo.js +14 -24
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +41 -10
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +48 -40
- package/build/src/protocol/intent.d.ts +57 -20
- package/build/src/protocol/intent.js +55 -79
- package/build/src/protocol/operations.d.ts +152 -43
- package/build/src/protocol/operations.js +482 -166
- package/build/src/protocol/outcome.d.ts +14 -3
- package/build/src/protocol/outcome.js +11 -3
- package/build/src/protocol/placement.d.ts +41 -0
- package/build/src/protocol/placement.js +147 -0
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +18 -5
- package/build/src/protocol/read/status.js +73 -13
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +4 -8
- package/build/src/runtime/proc/line-rpc.js +22 -28
- package/build/src/runtime/proc/run.d.ts +23 -21
- package/build/src/runtime/proc/run.js +123 -89
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +7 -1
- package/build/src/settings.js +32 -17
- package/build/src/settlement/fence.d.ts +5 -0
- package/build/src/settlement/fence.js +14 -0
- package/build/src/settlement/holder.d.ts +35 -4
- package/build/src/settlement/holder.js +127 -28
- package/build/src/settlement/settle.d.ts +9 -1
- package/build/src/settlement/settle.js +74 -37
- package/build/src/task/board.d.ts +23 -5
- package/build/src/task/board.js +17 -10
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +15 -20
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +27 -15
- package/build/src/task/index.js +57 -35
- package/build/src/task/operations.d.ts +38 -13
- package/build/src/task/operations.js +80 -46
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +5 -7
- package/build/src/task/store.js +43 -28
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +51 -0
- package/build/src/verification/execution.js +108 -0
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +24 -0
- package/build/src/world.js +136 -0
- package/package.json +8 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/protocol/read/audit.d.ts +0 -25
- package/build/src/protocol/read/audit.js +0 -39
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
|
@@ -1,126 +1,288 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { materializeIntegrationSnapshot, planIntegration, readDeliveryDiff, readDeliveryScope, worktreeChangeId, } from "../git/integration.js";
|
|
2
|
+
import { captureTender, dirtyTenderDelta, dirtyTenderRefusal, materializeTenderSnapshot, } from "../git/tender.js";
|
|
3
|
+
import { currentBranch, extendContractsForAdmissionAt, observeContractAt, observeContractWorld, observeContractsForAdmissionAt, } from "../git/observe.js";
|
|
4
|
+
import { reconcile, reconcileBatch, reconcileObservationFailure, } from "../git/reconcile.js";
|
|
4
5
|
import { NoGitWorldError, repositoryAt } from "../git/repository.js";
|
|
5
|
-
import {
|
|
6
|
+
import { withGitReadObservation } from "../git/read-observation.js";
|
|
6
7
|
import { dependencyKeySet } from "../core/subject.js";
|
|
7
8
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
8
|
-
import { contractState, documentIsCurrent } from "../core/facts/observation.js";
|
|
9
|
+
import { activeContract, contractState, documentIsCurrent } from "../core/facts/observation.js";
|
|
9
10
|
import { gate } from "../core/facts/types.js";
|
|
10
11
|
import { decideAbandon } from "../core/verbs/abandon.js";
|
|
11
12
|
import { decideAmend } from "../core/verbs/amend.js";
|
|
12
13
|
import { decideArc } from "../core/verbs/arc.js";
|
|
13
14
|
import { decideDeliver } from "../core/verbs/deliver.js";
|
|
14
15
|
import { decideAttestation } from "../core/verbs/attestation.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { admitIntent, currentVerifiedAttestation, verifyDelivery, } from "./intent.js";
|
|
17
|
+
import { admitPlacement, } from "./placement.js";
|
|
18
|
+
import { adjudicateAuditTarget } from "../git/target-placement.js";
|
|
18
19
|
import { readDocuments } from "./read/documents.js";
|
|
19
|
-
import { readContractBoard,
|
|
20
|
-
import { admitDecidedOffer } from "./attempt.js";
|
|
20
|
+
import { readContractBoard, readContractObservationAt, } from "./read/status.js";
|
|
21
|
+
import { admitDecidedOffer, mintAttempts } from "./attempt.js";
|
|
22
|
+
import { appointmentFor, readManagedWorktreeAppointment, readPlaceRegister, } from "../workspace-place.js";
|
|
21
23
|
export { bindOperation } from "./bind.js";
|
|
22
|
-
|
|
24
|
+
export { reconcileObservationFailure } from "../git/reconcile.js";
|
|
25
|
+
import { accepted, admitted, complete, } from "./outcome.js";
|
|
23
26
|
const REVIEWED = gate("reviewed");
|
|
24
27
|
function timestamp() { return new Date().toISOString(); }
|
|
25
28
|
function mergeAdmissions(current, next) {
|
|
26
|
-
|
|
29
|
+
const effects = [...(current.physical?.effects ?? []), ...(next.physical?.effects ?? [])];
|
|
30
|
+
const lag = [...(current.physical?.lag ?? []), ...(next.physical?.lag ?? [])];
|
|
31
|
+
return {
|
|
32
|
+
...next,
|
|
33
|
+
facts: [...current.facts, ...next.facts],
|
|
34
|
+
...(effects.length === 0 && lag.length === 0 ? {} : { physical: { effects, lag } }),
|
|
35
|
+
};
|
|
27
36
|
}
|
|
28
37
|
function stepStop(result) {
|
|
29
38
|
if (result.kind === "accepted")
|
|
30
39
|
return undefined;
|
|
31
40
|
return result.kind === "refused" ? { refusal: result.refusal } : { retry: result };
|
|
32
41
|
}
|
|
42
|
+
function verificationStop(step) {
|
|
43
|
+
return "failure" in step ? step : stepStop(step);
|
|
44
|
+
}
|
|
45
|
+
function unpackVerificationOutcome(verification) {
|
|
46
|
+
const stop = verificationStop(verification.step);
|
|
47
|
+
const admission = !("failure" in verification.step) && verification.step.kind === "accepted"
|
|
48
|
+
? verification.step
|
|
49
|
+
: undefined;
|
|
50
|
+
return {
|
|
51
|
+
...(verification.cleanup === undefined ? {} : { cleanup: verification.cleanup }),
|
|
52
|
+
...(verification.leak === undefined ? {} : { leak: verification.leak }),
|
|
53
|
+
...(stop === undefined ? {} : { stop }),
|
|
54
|
+
...(admission === undefined ? {} : { admission }),
|
|
55
|
+
...(verification.counts === undefined ? {} : { counts: verification.counts }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function placementStop(result) {
|
|
59
|
+
if (result.kind === "accepted")
|
|
60
|
+
return undefined;
|
|
61
|
+
if (result.kind === "placement-failed") {
|
|
62
|
+
return { failure: "target-placement-failed", diagnostic: result.diagnostic };
|
|
63
|
+
}
|
|
64
|
+
if (result.kind === "target-moved") {
|
|
65
|
+
const { contractId, target, expected, observed } = result;
|
|
66
|
+
return { failure: "target-moved", contractId, target, expected, observed };
|
|
67
|
+
}
|
|
68
|
+
return result.kind === "refused" ? { refusal: result.refusal } : { retry: result };
|
|
69
|
+
}
|
|
33
70
|
export { NoGitWorldError };
|
|
34
|
-
export function scopeOperation(input) {
|
|
35
|
-
|
|
36
|
-
|
|
71
|
+
export async function scopeOperation(input) {
|
|
72
|
+
return await repositoryAt(input.coordinate);
|
|
73
|
+
}
|
|
74
|
+
export async function currentBranchOperation(input) {
|
|
75
|
+
return await currentBranch(input.scope);
|
|
76
|
+
}
|
|
77
|
+
export async function contractsOperation(input) {
|
|
78
|
+
return withGitReadObservation(input.scope, input.channel, readContractBoard);
|
|
37
79
|
}
|
|
38
|
-
export function
|
|
39
|
-
|
|
40
|
-
return readContractObservation(input.scope, input.contractId);
|
|
80
|
+
export async function contractObservationOperation(input) {
|
|
81
|
+
return await readContractObservationAt(input.scope, input.channel, input.contractId);
|
|
41
82
|
}
|
|
42
|
-
export function
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
export async function documentsOperationAt(scope, channel) {
|
|
84
|
+
return withGitReadObservation(scope, channel, readDocuments);
|
|
85
|
+
}
|
|
86
|
+
export async function stateOperation(input) {
|
|
87
|
+
const state = (await observeContractAt(input.scope, input.channel, input.contractId)).state;
|
|
45
88
|
if (state === null)
|
|
46
89
|
throw new Error(`contract does not exist: ${input.contractId}`);
|
|
47
90
|
return state;
|
|
48
91
|
}
|
|
49
|
-
export function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
92
|
+
export async function deliveryOperation(input) {
|
|
93
|
+
const state = (await observeContractAt(input.scope, input.channel, input.contractId)).state;
|
|
94
|
+
return state?.delivery?.data ?? null;
|
|
95
|
+
}
|
|
96
|
+
export async function deliveryDiffOperation(input) { return await readDeliveryDiff(input.scope, input.integrationPredecessor, input.integrationSnapshot); }
|
|
97
|
+
async function extendPrerequisiteClosureAt(channel, observation, seeds) {
|
|
98
|
+
let current = observation;
|
|
99
|
+
const visited = new Set();
|
|
100
|
+
let pending = [...seeds];
|
|
101
|
+
while (pending.length > 0) {
|
|
102
|
+
const batch = [...new Set(pending.filter((id) => !visited.has(id)))];
|
|
103
|
+
pending = [];
|
|
104
|
+
if (batch.length === 0)
|
|
105
|
+
break;
|
|
106
|
+
current = await extendContractsForAdmissionAt(channel, current, batch);
|
|
107
|
+
for (const id of batch) {
|
|
108
|
+
visited.add(id);
|
|
109
|
+
const state = contractState(current.decision, id);
|
|
110
|
+
if (state !== null)
|
|
111
|
+
pending.push(...state.terms.after);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return current;
|
|
115
|
+
}
|
|
116
|
+
export async function amendOperation(input) {
|
|
117
|
+
const attempts = mintAttempts({ entryCount: 1 });
|
|
118
|
+
let source = input.source;
|
|
119
|
+
for (let index = 0; index < attempts.length; index += 1) {
|
|
120
|
+
let observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
121
|
+
const state = contractState(observation.decision, input.contractId);
|
|
122
|
+
if (source === undefined && state !== null)
|
|
123
|
+
source = state.terms;
|
|
124
|
+
const amendment = source === undefined || input.deriveAmendment === undefined
|
|
125
|
+
? undefined
|
|
126
|
+
: { source, ...input.deriveAmendment(source) };
|
|
127
|
+
if (amendment !== undefined) {
|
|
128
|
+
observation = await extendPrerequisiteClosureAt(input.channel, observation, [...new Set([...(state?.terms.after ?? []), ...amendment.terms.after])]);
|
|
129
|
+
}
|
|
130
|
+
const preparation = amendment === undefined
|
|
131
|
+
? undefined
|
|
132
|
+
: amendment.verification.kind === "prepared"
|
|
133
|
+
? { kind: "prepared", data: amendment.terms }
|
|
134
|
+
: { kind: "refused", refusal: amendment.verification.refusal };
|
|
135
|
+
const decision = decideAmend({
|
|
136
|
+
input: {
|
|
137
|
+
contractId: input.contractId,
|
|
138
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
139
|
+
at: timestamp(),
|
|
140
|
+
...(amendment === undefined ? {} : { source: amendment.source }),
|
|
141
|
+
...(preparation === undefined ? {} : { preparation }),
|
|
142
|
+
},
|
|
143
|
+
attempt: attempts[index],
|
|
144
|
+
observation: observation.decision,
|
|
145
|
+
});
|
|
146
|
+
if (decision.kind === "refused")
|
|
147
|
+
return decision;
|
|
148
|
+
const admission = await admitDecidedOffer({
|
|
149
|
+
channel: input.channel,
|
|
150
|
+
repository: input.scope,
|
|
151
|
+
decisionObservation: observation,
|
|
152
|
+
attempt: attempts[index],
|
|
153
|
+
offer: decision.offer,
|
|
154
|
+
primaryContract: input.contractId,
|
|
155
|
+
});
|
|
156
|
+
if (admission.kind === "accepted") {
|
|
157
|
+
if (amendment === undefined)
|
|
158
|
+
throw new Error("accepted amendment is missing its document derivation");
|
|
159
|
+
return admitted(admission, amendment);
|
|
160
|
+
}
|
|
161
|
+
if (admission.kind === "publication-failed")
|
|
162
|
+
return { kind: "retry", reason: admission };
|
|
163
|
+
if (admission.kind === "collision" && index + 1 === attempts.length)
|
|
164
|
+
return { kind: "retry", reason: admission };
|
|
165
|
+
}
|
|
166
|
+
return { kind: "retry", reason: { kind: "exhausted" } };
|
|
167
|
+
}
|
|
168
|
+
export async function prepareDelivery(repository, stage, input) {
|
|
169
|
+
const { contractId, coordinates } = stage;
|
|
170
|
+
if (coordinates.workspace === "here" && coordinates.target !== undefined) {
|
|
171
|
+
const branch = await currentBranch(repository);
|
|
172
|
+
if (branch !== coordinates.target) {
|
|
173
|
+
return { kind: "refused", refusal: { kind: "workspace-not-on-target", contractId, target: coordinates.target, branch } };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const appointed = coordinates.workspace === "worktree"
|
|
177
|
+
? stage.appointment === undefined
|
|
178
|
+
? appointmentFor(await readPlaceRegister(repository), contractId)
|
|
179
|
+
: { contract: contractId, place: stage.appointment.place }
|
|
180
|
+
: undefined;
|
|
181
|
+
const tender = await captureTender(repository, {
|
|
182
|
+
contractId,
|
|
183
|
+
coordinates,
|
|
184
|
+
...(appointed === undefined ? {} : { place: appointed.place }),
|
|
185
|
+
});
|
|
186
|
+
if (tender.kind === "refused")
|
|
187
|
+
return tender;
|
|
188
|
+
if ((tender.data.dirty && input.includeDirty !== true) || tender.data.changes.submodules.length > 0) {
|
|
189
|
+
return { kind: "refused", refusal: await dirtyTenderRefusal(repository, contractId, tender.data) };
|
|
190
|
+
}
|
|
191
|
+
const tenderSnapshot = await materializeTenderSnapshot(repository, tender.data, {
|
|
192
|
+
contractId,
|
|
193
|
+
title: input.title,
|
|
194
|
+
...(input.message === undefined ? {} : { message: input.message }),
|
|
195
|
+
});
|
|
196
|
+
const requireBranchesToBeUpToDate = input.requireBranchesToBeUpToDate ?? false;
|
|
197
|
+
const integration = await planIntegration(repository, { contractId, coordinates }, { ...tender.data, head: tenderSnapshot }, requireBranchesToBeUpToDate);
|
|
198
|
+
if (integration.kind === "refused")
|
|
199
|
+
return integration;
|
|
200
|
+
const integrationSnapshot = coordinates.target === undefined
|
|
201
|
+
? tenderSnapshot
|
|
202
|
+
: await materializeIntegrationSnapshot(repository, integration.data.tree, integration.data.predecessor, {
|
|
203
|
+
contractId,
|
|
204
|
+
title: input.title,
|
|
205
|
+
...(input.message === undefined ? {} : { message: input.message }),
|
|
206
|
+
});
|
|
54
207
|
return {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
208
|
+
kind: "prepared",
|
|
209
|
+
data: {
|
|
210
|
+
tenderSnapshot,
|
|
211
|
+
integration: {
|
|
212
|
+
predecessor: integration.data.predecessor,
|
|
213
|
+
snapshot: integrationSnapshot,
|
|
214
|
+
changeId: await worktreeChangeId(repository, { contractId, coordinates }, tender.data),
|
|
215
|
+
},
|
|
216
|
+
method: "squash",
|
|
217
|
+
policy: { requireBranchesToBeUpToDate },
|
|
218
|
+
},
|
|
58
219
|
};
|
|
59
220
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
frontier = [...next];
|
|
75
|
-
observation = extendContractsForAdmission(repository, observation, frontier);
|
|
221
|
+
async function captureReviewableWorktree(repository, stage) {
|
|
222
|
+
const appointed = stage.coordinates.workspace === "worktree"
|
|
223
|
+
? appointmentFor(await readPlaceRegister(repository), stage.contractId)
|
|
224
|
+
: undefined;
|
|
225
|
+
const tender = await captureTender(repository, {
|
|
226
|
+
...stage,
|
|
227
|
+
...(appointed === undefined ? {} : { place: appointed.place }),
|
|
228
|
+
});
|
|
229
|
+
if (tender.kind === "refused")
|
|
230
|
+
return tender;
|
|
231
|
+
if (tender.data.changes.submodules.length > 0) {
|
|
232
|
+
return { kind: "refused", refusal: await dirtyTenderRefusal(repository, stage.contractId, tender.data) };
|
|
76
233
|
}
|
|
77
|
-
|
|
234
|
+
const workspace = await dirtyTenderDelta(repository, tender.data);
|
|
235
|
+
return {
|
|
236
|
+
kind: "prepared",
|
|
237
|
+
data: {
|
|
238
|
+
changeId: await worktreeChangeId(repository, stage, tender.data),
|
|
239
|
+
tender: tender.data,
|
|
240
|
+
...(workspace === undefined ? {} : { workspace }),
|
|
241
|
+
},
|
|
242
|
+
};
|
|
78
243
|
}
|
|
79
|
-
export async function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
:
|
|
85
|
-
|
|
86
|
-
:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
90
|
-
at: timestamp(),
|
|
91
|
-
...(amendment === undefined ? {} : { source: amendment.source }),
|
|
92
|
-
...(preparation === undefined ? {} : { preparation }),
|
|
244
|
+
export async function prepareReview(repository, stage) {
|
|
245
|
+
const prepared = await captureReviewableWorktree(repository, stage);
|
|
246
|
+
if (prepared.kind === "refused")
|
|
247
|
+
return prepared;
|
|
248
|
+
return {
|
|
249
|
+
kind: "prepared",
|
|
250
|
+
data: {
|
|
251
|
+
changeId: prepared.data.changeId,
|
|
252
|
+
...(prepared.data.workspace === undefined ? {} : { workspace: prepared.data.workspace }),
|
|
253
|
+
},
|
|
93
254
|
};
|
|
94
|
-
return complete(admitIntent(input.scope, decisionInput, decideAmend, {
|
|
95
|
-
observedContracts: [input.contractId, ...(amendment?.terms.after ?? [])],
|
|
96
|
-
observe: observePrerequisiteClosure,
|
|
97
|
-
}), undefined);
|
|
98
255
|
}
|
|
99
|
-
function deliverAttempt(input, attempt) {
|
|
100
|
-
const decisionObservation =
|
|
256
|
+
async function deliverAttempt(input, attempt) {
|
|
257
|
+
const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
101
258
|
const state = contractState(decisionObservation.decision, input.contractId);
|
|
259
|
+
const derivation = state === null || input.deriveDocument === undefined
|
|
260
|
+
? undefined
|
|
261
|
+
: input.deriveDocument(state);
|
|
102
262
|
let preparation;
|
|
103
|
-
if (state === null ||
|
|
263
|
+
if (state === null || derivation === undefined) {
|
|
104
264
|
preparation = { kind: "unavailable" };
|
|
105
265
|
}
|
|
106
|
-
else if (
|
|
266
|
+
else if (derivation.verification.kind === "refused") {
|
|
107
267
|
preparation = {
|
|
108
268
|
kind: "refused",
|
|
109
|
-
document:
|
|
110
|
-
refusal:
|
|
269
|
+
document: derivation.document,
|
|
270
|
+
refusal: derivation.verification.refusal,
|
|
111
271
|
};
|
|
112
272
|
}
|
|
113
273
|
else {
|
|
114
|
-
const prepared = prepareDelivery(input.scope, {
|
|
274
|
+
const prepared = await prepareDelivery(input.scope, {
|
|
115
275
|
contractId: state.id,
|
|
116
276
|
coordinates: state.coordinates,
|
|
117
277
|
}, {
|
|
118
|
-
title:
|
|
278
|
+
title: derivation.title,
|
|
119
279
|
...(input.message === undefined ? {} : { message: input.message }),
|
|
280
|
+
requireBranchesToBeUpToDate: input.requireBranchesToBeUpToDate,
|
|
281
|
+
includeDirty: input.includeDirty,
|
|
120
282
|
});
|
|
121
283
|
preparation = prepared.kind === "refused"
|
|
122
|
-
? { kind: "refused", document:
|
|
123
|
-
: { kind: "prepared", document:
|
|
284
|
+
? { kind: "refused", document: derivation.document, refusal: prepared.refusal }
|
|
285
|
+
: { kind: "prepared", document: derivation.document, data: prepared.data };
|
|
124
286
|
}
|
|
125
287
|
const decisionInput = {
|
|
126
288
|
contractId: input.contractId,
|
|
@@ -134,61 +296,73 @@ function deliverAttempt(input, attempt) {
|
|
|
134
296
|
if (preparation.kind !== "prepared") {
|
|
135
297
|
throw new Error("offered delivery is missing its mechanical preparation");
|
|
136
298
|
}
|
|
137
|
-
const admitted = admitDecidedOffer(
|
|
299
|
+
const admitted = await admitDecidedOffer({
|
|
300
|
+
channel: input.channel,
|
|
301
|
+
repository: input.scope,
|
|
302
|
+
decisionObservation,
|
|
303
|
+
attempt,
|
|
304
|
+
offer: decision.offer,
|
|
305
|
+
primaryContract: input.contractId,
|
|
306
|
+
});
|
|
138
307
|
if (admitted.kind === "accepted") {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
expectedPredecessor: preparation.data.expectedPredecessor,
|
|
143
|
-
} };
|
|
308
|
+
if (derivation === undefined)
|
|
309
|
+
throw new Error("accepted delivery is missing its document derivation");
|
|
310
|
+
return { ...admitted, value: { delivery: preparation.data, derivation } };
|
|
144
311
|
}
|
|
145
312
|
return admitted;
|
|
146
313
|
}
|
|
147
314
|
async function completeDelivery(input, first) {
|
|
148
|
-
|
|
149
|
-
throw new Error("accepted delivery is missing its document derivation");
|
|
150
|
-
}
|
|
151
|
-
const derivation = input.derivation;
|
|
315
|
+
const derivation = first.value.derivation;
|
|
152
316
|
if (derivation.verification.kind !== "prepared") {
|
|
153
317
|
throw new Error("accepted delivery is missing its Verification preparation");
|
|
154
318
|
}
|
|
155
319
|
let admission = first;
|
|
156
320
|
let verificationValue;
|
|
321
|
+
let verificationReuse;
|
|
322
|
+
let cleanup;
|
|
157
323
|
let leak;
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
? {}
|
|
168
|
-
:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
324
|
+
const currentVerified = currentVerifiedAttestation(first.state);
|
|
325
|
+
if (currentVerified !== undefined) {
|
|
326
|
+
verificationReuse = currentVerified;
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
const verification = await verifyDelivery({
|
|
330
|
+
channel: input.channel,
|
|
331
|
+
repository: input.scope,
|
|
332
|
+
contractId: input.contractId,
|
|
333
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
334
|
+
at: timestamp(),
|
|
335
|
+
state: first.state,
|
|
336
|
+
snapshot: first.value.delivery.integration.snapshot,
|
|
337
|
+
environment: process.env,
|
|
338
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
339
|
+
...(derivation.verification.data === null
|
|
340
|
+
? {}
|
|
341
|
+
: { verification: derivation.verification.data }),
|
|
342
|
+
});
|
|
343
|
+
if (verification !== null) {
|
|
344
|
+
const unpacked = unpackVerificationOutcome(verification);
|
|
345
|
+
cleanup = unpacked.cleanup;
|
|
346
|
+
leak = unpacked.leak;
|
|
347
|
+
verificationValue = unpacked.stop;
|
|
348
|
+
if (unpacked.admission !== undefined)
|
|
349
|
+
admission = mergeAdmissions(admission, unpacked.admission);
|
|
178
350
|
}
|
|
179
351
|
}
|
|
180
|
-
const placement = admitPlacement(input.scope, {
|
|
352
|
+
const placement = await admitPlacement(input.channel, input.scope, first.state.coordinates.target, {
|
|
181
353
|
contractId: input.contractId,
|
|
182
354
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
183
355
|
at: timestamp(),
|
|
184
356
|
});
|
|
185
|
-
const placementValue =
|
|
357
|
+
const placementValue = placementStop(placement);
|
|
186
358
|
if (placement.kind === "accepted")
|
|
187
359
|
admission = mergeAdmissions(admission, placement);
|
|
188
360
|
return admitted(admission, {
|
|
189
|
-
...first.value,
|
|
361
|
+
...first.value.delivery,
|
|
190
362
|
...(verificationValue === undefined ? {} : { verification: verificationValue }),
|
|
363
|
+
...(verificationReuse === undefined ? {} : { verificationReuse }),
|
|
191
364
|
...(placementValue === undefined ? {} : { placement: placementValue }),
|
|
365
|
+
...(cleanup === undefined ? {} : { cleanup }),
|
|
192
366
|
...(leak === undefined ? {} : { leak }),
|
|
193
367
|
});
|
|
194
368
|
}
|
|
@@ -196,7 +370,7 @@ export async function deliverOperation(input) {
|
|
|
196
370
|
const attempts = mintAttempts({ entryCount: 2 });
|
|
197
371
|
let first = null;
|
|
198
372
|
for (let index = 0; index < attempts.length; index += 1) {
|
|
199
|
-
const result = deliverAttempt(input, attempts[index]);
|
|
373
|
+
const result = await deliverAttempt(input, attempts[index]);
|
|
200
374
|
if (result.kind === "accepted") {
|
|
201
375
|
first = result;
|
|
202
376
|
break;
|
|
@@ -212,30 +386,41 @@ export async function deliverOperation(input) {
|
|
|
212
386
|
}
|
|
213
387
|
if (first === null)
|
|
214
388
|
return { kind: "retry", reason: { kind: "exhausted" } };
|
|
215
|
-
return completeDelivery(input, first);
|
|
389
|
+
return await completeDelivery(input, first);
|
|
216
390
|
}
|
|
217
|
-
export function abandonOperation(input) {
|
|
218
|
-
return complete(admitIntent(input.scope, {
|
|
391
|
+
export async function abandonOperation(input) {
|
|
392
|
+
return complete(await admitIntent(input.channel, input.scope, {
|
|
219
393
|
contractId: input.contractId,
|
|
220
394
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
221
395
|
at: timestamp(),
|
|
222
396
|
...(input.note === undefined ? {} : { note: input.note }),
|
|
223
|
-
}, decideAbandon,
|
|
397
|
+
}, decideAbandon, {
|
|
398
|
+
...(input.decorateOffer === undefined ? {} : { decorateOffer: input.decorateOffer }),
|
|
399
|
+
...(input.observationSelection === undefined ? {} : { observationSelection: input.observationSelection }),
|
|
400
|
+
}), undefined);
|
|
224
401
|
}
|
|
225
|
-
export function arcOperation(input) {
|
|
226
|
-
return complete(admitIntent(input.scope, {
|
|
402
|
+
export async function arcOperation(input) {
|
|
403
|
+
return complete(await admitIntent(input.channel, input.scope, {
|
|
227
404
|
contractId: input.contractId,
|
|
228
405
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
229
406
|
at: timestamp(),
|
|
230
407
|
data: input.chapter,
|
|
231
408
|
}, decideArc), undefined);
|
|
232
409
|
}
|
|
233
|
-
function
|
|
234
|
-
|
|
410
|
+
function reviewValue(value, placement) {
|
|
411
|
+
return {
|
|
412
|
+
...(value.workspace === undefined ? {} : { workspace: value.workspace }),
|
|
413
|
+
...(placement === undefined ? {} : { placement }),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
async function reviewAttempt(input, attempt) {
|
|
417
|
+
const decisionObservation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
235
418
|
const state = contractState(decisionObservation.decision, input.contractId);
|
|
236
419
|
let preparation;
|
|
420
|
+
let workspace;
|
|
421
|
+
let tender;
|
|
237
422
|
if (state !== null) {
|
|
238
|
-
const prepared =
|
|
423
|
+
const prepared = await captureReviewableWorktree(input.scope, { contractId: state.id, coordinates: state.coordinates });
|
|
239
424
|
preparation = prepared.kind === "refused"
|
|
240
425
|
? { kind: "refused", refusal: prepared.refusal }
|
|
241
426
|
: {
|
|
@@ -244,12 +429,16 @@ function reviewAttempt(input, attempt) {
|
|
|
244
429
|
gate: REVIEWED,
|
|
245
430
|
subject: dependencyKeySet([
|
|
246
431
|
{ kind: "document", value: state.terms.document.key },
|
|
247
|
-
{ kind: "change", value: prepared.data },
|
|
432
|
+
{ kind: "change", value: prepared.data.changeId },
|
|
248
433
|
]),
|
|
249
434
|
verdict: input.verdict,
|
|
250
435
|
...(input.summary === undefined ? {} : { summary: input.summary }),
|
|
251
436
|
},
|
|
252
437
|
};
|
|
438
|
+
if (prepared.kind === "prepared") {
|
|
439
|
+
workspace = prepared.data.workspace;
|
|
440
|
+
tender = prepared.data.tender;
|
|
441
|
+
}
|
|
253
442
|
}
|
|
254
443
|
const decisionInput = {
|
|
255
444
|
contractId: input.contractId,
|
|
@@ -260,17 +449,30 @@ function reviewAttempt(input, attempt) {
|
|
|
260
449
|
const decision = decideAttestation({ input: decisionInput, attempt, observation: decisionObservation.decision });
|
|
261
450
|
if (decision.kind === "refused")
|
|
262
451
|
return { kind: "refused", refusal: decision.refusal };
|
|
263
|
-
const admitted = admitDecidedOffer(
|
|
452
|
+
const admitted = await admitDecidedOffer({
|
|
453
|
+
channel: input.channel,
|
|
454
|
+
repository: input.scope,
|
|
455
|
+
decisionObservation,
|
|
456
|
+
attempt,
|
|
457
|
+
offer: decision.offer,
|
|
458
|
+
primaryContract: input.contractId,
|
|
459
|
+
});
|
|
264
460
|
if (admitted.kind === "accepted")
|
|
265
|
-
return {
|
|
461
|
+
return {
|
|
462
|
+
...admitted,
|
|
463
|
+
value: {
|
|
464
|
+
...(workspace === undefined ? {} : { workspace }),
|
|
465
|
+
...(tender === undefined ? {} : { tender }),
|
|
466
|
+
},
|
|
467
|
+
};
|
|
266
468
|
return admitted;
|
|
267
469
|
}
|
|
268
|
-
export function reviewOperation(input) {
|
|
470
|
+
export async function reviewOperation(input) {
|
|
269
471
|
const git = input.scope;
|
|
270
|
-
const attempts = mintAttempts({ entryCount:
|
|
472
|
+
const attempts = mintAttempts({ entryCount: 1 });
|
|
271
473
|
let review = null;
|
|
272
474
|
for (let index = 0; index < attempts.length; index += 1) {
|
|
273
|
-
const result = reviewAttempt(input, attempts[index]);
|
|
475
|
+
const result = await reviewAttempt(input, attempts[index]);
|
|
274
476
|
if (result.kind === "accepted" || result.kind === "refused") {
|
|
275
477
|
review = result;
|
|
276
478
|
break;
|
|
@@ -285,73 +487,178 @@ export function reviewOperation(input) {
|
|
|
285
487
|
if (review.kind !== "accepted")
|
|
286
488
|
return review;
|
|
287
489
|
if (input.verdict !== "satisfied")
|
|
288
|
-
return admitted(review,
|
|
289
|
-
const
|
|
490
|
+
return admitted(review, reviewValue(review.value));
|
|
491
|
+
const target = review.state.coordinates.target;
|
|
492
|
+
const tender = review.value.tender;
|
|
493
|
+
const placement = await admitPlacement(input.channel, git, target, {
|
|
290
494
|
contractId: input.contractId,
|
|
291
495
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
292
496
|
at: timestamp(),
|
|
497
|
+
}, tender === undefined || target === undefined ? undefined : async () => {
|
|
498
|
+
const integration = await planIntegration(git, {
|
|
499
|
+
contractId: input.contractId,
|
|
500
|
+
coordinates: review.state.coordinates,
|
|
501
|
+
}, tender, false);
|
|
502
|
+
if (integration.kind === "refused" && integration.refusal.kind !== "target-missing") {
|
|
503
|
+
return { kind: "refused", refusal: integration.refusal };
|
|
504
|
+
}
|
|
505
|
+
return undefined;
|
|
293
506
|
});
|
|
294
|
-
const
|
|
507
|
+
const stopped = placementStop(placement);
|
|
295
508
|
const admission = placement.kind === "accepted" ? mergeAdmissions(review, placement) : review;
|
|
296
|
-
return admitted(admission,
|
|
509
|
+
return admitted(admission, reviewValue(review.value, stopped));
|
|
297
510
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (initial.state === null)
|
|
302
|
-
return { kind: "refused", refusal: { kind: "contract-missing", contractId: input.contractId } };
|
|
303
|
-
const derivation = input.derivation;
|
|
304
|
-
if (derivation === undefined) {
|
|
305
|
-
return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
|
|
306
|
-
}
|
|
307
|
-
if (!documentIsCurrent(initial.state, derivation.document)) {
|
|
308
|
-
return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
|
|
309
|
-
}
|
|
310
|
-
if (derivation.verification.kind === "refused") {
|
|
311
|
-
return { kind: "refused", refusal: derivation.verification.refusal };
|
|
312
|
-
}
|
|
313
|
-
if (initial.state.delivery === null || derivation.verification.data === null) {
|
|
314
|
-
return accepted(initial.state, [], initial.report);
|
|
511
|
+
async function auditWorkspace(repository, state) {
|
|
512
|
+
if (state.coordinates.workspace === "here") {
|
|
513
|
+
return { kind: "ready", answer: { kind: "here", path: repository.effectiveCwd } };
|
|
315
514
|
}
|
|
515
|
+
const appointed = await readManagedWorktreeAppointment(repository, state.id);
|
|
516
|
+
if (appointed.kind === "failed")
|
|
517
|
+
throw new Error(appointed.diagnostic);
|
|
518
|
+
if (appointed.kind === "unappointed")
|
|
519
|
+
return appointed;
|
|
520
|
+
return {
|
|
521
|
+
kind: "ready",
|
|
522
|
+
answer: { kind: "worktree", path: appointed.path },
|
|
523
|
+
appointment: appointed,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function auditDeliveryRelation(state, candidate) {
|
|
527
|
+
const recorded = state.delivery?.data.integration.changeId;
|
|
528
|
+
if (recorded === undefined)
|
|
529
|
+
return undefined;
|
|
530
|
+
return {
|
|
531
|
+
changeId: recorded,
|
|
532
|
+
relation: recorded === candidate.integration.changeId ? "identical" : "differs",
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
async function auditCandidateVerification(input, state, snapshot, definition) {
|
|
316
536
|
const verification = await verifyDelivery({
|
|
317
|
-
|
|
537
|
+
channel: input.channel,
|
|
538
|
+
repository: input.scope,
|
|
318
539
|
contractId: input.contractId,
|
|
319
540
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
320
541
|
at: timestamp(),
|
|
321
|
-
state
|
|
542
|
+
state,
|
|
543
|
+
snapshot,
|
|
322
544
|
environment: process.env,
|
|
323
|
-
|
|
324
|
-
verification:
|
|
545
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
546
|
+
verification: definition,
|
|
325
547
|
});
|
|
326
548
|
if (verification === null) {
|
|
327
549
|
throw new Error("audit verification preparation unexpectedly produced no attempt");
|
|
328
550
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
551
|
+
return unpackVerificationOutcome(verification);
|
|
552
|
+
}
|
|
553
|
+
function auditVerificationAnswer(verified) {
|
|
554
|
+
if (verified === undefined)
|
|
555
|
+
return { kind: "not-run" };
|
|
556
|
+
if (verified.stop !== undefined)
|
|
557
|
+
return { kind: "stopped", stop: verified.stop };
|
|
558
|
+
if (verified.counts === undefined) {
|
|
559
|
+
throw new Error("terminal Verification is missing producer counts");
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
kind: verified.counts.verdict,
|
|
563
|
+
passed: verified.counts.passed,
|
|
564
|
+
total: verified.counts.total,
|
|
565
|
+
...(verified.counts.summary === undefined ? {} : { summary: verified.counts.summary }),
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
async function readyAuditCandidate(repository, candidate, workspace, showDiff) {
|
|
569
|
+
const predecessor = candidate.integration.predecessor;
|
|
570
|
+
const snapshot = candidate.integration.snapshot;
|
|
571
|
+
const scope = await readDeliveryScope(repository, predecessor, snapshot, showDiff);
|
|
572
|
+
const diff = showDiff ? await readDeliveryDiff(repository, predecessor, snapshot) : undefined;
|
|
573
|
+
return {
|
|
574
|
+
kind: "ready",
|
|
575
|
+
workspace,
|
|
576
|
+
identity: candidate,
|
|
577
|
+
scope,
|
|
578
|
+
...(diff === undefined || diff === null ? {} : { diff }),
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
async function auditTargetAnswer(repository, state, candidate) {
|
|
582
|
+
const target = state.coordinates.target;
|
|
583
|
+
if (target === undefined)
|
|
584
|
+
return { kind: "not-observed" };
|
|
585
|
+
return await adjudicateAuditTarget(repository, {
|
|
586
|
+
contractId: state.id,
|
|
587
|
+
coordinates: { ...state.coordinates, target },
|
|
588
|
+
predecessor: candidate.integration.predecessor,
|
|
589
|
+
candidate: candidate.integration.snapshot,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
export async function auditOperation(input) {
|
|
593
|
+
const observed = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
594
|
+
const state = activeContract(observed.decision, input.contractId);
|
|
595
|
+
if ("kind" in state)
|
|
596
|
+
return { kind: "refused", refusal: state };
|
|
597
|
+
const derivation = input.deriveDocument?.(state);
|
|
598
|
+
if (derivation === undefined || !documentIsCurrent(state, derivation.document)) {
|
|
599
|
+
return { kind: "refused", refusal: { kind: "document-moved", contractId: input.contractId } };
|
|
600
|
+
}
|
|
601
|
+
if (derivation.verification.kind === "refused") {
|
|
602
|
+
return { kind: "refused", refusal: derivation.verification.refusal };
|
|
603
|
+
}
|
|
604
|
+
const workspace = await auditWorkspace(input.scope, state);
|
|
605
|
+
if (workspace.kind === "unappointed") {
|
|
606
|
+
return accepted(state, [], {
|
|
607
|
+
candidate: { kind: "blocked", refusal: { kind: "worktree-missing", contractId: state.id } },
|
|
608
|
+
verification: { kind: "not-run" },
|
|
609
|
+
target: { kind: "not-observed" },
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
const prepared = await prepareDelivery(input.scope, {
|
|
613
|
+
contractId: state.id,
|
|
614
|
+
coordinates: state.coordinates,
|
|
615
|
+
...(workspace.appointment === undefined ? {} : { appointment: workspace.appointment }),
|
|
616
|
+
}, {
|
|
617
|
+
title: derivation.title,
|
|
618
|
+
requireBranchesToBeUpToDate: input.requireBranchesToBeUpToDate ?? false,
|
|
619
|
+
includeDirty: input.includeDirty ?? false,
|
|
620
|
+
});
|
|
621
|
+
if (prepared.kind === "refused") {
|
|
622
|
+
return accepted(state, [], {
|
|
623
|
+
candidate: { kind: "blocked", refusal: prepared.refusal },
|
|
624
|
+
verification: { kind: "not-run" },
|
|
625
|
+
target: { kind: "not-observed" },
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
const verified = derivation.verification.data === null
|
|
629
|
+
? undefined
|
|
630
|
+
: await auditCandidateVerification(input, state, prepared.data.integration.snapshot, derivation.verification.data);
|
|
631
|
+
const delivery = auditDeliveryRelation(state, prepared.data);
|
|
632
|
+
const verification = auditVerificationAnswer(verified);
|
|
339
633
|
const value = {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
634
|
+
candidate: await readyAuditCandidate(input.scope, prepared.data, workspace.answer, input.showDiff === true),
|
|
635
|
+
verification,
|
|
636
|
+
target: verification.kind === "stopped"
|
|
637
|
+
? { kind: "not-observed" }
|
|
638
|
+
: await auditTargetAnswer(input.scope, state, prepared.data),
|
|
639
|
+
...(delivery === undefined ? {} : { delivery }),
|
|
343
640
|
};
|
|
344
|
-
|
|
345
|
-
?
|
|
346
|
-
:
|
|
641
|
+
const obligations = {
|
|
642
|
+
...(verified?.cleanup === undefined ? {} : { cleanup: verified.cleanup }),
|
|
643
|
+
...(verified?.leak === undefined ? {} : { leak: verified.leak }),
|
|
644
|
+
};
|
|
645
|
+
return verified?.admission === undefined
|
|
646
|
+
? accepted(state, [], value, undefined, obligations)
|
|
647
|
+
: {
|
|
648
|
+
...admitted(verified.admission, value),
|
|
649
|
+
...obligations,
|
|
650
|
+
};
|
|
347
651
|
}
|
|
348
652
|
export async function reconcileOperation(input) {
|
|
349
653
|
try {
|
|
350
654
|
const observation = await reconcile({
|
|
351
655
|
repository: input.scope,
|
|
656
|
+
channel: input.channel,
|
|
352
657
|
contractId: input.contractId,
|
|
353
658
|
hooks: input.hooks,
|
|
354
659
|
retryHooks: input.retryHooks,
|
|
660
|
+
...(input.retainTerminalWorktree === undefined ? {} : { retainTerminalWorktree: input.retainTerminalWorktree }),
|
|
661
|
+
...(input.place === undefined ? {} : { place: input.place }),
|
|
355
662
|
});
|
|
356
663
|
return { state: observation.state, report: observation.result };
|
|
357
664
|
}
|
|
@@ -361,10 +668,19 @@ export async function reconcileOperation(input) {
|
|
|
361
668
|
return { state: null, report: reconcileObservationFailure(error) };
|
|
362
669
|
}
|
|
363
670
|
}
|
|
671
|
+
export async function worldContractStates(input) {
|
|
672
|
+
const observation = await withGitReadObservation(input.scope, input.channel, async (read) => await observeContractWorld(read));
|
|
673
|
+
return [...observation.contracts.values()].flatMap((value) => value.state === null ? [] : [value.state]);
|
|
674
|
+
}
|
|
364
675
|
export async function reconcileAllOperation(input) {
|
|
365
676
|
const git = input.scope;
|
|
366
|
-
const observation =
|
|
367
|
-
const contracts = (await reconcileBatch(git, observation.contracts.keys(),
|
|
677
|
+
const observation = await withGitReadObservation(input.scope, input.channel, async (read) => await observeContractWorld(read));
|
|
678
|
+
const contracts = (await reconcileBatch(git, input.channel, observation.contracts.keys(), {
|
|
679
|
+
hooks: input.hooks,
|
|
680
|
+
retryHooks: input.retryHooks,
|
|
681
|
+
retainTerminalWorktree: input.retainTerminalWorktree ?? false,
|
|
682
|
+
...(input.places === undefined ? {} : { places: input.places }),
|
|
683
|
+
})).map((item) => ({
|
|
368
684
|
contractId: item.contract,
|
|
369
685
|
state: item.state,
|
|
370
686
|
report: item.result,
|