@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,18 +1,29 @@
|
|
|
1
1
|
import type { ContractHead, ContractState, JournalEntry } from "../core/facts/types.js";
|
|
2
|
+
import type { WorktreeLeak } from "../git/scratch.js";
|
|
3
|
+
import type { ReconcileResult } from "../git/reconcile.js";
|
|
2
4
|
import type { AcceptedAdmission } from "./attempt.js";
|
|
5
|
+
import type { VerificationCleanupFailure } from "./intent.js";
|
|
3
6
|
import type { ProtocolResult, ProtocolTerminal } from "./run.js";
|
|
7
|
+
export type AcceptedProtocolStep = AcceptedAdmission & Readonly<{
|
|
8
|
+
physical?: ReconcileResult;
|
|
9
|
+
}>;
|
|
10
|
+
export type AcceptedObligations = Readonly<{
|
|
11
|
+
cleanup?: VerificationCleanupFailure;
|
|
12
|
+
leak?: WorktreeLeak;
|
|
13
|
+
}>;
|
|
4
14
|
export type IntentOutcome<Value, Refusal = never> = Readonly<{
|
|
5
15
|
kind: "accepted";
|
|
6
16
|
facts: readonly JournalEntry[];
|
|
7
17
|
head: ContractHead;
|
|
8
18
|
value: Value;
|
|
9
|
-
|
|
19
|
+
physical?: ReconcileResult;
|
|
20
|
+
} & AcceptedObligations> | Readonly<{
|
|
10
21
|
kind: "refused";
|
|
11
22
|
refusal: Refusal;
|
|
12
23
|
}> | Readonly<{
|
|
13
24
|
kind: "retry";
|
|
14
25
|
reason: ProtocolTerminal;
|
|
15
26
|
}>;
|
|
16
|
-
export declare function accepted<Value, Refusal = never>(state: ContractState, facts: readonly JournalEntry[], value: Value): IntentOutcome<Value, Refusal>;
|
|
17
|
-
export declare function admitted<Value, Refusal = never>(admission:
|
|
27
|
+
export declare function accepted<Value, Refusal = never>(state: ContractState, facts: readonly JournalEntry[], value: Value, physical?: ReconcileResult, obligations?: AcceptedObligations): IntentOutcome<Value, Refusal>;
|
|
28
|
+
export declare function admitted<Value, Refusal = never>(admission: AcceptedProtocolStep, value: Value): IntentOutcome<Value, Refusal>;
|
|
18
29
|
export declare function complete<Value, Refusal>(result: ProtocolResult<Refusal>, value: Value): IntentOutcome<Value, Refusal>;
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
export function accepted(state, facts, value) {
|
|
1
|
+
export function accepted(state, facts, value, physical, obligations) {
|
|
2
2
|
if (state.head === null)
|
|
3
3
|
throw new Error("accepted contract is missing its journal head");
|
|
4
|
-
return {
|
|
4
|
+
return {
|
|
5
|
+
kind: "accepted",
|
|
6
|
+
facts,
|
|
7
|
+
head: state.head,
|
|
8
|
+
value,
|
|
9
|
+
...(physical === undefined ? {} : { physical }),
|
|
10
|
+
...(obligations?.cleanup === undefined ? {} : { cleanup: obligations.cleanup }),
|
|
11
|
+
...(obligations?.leak === undefined ? {} : { leak: obligations.leak }),
|
|
12
|
+
};
|
|
5
13
|
}
|
|
6
14
|
export function admitted(admission, value) {
|
|
7
|
-
return accepted(admission.state, admission.facts, value);
|
|
15
|
+
return accepted(admission.state, admission.facts, value, admission.physical);
|
|
8
16
|
}
|
|
9
17
|
export function complete(result, value) {
|
|
10
18
|
if (result.kind === "refused")
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ActorId, ContractId, SnapshotId } from "../core/facts/types.js";
|
|
2
|
+
import { type PlacementRefusal } from "../core/verbs/placement.js";
|
|
3
|
+
import type { GitDecodeChannel } from "../git/read-observation.js";
|
|
4
|
+
import { type ReconcileResult } from "../git/reconcile.js";
|
|
5
|
+
import { type GitRepository } from "../git/repository.js";
|
|
6
|
+
import { type TargetPlacementObservationInput, type TargetPlacementRefusal } from "../git/target-placement.js";
|
|
7
|
+
import { type AcceptedAdmission } from "./attempt.js";
|
|
8
|
+
import { type ProtocolResult } from "./run.js";
|
|
9
|
+
export type PlacementExecutionFailure = Readonly<{
|
|
10
|
+
kind: "placement-failed";
|
|
11
|
+
diagnostic: string;
|
|
12
|
+
}>;
|
|
13
|
+
export type TargetMovedStop = Readonly<{
|
|
14
|
+
kind: "target-moved";
|
|
15
|
+
contractId: ContractId;
|
|
16
|
+
target: string;
|
|
17
|
+
expected: SnapshotId;
|
|
18
|
+
observed: SnapshotId | null;
|
|
19
|
+
}>;
|
|
20
|
+
export type PlacementProtocolResult<ExtraRefusal = never> = (AcceptedAdmission & Readonly<{
|
|
21
|
+
physical?: ReconcileResult;
|
|
22
|
+
}>) | Exclude<ProtocolResult<PlacementRefusal | TargetPlacementRefusal | ExtraRefusal>, AcceptedAdmission> | TargetMovedStop | PlacementExecutionFailure;
|
|
23
|
+
type PlacementProtocolInput = Readonly<{
|
|
24
|
+
contractId: ContractId;
|
|
25
|
+
actor?: ActorId;
|
|
26
|
+
at: string;
|
|
27
|
+
}>;
|
|
28
|
+
export type ProspectiveTargetPreview = Readonly<{
|
|
29
|
+
kind: "ready";
|
|
30
|
+
}> | Readonly<{
|
|
31
|
+
kind: "refused";
|
|
32
|
+
refusal: TargetPlacementRefusal;
|
|
33
|
+
}> | Readonly<{
|
|
34
|
+
kind: "failed";
|
|
35
|
+
diagnostic: string;
|
|
36
|
+
}>;
|
|
37
|
+
/** Observe prospective target followability without fencing or placing. */
|
|
38
|
+
export declare function observeProspectiveTargetPlacement(repository: GitRepository, input: TargetPlacementObservationInput): Promise<ProspectiveTargetPreview>;
|
|
39
|
+
/** Run the sole placement adjudicator inside the target's physical fence. */
|
|
40
|
+
export declare function admitPlacement<ExtraRefusal = never>(channel: GitDecodeChannel, repository: GitRepository, target: string | undefined, input: PlacementProtocolInput, onDeliveryMissing?: () => Promise<PlacementProtocolResult<ExtraRefusal> | undefined>): Promise<PlacementProtocolResult<ExtraRefusal>>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
|
|
2
|
+
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
3
|
+
import { contractState } from "../core/facts/observation.js";
|
|
4
|
+
import { decidePlacement } from "../core/verbs/placement.js";
|
|
5
|
+
import { observeGitForAdmissionAt } from "../git/observe.js";
|
|
6
|
+
import { reconcileEffectFailure } from "../git/reconcile.js";
|
|
7
|
+
import { GitPlumbingError } from "../git/repository.js";
|
|
8
|
+
import { acquireTargetPlacementFence, followTargetPlacement, prepareTargetPlacement, observeTargetHead, observeTargetPlacement, } from "../git/target-placement.js";
|
|
9
|
+
import { admitDecidedOffer, mintAttempts } from "./attempt.js";
|
|
10
|
+
import { prepareProtocolAttempt, runProtocol, } from "./run.js";
|
|
11
|
+
function placementFailure(error) {
|
|
12
|
+
return { kind: "placement-failed", diagnostic: error instanceof Error ? error.message : String(error) };
|
|
13
|
+
}
|
|
14
|
+
function expectedOperationalDiagnostic(error) {
|
|
15
|
+
if (error instanceof GitPlumbingError || error instanceof SqliteTransactionLockError) {
|
|
16
|
+
return error instanceof Error ? error.message : String(error);
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
function expectedPlacementFailure(error) {
|
|
21
|
+
return { kind: "placement-failed", diagnostic: expectedOperationalDiagnostic(error) };
|
|
22
|
+
}
|
|
23
|
+
/** Observe prospective target followability without fencing or placing. */
|
|
24
|
+
export async function observeProspectiveTargetPlacement(repository, input) {
|
|
25
|
+
try {
|
|
26
|
+
const observed = await observeTargetPlacement(repository, input);
|
|
27
|
+
return observed.kind === "ready"
|
|
28
|
+
? { kind: "ready" }
|
|
29
|
+
: { kind: "refused", refusal: observed.refusal };
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return { kind: "failed", diagnostic: expectedOperationalDiagnostic(error) };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function runFencedPlacement(repository, input, protocol) {
|
|
36
|
+
for (let index = 0; index < protocol.attempts.length; index += 1) {
|
|
37
|
+
const prepared = await prepareProtocolAttempt(protocol, protocol.attempts[index]);
|
|
38
|
+
if (prepared.kind === "refused")
|
|
39
|
+
return prepared;
|
|
40
|
+
const state = contractState(prepared.observation.decision, input.contractId);
|
|
41
|
+
if (state === null)
|
|
42
|
+
throw new Error("placement offer has no contract state");
|
|
43
|
+
if (prepared.offer.target === undefined)
|
|
44
|
+
throw new Error("targeted placement offer is missing its target movement");
|
|
45
|
+
const observed = await observeTargetHead(repository, prepared.offer.target.target);
|
|
46
|
+
if (observed !== prepared.offer.target.expectedOid) {
|
|
47
|
+
return {
|
|
48
|
+
kind: "target-moved",
|
|
49
|
+
contractId: input.contractId,
|
|
50
|
+
target: prepared.offer.target.target,
|
|
51
|
+
expected: prepared.offer.target.expectedOid,
|
|
52
|
+
observed,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const physical = await prepareTargetPlacement(repository, state, prepared.offer.target);
|
|
56
|
+
if (physical.kind === "refused")
|
|
57
|
+
return physical;
|
|
58
|
+
const result = await admitDecidedOffer({
|
|
59
|
+
channel: protocol.channel,
|
|
60
|
+
repository,
|
|
61
|
+
decisionObservation: prepared.observation,
|
|
62
|
+
attempt: prepared.attempt,
|
|
63
|
+
offer: prepared.offer,
|
|
64
|
+
primaryContract: input.contractId,
|
|
65
|
+
});
|
|
66
|
+
if (result.kind === "accepted") {
|
|
67
|
+
return { ...result, physical: await followTargetPlacement(repository, physical.placement) };
|
|
68
|
+
}
|
|
69
|
+
if (result.kind === "publication-failed")
|
|
70
|
+
return result;
|
|
71
|
+
if (result.kind === "collision" && index + 1 === protocol.attempts.length)
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
return { kind: "exhausted" };
|
|
75
|
+
}
|
|
76
|
+
/** Hold the existing target-placement fence for one owner callback. */
|
|
77
|
+
async function runUnderTargetPlacementFence(repository, target, run, onReleaseFailure) {
|
|
78
|
+
let held;
|
|
79
|
+
try {
|
|
80
|
+
held = await acquireTargetPlacementFence(repository, target);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return placementFailure(error);
|
|
84
|
+
}
|
|
85
|
+
let produced;
|
|
86
|
+
let result;
|
|
87
|
+
let exceptional;
|
|
88
|
+
try {
|
|
89
|
+
produced = await run();
|
|
90
|
+
result = produced;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error instanceof AuthorityCorruptionError || error instanceof TypeError)
|
|
94
|
+
exceptional = error;
|
|
95
|
+
else {
|
|
96
|
+
try {
|
|
97
|
+
result = expectedPlacementFailure(error);
|
|
98
|
+
}
|
|
99
|
+
catch (unexpected) {
|
|
100
|
+
exceptional = unexpected;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
let releaseFailure;
|
|
105
|
+
try {
|
|
106
|
+
held.close();
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
releaseFailure = error;
|
|
110
|
+
}
|
|
111
|
+
if (exceptional !== undefined)
|
|
112
|
+
throw exceptional;
|
|
113
|
+
if (result === undefined)
|
|
114
|
+
throw new Error("fenced target work produced no result");
|
|
115
|
+
if (releaseFailure !== undefined) {
|
|
116
|
+
return produced !== undefined && onReleaseFailure !== undefined
|
|
117
|
+
? onReleaseFailure(produced, releaseFailure)
|
|
118
|
+
: placementFailure(releaseFailure);
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
function isDeliveryMissing(result) {
|
|
123
|
+
return result.kind === "refused" && result.refusal.kind === "delivery-missing";
|
|
124
|
+
}
|
|
125
|
+
/** Run the sole placement adjudicator inside the target's physical fence. */
|
|
126
|
+
export async function admitPlacement(channel, repository, target, input, onDeliveryMissing) {
|
|
127
|
+
const attempts = mintAttempts({ entryCount: 1 });
|
|
128
|
+
const protocol = {
|
|
129
|
+
input,
|
|
130
|
+
channel,
|
|
131
|
+
repository,
|
|
132
|
+
contracts: [input.contractId],
|
|
133
|
+
attempts,
|
|
134
|
+
decide: decidePlacement,
|
|
135
|
+
observe: (observedRepository, observedChannel, contracts) => observeGitForAdmissionAt(observedRepository, observedChannel, contracts),
|
|
136
|
+
};
|
|
137
|
+
if (target === undefined)
|
|
138
|
+
return await runProtocol(protocol);
|
|
139
|
+
return await runUnderTargetPlacementFence(repository, target, async () => {
|
|
140
|
+
const result = await runFencedPlacement(repository, input, protocol);
|
|
141
|
+
if (onDeliveryMissing === undefined || !isDeliveryMissing(result))
|
|
142
|
+
return result;
|
|
143
|
+
return await onDeliveryMissing() ?? result;
|
|
144
|
+
}, (result, error) => result.kind === "accepted"
|
|
145
|
+
? { ...result, physical: reconcileEffectFailure(error, result.physical) }
|
|
146
|
+
: placementFailure(error));
|
|
147
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { GitReadObservation } from "../../git/read-observation.js";
|
|
2
2
|
import type { ContractId } from "../../core/facts/types.js";
|
|
3
3
|
export type ContractDocumentProjection = Readonly<{
|
|
4
4
|
contract: ContractId;
|
|
5
5
|
documentBytes: string;
|
|
6
6
|
}>;
|
|
7
7
|
/** Read every live contract document from one immutable Git snapshot. */
|
|
8
|
-
export declare function readDocuments(
|
|
8
|
+
export declare function readDocuments(observation: GitReadObservation): Promise<readonly ContractDocumentProjection[]>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { observeActiveContractWorld } from "../../git/observe.js";
|
|
2
2
|
/** Read every live contract document from one immutable Git snapshot. */
|
|
3
|
-
export function readDocuments(
|
|
4
|
-
const observed =
|
|
3
|
+
export async function readDocuments(observation) {
|
|
4
|
+
const observed = await observeActiveContractWorld(observation);
|
|
5
5
|
const documents = [];
|
|
6
6
|
for (const [contract, observation] of observed.contracts) {
|
|
7
7
|
const state = observation.state;
|
|
8
|
-
if (state === null
|
|
8
|
+
if (state === null)
|
|
9
9
|
continue;
|
|
10
10
|
documents.push({
|
|
11
11
|
contract,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { ContractTargetLag, ContractWorkspaceObservation } from "../../git/workspace.js";
|
|
1
2
|
import type { GitRepository } from "../../git/repository.js";
|
|
3
|
+
import type { GitDecodeChannel, GitReadObservation } from "../../git/read-observation.js";
|
|
2
4
|
import { type GateCurrent } from "../../core/facts/gate.js";
|
|
3
|
-
import type { ContractId, SnapshotId } from "../../core/facts/types.js";
|
|
5
|
+
import type { ContractId, ContractState, DeliverData, SnapshotId } from "../../core/facts/types.js";
|
|
4
6
|
export type ContractPhase = "waiting" | "bound" | "pending-delivery" | "claimed" | "abandoned";
|
|
5
7
|
export type ContractDisposition = "active" | "terminal";
|
|
6
8
|
export type ContractGateCurrent = GateCurrent;
|
|
@@ -8,14 +10,23 @@ export type ContractGateReport = Readonly<{
|
|
|
8
10
|
gate: string;
|
|
9
11
|
current: ContractGateCurrent;
|
|
10
12
|
}>;
|
|
13
|
+
export type { ContractTargetLag, ContractWorkspaceObservation };
|
|
11
14
|
export type ContractRow = Readonly<{
|
|
12
15
|
id: ContractId;
|
|
16
|
+
title: string | null;
|
|
13
17
|
phase: ContractPhase;
|
|
18
|
+
phaseAt: string;
|
|
14
19
|
disposition: ContractDisposition;
|
|
15
20
|
workspace: "worktree" | "here";
|
|
16
21
|
worktreePath: string | null;
|
|
22
|
+
workspaceObservation: ContractWorkspaceObservation;
|
|
17
23
|
target: string | null;
|
|
18
|
-
|
|
24
|
+
targetLag: ContractTargetLag;
|
|
25
|
+
delivery: DeliverData | null;
|
|
26
|
+
targetObservation: Readonly<{
|
|
27
|
+
head: SnapshotId | null;
|
|
28
|
+
drift: boolean;
|
|
29
|
+
}> | null;
|
|
19
30
|
gates: Readonly<{
|
|
20
31
|
reports: readonly ContractGateReport[];
|
|
21
32
|
satisfied: boolean;
|
|
@@ -23,6 +34,7 @@ export type ContractRow = Readonly<{
|
|
|
23
34
|
}>;
|
|
24
35
|
export type ContractBoard = Readonly<{
|
|
25
36
|
root: string;
|
|
37
|
+
state: SnapshotId | null;
|
|
26
38
|
rows: readonly ContractRow[];
|
|
27
39
|
}>;
|
|
28
40
|
export type ContractObservation = Readonly<{
|
|
@@ -32,7 +44,8 @@ export type ContractObservation = Readonly<{
|
|
|
32
44
|
kind: "present";
|
|
33
45
|
row: ContractRow;
|
|
34
46
|
}>;
|
|
47
|
+
export declare function phaseAtFor(state: Pick<ContractState, "terminal" | "delivery" | "bound">, bindAt: string): string;
|
|
35
48
|
/** Build the Contract board from one immutable git observation. */
|
|
36
|
-
export declare function readContractBoard(
|
|
37
|
-
/** Observe one Contract
|
|
38
|
-
export declare function
|
|
49
|
+
export declare function readContractBoard(observation: GitReadObservation): Promise<ContractBoard>;
|
|
50
|
+
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
51
|
+
export declare function readContractObservationAt(repository: GitRepository, channel: GitDecodeChannel, id: ContractId): Promise<ContractObservation>;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { observeActiveContractWorld, observeContractsForAdmissionInObservationAt, observeDeliveryTargetAt, withContractReadObservationAt, } from "../../git/observe.js";
|
|
2
|
+
import { decodeContractDocument } from "../../body/decode.js";
|
|
3
|
+
import { observeTargetLag, observeWorkspace, worktreePath, } from "../../git/workspace.js";
|
|
4
|
+
import { appointmentFor, readPlaceRegister, } from "../../workspace-place.js";
|
|
3
5
|
import { gateReports } from "../../core/facts/gate.js";
|
|
6
|
+
function titleFor(state) {
|
|
7
|
+
try {
|
|
8
|
+
return decodeContractDocument(state.terms.document.bytes).title;
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error instanceof TypeError)
|
|
12
|
+
return null;
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
4
16
|
function phaseFor(state) {
|
|
5
17
|
if (state.terminal?.kind === "claimed")
|
|
6
18
|
return "claimed";
|
|
@@ -12,17 +24,51 @@ function phaseFor(state) {
|
|
|
12
24
|
return "bound";
|
|
13
25
|
return "waiting";
|
|
14
26
|
}
|
|
15
|
-
function
|
|
27
|
+
export function phaseAtFor(state, bindAt) {
|
|
28
|
+
return state.terminal?.at ?? state.delivery?.at ?? state.bound?.at ?? bindAt;
|
|
29
|
+
}
|
|
30
|
+
async function managedWorkspaceFacts(repository, state, register, targetObservation) {
|
|
31
|
+
const appointed = appointmentFor(register, state.id);
|
|
32
|
+
if (appointed === undefined) {
|
|
33
|
+
return {
|
|
34
|
+
appointed,
|
|
35
|
+
workspaceObservation: { kind: "unappointed" },
|
|
36
|
+
targetLag: state.coordinates.target === undefined ? { kind: "none" } : { kind: "unknown" },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const path = worktreePath(repository, appointed.place);
|
|
40
|
+
const [workspaceObservation, targetLag] = await Promise.all([
|
|
41
|
+
observeWorkspace(repository, { kind: "worktree", path }, path),
|
|
42
|
+
observeTargetLag(repository, path, targetObservation?.head),
|
|
43
|
+
]);
|
|
44
|
+
return { appointed, workspaceObservation, targetLag };
|
|
45
|
+
}
|
|
46
|
+
async function hereWorkspaceFacts(repository, targetObservation) {
|
|
47
|
+
const [workspaceObservation, targetLag] = await Promise.all([
|
|
48
|
+
observeWorkspace(repository, { kind: "here" }, repository.effectiveCwd),
|
|
49
|
+
observeTargetLag(repository, repository.effectiveCwd, targetObservation?.head),
|
|
50
|
+
]);
|
|
51
|
+
return { appointed: undefined, workspaceObservation, targetLag };
|
|
52
|
+
}
|
|
53
|
+
async function rowFor(repository, state, bindAt, targetObservation, register) {
|
|
16
54
|
const workspace = state.coordinates.workspace;
|
|
17
55
|
const gates = gateReports(state);
|
|
56
|
+
const { appointed, workspaceObservation, targetLag } = workspace === "worktree"
|
|
57
|
+
? await managedWorkspaceFacts(repository, state, register, targetObservation)
|
|
58
|
+
: await hereWorkspaceFacts(repository, targetObservation);
|
|
18
59
|
return {
|
|
19
60
|
id: state.id,
|
|
61
|
+
title: titleFor(state),
|
|
20
62
|
phase: phaseFor(state),
|
|
63
|
+
phaseAt: phaseAtFor(state, bindAt),
|
|
21
64
|
disposition: state.terminal === null ? "active" : "terminal",
|
|
22
65
|
workspace,
|
|
23
|
-
worktreePath:
|
|
66
|
+
worktreePath: appointed === undefined ? null : worktreePath(repository, appointed.place),
|
|
67
|
+
workspaceObservation,
|
|
24
68
|
target: state.coordinates.target ?? null,
|
|
25
|
-
|
|
69
|
+
targetLag,
|
|
70
|
+
delivery: state.delivery?.data ?? null,
|
|
71
|
+
targetObservation,
|
|
26
72
|
gates: {
|
|
27
73
|
reports: gates.reports.map((report) => ({ gate: report.gate, current: report.current })),
|
|
28
74
|
satisfied: gates.satisfied,
|
|
@@ -30,18 +76,32 @@ function rowFor(repository, state) {
|
|
|
30
76
|
};
|
|
31
77
|
}
|
|
32
78
|
/** Build the Contract board from one immutable git observation. */
|
|
33
|
-
export function readContractBoard(
|
|
34
|
-
const observed =
|
|
79
|
+
export async function readContractBoard(observation) {
|
|
80
|
+
const observed = await observeActiveContractWorld(observation);
|
|
81
|
+
const register = await readPlaceRegister(observation.repository);
|
|
35
82
|
const rows = [];
|
|
36
83
|
for (const value of observed.contracts.values()) {
|
|
37
84
|
if (value.state === null)
|
|
38
85
|
continue;
|
|
39
|
-
|
|
86
|
+
const state = value.state;
|
|
87
|
+
const bindAt = value.entries[0].at;
|
|
88
|
+
rows.push(observeDeliveryTargetAt(observation, state).then((target) => rowFor(observation.repository, state, bindAt, target, register)));
|
|
40
89
|
}
|
|
41
|
-
return { root: repository.primaryWorktree, rows };
|
|
90
|
+
return { root: observation.repository.primaryWorktree, state: observed.snapshot, rows: await Promise.all(rows) };
|
|
42
91
|
}
|
|
43
|
-
/** Observe one Contract
|
|
44
|
-
export function
|
|
45
|
-
|
|
46
|
-
|
|
92
|
+
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
93
|
+
export async function readContractObservationAt(repository, channel, id) {
|
|
94
|
+
return withContractReadObservationAt(repository, channel, id, async (observation) => {
|
|
95
|
+
const observed = await observeContractsForAdmissionInObservationAt(observation, [id]);
|
|
96
|
+
const record = observed.journals.get(id);
|
|
97
|
+
if (record === undefined)
|
|
98
|
+
throw new Error(`missing requested Contract observation: ${id}`);
|
|
99
|
+
const state = record.state;
|
|
100
|
+
return state === null
|
|
101
|
+
? { kind: "missing", id }
|
|
102
|
+
: {
|
|
103
|
+
kind: "present",
|
|
104
|
+
row: await rowFor(observation.repository, state, record.entries[0].at, await observeDeliveryTargetAt(observation, state), await readPlaceRegister(observation.repository)),
|
|
105
|
+
};
|
|
106
|
+
});
|
|
47
107
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type GitDecisionObservation } from "../git/observe.js";
|
|
2
|
+
import type { GitDecodeChannel, GitTreeSelection } from "../git/read-observation.js";
|
|
2
3
|
import type { GitRepository } from "../git/repository.js";
|
|
4
|
+
import type { GitRefAssertion } from "../git/repository.js";
|
|
3
5
|
import type { AttemptContext, DecideInput, OfferDecision } from "../core/decide.js";
|
|
4
6
|
import type { Offer, TreeUpdate } from "../core/facts/offer.js";
|
|
5
7
|
import { type ContractId } from "../core/facts/types.js";
|
|
@@ -16,24 +18,64 @@ export type CompanionDecorator = (input: Readonly<{
|
|
|
16
18
|
observation: GitDecisionObservation;
|
|
17
19
|
contractId: ContractId;
|
|
18
20
|
offer: Offer;
|
|
19
|
-
}>) => readonly TreeUpdate[]
|
|
20
|
-
type RunProtocolInput<Input extends Readonly<{
|
|
21
|
+
}>) => readonly TreeUpdate[] | Promise<readonly TreeUpdate[]>;
|
|
22
|
+
export type RunProtocolInput<Input extends Readonly<{
|
|
21
23
|
contractId: ContractId;
|
|
22
|
-
}>, Refusal
|
|
23
|
-
|
|
24
|
+
}>, Refusal, Seed extends Readonly<{
|
|
25
|
+
contractId: ContractId;
|
|
26
|
+
}> = Input> = Readonly<{
|
|
27
|
+
channel: GitDecodeChannel;
|
|
24
28
|
repository: GitRepository;
|
|
25
29
|
contracts: readonly ContractId[];
|
|
26
30
|
attempts: readonly AttemptContext[];
|
|
27
31
|
decide: (input: DecideInput<Input>) => OfferDecision<Refusal>;
|
|
28
32
|
/** Override the targeted observer only for intents that need a full snapshot. */
|
|
29
|
-
observe?: (repository: GitRepository, contracts: readonly ContractId[]) => GitDecisionObservation
|
|
33
|
+
observe?: (repository: GitRepository, channel: GitDecodeChannel, contracts: readonly ContractId[]) => Promise<GitDecisionObservation>;
|
|
30
34
|
/** Mint verb-owned entries from the exact size of this attempt's observation. */
|
|
31
35
|
extendAttempt?: (attempt: AttemptContext, observedContractCount: number) => AttemptContext;
|
|
32
36
|
/** Add opaque companions from the exact immutable observation for this attempt. */
|
|
33
37
|
decorateOffer?: CompanionDecorator;
|
|
38
|
+
observationSelection?: GitTreeSelection;
|
|
39
|
+
}> & (Readonly<{
|
|
40
|
+
input: Input;
|
|
41
|
+
prepareInput?: never;
|
|
42
|
+
}> | Readonly<{
|
|
43
|
+
input: Seed;
|
|
44
|
+
prepareInput: (observation: GitDecisionObservation, input: Seed) => Readonly<{
|
|
45
|
+
kind: "prepared";
|
|
46
|
+
input: Input;
|
|
47
|
+
assertions?: readonly GitRefAssertion[];
|
|
48
|
+
}> | Readonly<{
|
|
49
|
+
kind: "refused";
|
|
50
|
+
refusal: Refusal;
|
|
51
|
+
}> | Promise<Readonly<{
|
|
52
|
+
kind: "prepared";
|
|
53
|
+
input: Input;
|
|
54
|
+
assertions?: readonly GitRefAssertion[];
|
|
55
|
+
}> | Readonly<{
|
|
56
|
+
kind: "refused";
|
|
57
|
+
refusal: Refusal;
|
|
58
|
+
}>>;
|
|
59
|
+
}>);
|
|
60
|
+
export type PreparedProtocolAttempt<Refusal> = Readonly<{
|
|
61
|
+
kind: "refused";
|
|
62
|
+
refusal: Refusal;
|
|
63
|
+
}> | Readonly<{
|
|
64
|
+
kind: "offered";
|
|
65
|
+
observation: GitDecisionObservation;
|
|
66
|
+
attempt: AttemptContext;
|
|
67
|
+
offer: Offer;
|
|
68
|
+
assertions: readonly GitRefAssertion[];
|
|
34
69
|
}>;
|
|
70
|
+
/** Form one decided offer without admitting or reinterpreting it. */
|
|
71
|
+
export declare function prepareProtocolAttempt<Input extends Readonly<{
|
|
72
|
+
contractId: ContractId;
|
|
73
|
+
}>, Refusal, Seed extends Readonly<{
|
|
74
|
+
contractId: ContractId;
|
|
75
|
+
}> = Input>(input: RunProtocolInput<Input, Refusal, Seed>, baseAttempt: AttemptContext): Promise<PreparedProtocolAttempt<Refusal>>;
|
|
35
76
|
/** Run bounded, verb-neutral attempts and return one real admission on acceptance. */
|
|
36
77
|
export declare function runProtocol<Input extends Readonly<{
|
|
37
78
|
contractId: ContractId;
|
|
38
|
-
}>, Refusal
|
|
39
|
-
|
|
79
|
+
}>, Refusal, Seed extends Readonly<{
|
|
80
|
+
contractId: ContractId;
|
|
81
|
+
}> = Input>(input: RunProtocolInput<Input, Refusal, Seed>): Promise<ProtocolResult<Refusal>>;
|
|
@@ -1,32 +1,60 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { extendAdmissionPathsAt, observeContractsForAdmissionAt, } from "../git/observe.js";
|
|
2
2
|
import { admitDecidedOffer } from "./attempt.js";
|
|
3
|
+
/** Form one decided offer without admitting or reinterpreting it. */
|
|
4
|
+
export async function prepareProtocolAttempt(input, baseAttempt) {
|
|
5
|
+
const decisionObservation = input.observe === undefined
|
|
6
|
+
? await observeContractsForAdmissionAt(input.repository, input.channel, input.contracts, input.observationSelection)
|
|
7
|
+
: await input.observe(input.repository, input.channel, input.contracts);
|
|
8
|
+
const observation = decisionObservation.decision;
|
|
9
|
+
const preparedInput = "prepareInput" in input && input.prepareInput !== undefined
|
|
10
|
+
? await input.prepareInput(decisionObservation, input.input)
|
|
11
|
+
: { kind: "prepared", input: input.input, assertions: [] };
|
|
12
|
+
if (preparedInput.kind === "refused")
|
|
13
|
+
return preparedInput;
|
|
14
|
+
const attempt = input.extendAttempt === undefined
|
|
15
|
+
? baseAttempt
|
|
16
|
+
: input.extendAttempt(baseAttempt, observation.size);
|
|
17
|
+
const decision = input.decide({ input: preparedInput.input, attempt, observation });
|
|
18
|
+
if (decision.kind === "refused")
|
|
19
|
+
return decision;
|
|
20
|
+
const companions = input.decorateOffer === undefined
|
|
21
|
+
? []
|
|
22
|
+
: await input.decorateOffer({
|
|
23
|
+
repository: input.repository,
|
|
24
|
+
observation: decisionObservation,
|
|
25
|
+
contractId: input.input.contractId,
|
|
26
|
+
offer: decision.offer,
|
|
27
|
+
});
|
|
28
|
+
const offer = companions.length === 0
|
|
29
|
+
? decision.offer
|
|
30
|
+
: { ...decision.offer, companions: [...(decision.offer.companions ?? []), ...companions] };
|
|
31
|
+
const admissionObservation = companions.length === 0
|
|
32
|
+
? decisionObservation
|
|
33
|
+
: await extendAdmissionPathsAt(input.channel, decisionObservation, companions.map(({ path }) => path));
|
|
34
|
+
return {
|
|
35
|
+
kind: "offered",
|
|
36
|
+
observation: admissionObservation,
|
|
37
|
+
attempt,
|
|
38
|
+
offer,
|
|
39
|
+
assertions: preparedInput.assertions ?? [],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
3
42
|
/** Run bounded, verb-neutral attempts and return one real admission on acceptance. */
|
|
4
|
-
export function runProtocol(input) {
|
|
43
|
+
export async function runProtocol(input) {
|
|
5
44
|
const attempts = input.attempts;
|
|
6
|
-
const contracts = input.contracts;
|
|
7
|
-
const observe = input.observe ?? observeContractsForAdmission;
|
|
8
45
|
for (let index = 0; index < attempts.length; index += 1) {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
: input.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
repository: input.repository,
|
|
22
|
-
observation: decisionObservation,
|
|
23
|
-
contractId: input.input.contractId,
|
|
24
|
-
offer: decision.offer,
|
|
25
|
-
});
|
|
26
|
-
const offer = companions.length === 0
|
|
27
|
-
? decision.offer
|
|
28
|
-
: { ...decision.offer, companions: [...(decision.offer.companions ?? []), ...companions] };
|
|
29
|
-
const result = admitDecidedOffer(input.repository, decisionObservation, attempt, offer, input.input.contractId);
|
|
46
|
+
const prepared = await prepareProtocolAttempt(input, attempts[index]);
|
|
47
|
+
if (prepared.kind === "refused")
|
|
48
|
+
return prepared;
|
|
49
|
+
const result = await admitDecidedOffer({
|
|
50
|
+
channel: input.channel,
|
|
51
|
+
repository: input.repository,
|
|
52
|
+
decisionObservation: prepared.observation,
|
|
53
|
+
attempt: prepared.attempt,
|
|
54
|
+
offer: prepared.offer,
|
|
55
|
+
primaryContract: input.input.contractId,
|
|
56
|
+
assertions: prepared.assertions,
|
|
57
|
+
});
|
|
30
58
|
if (result.kind === "accepted" || result.kind === "publication-failed")
|
|
31
59
|
return result;
|
|
32
60
|
if (result.kind === "collision" && index + 1 === attempts.length)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type StdioProcessExit } from "./stdio.js";
|
|
1
2
|
export type LineRpcNotification = Readonly<{
|
|
2
3
|
method: string;
|
|
3
4
|
params?: Readonly<Record<string, unknown>>;
|
|
@@ -5,20 +6,14 @@ export type LineRpcNotification = Readonly<{
|
|
|
5
6
|
export type LineRpcServerRequest = LineRpcNotification & Readonly<{
|
|
6
7
|
id: number | string;
|
|
7
8
|
}>;
|
|
8
|
-
export type LineRpcExit =
|
|
9
|
-
code: number | null;
|
|
10
|
-
signal: NodeJS.Signals | null;
|
|
11
|
-
stderr: string;
|
|
12
|
-
}>;
|
|
9
|
+
export type LineRpcExit = StdioProcessExit;
|
|
13
10
|
export declare class LineRpcProcess {
|
|
14
|
-
private readonly
|
|
11
|
+
private readonly process;
|
|
15
12
|
private readonly pending;
|
|
16
13
|
private readonly notifications;
|
|
17
14
|
private readonly serverRequests;
|
|
18
|
-
private readonly exited;
|
|
19
15
|
private nextId;
|
|
20
16
|
private stdout;
|
|
21
|
-
private stderr;
|
|
22
17
|
private closed;
|
|
23
18
|
constructor(input: Readonly<{
|
|
24
19
|
argv: readonly [string, ...string[]];
|
|
@@ -33,5 +28,6 @@ export declare class LineRpcProcess {
|
|
|
33
28
|
private fail;
|
|
34
29
|
request(method: string, params?: Readonly<Record<string, unknown>>): Promise<unknown>;
|
|
35
30
|
notify(method: string): void;
|
|
31
|
+
endInputAndDrain(timeoutMs?: number): Promise<void>;
|
|
36
32
|
close(force?: boolean): Promise<void>;
|
|
37
33
|
}
|