@astrosheep/keiyaku 4.0.1 → 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 +137 -5
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +23 -14
- package/build/src/akuma/akuma.js +120 -104
- package/build/src/akuma/archetype.d.ts +7 -6
- package/build/src/akuma/archetype.js +68 -41
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +408 -213
- package/build/src/akuma/heart/facts.d.ts +25 -34
- package/build/src/akuma/heart/facts.js +18 -7
- package/build/src/akuma/heart/index.d.ts +39 -42
- package/build/src/akuma/heart/index.js +134 -93
- package/build/src/akuma/heart/rows.d.ts +9 -31
- package/build/src/akuma/heart/rows.js +26 -44
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +7 -15
- 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 +28 -14
- package/build/src/akuma/heart/storage.js +86 -26
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +6 -1
- package/build/src/akuma/index.js +6 -0
- package/build/src/akuma/projection.d.ts +117 -38
- package/build/src/akuma/projection.js +208 -97
- 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 +12 -4
- package/build/src/akuma/provider.js +117 -70
- 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/events.js +66 -13
- package/build/src/akuma/providers/claude/index.d.ts +2 -1
- package/build/src/akuma/providers/claude/index.js +35 -21
- package/build/src/akuma/providers/codex-app-server/events.js +4 -1
- package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
- package/build/src/akuma/providers/codex-app-server/index.js +24 -31
- 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 +24 -59
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
- package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
- package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
- package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
- package/build/src/akuma/providers/pi/events.js +49 -11
- package/build/src/akuma/providers/pi/index.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +50 -21
- 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 -7
- package/build/src/akuma/requests.js +92 -65
- package/build/src/alias/index.d.ts +2 -2
- package/build/src/alias/index.js +10 -10
- 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/cli/accepted.d.ts +17 -13
- package/build/src/cli/accepted.js +72 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
- package/build/src/cli/commands/akuma-invoke.js +14 -9
- package/build/src/cli/commands/akuma.d.ts +13 -3
- package/build/src/cli/commands/akuma.js +67 -34
- package/build/src/cli/commands/contract.d.ts +18 -5
- package/build/src/cli/commands/contract.js +9 -3
- package/build/src/cli/commands/task-invoke.d.ts +17 -4
- package/build/src/cli/commands/task-invoke.js +43 -20
- 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 +51 -13
- 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 +4 -3
- package/build/src/cli/invoke.js +160 -179
- package/build/src/cli/main.js +34 -6
- package/build/src/cli/parse.d.ts +9 -2
- package/build/src/cli/parse.js +29 -7
- 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 +2 -2
- package/build/src/cli/render/akuma-tool.js +30 -4
- package/build/src/cli/render/akuma.d.ts +1 -0
- package/build/src/cli/render/akuma.js +211 -116
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +192 -79
- package/build/src/cli/render/kanshi.js +263 -168
- 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 -20
- 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 +7 -0
- package/build/src/cli/render/terminal.js +46 -0
- package/build/src/cli/render/text.js +6 -3
- package/build/src/cli/result.d.ts +115 -20
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +6 -5
- package/build/src/contract-worktree.js +95 -57
- package/build/src/coordination/durable-file.d.ts +4 -3
- package/build/src/coordination/durable-file.js +29 -25
- 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/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/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +0 -11
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +1 -7
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +4 -1
- package/build/src/dispatch/index.d.ts +2 -2
- package/build/src/dispatch/index.js +17 -17
- package/build/src/git/admission.d.ts +1 -1
- package/build/src/git/admission.js +11 -11
- package/build/src/git/hooks.js +13 -13
- package/build/src/git/integration.d.ts +14 -15
- package/build/src/git/integration.js +80 -44
- package/build/src/git/observe.d.ts +5 -3
- package/build/src/git/observe.js +18 -12
- package/build/src/git/read-observation.js +9 -9
- package/build/src/git/reconcile.d.ts +2 -0
- package/build/src/git/reconcile.js +138 -95
- package/build/src/git/repository.d.ts +27 -19
- package/build/src/git/repository.js +155 -83
- package/build/src/git/scratch.d.ts +7 -3
- package/build/src/git/scratch.js +44 -37
- package/build/src/git/target-placement.d.ts +40 -4
- package/build/src/git/target-placement.js +221 -101
- package/build/src/git/tender.d.ts +6 -5
- package/build/src/git/tender.js +24 -43
- package/build/src/git/terminal-seal.d.ts +1 -1
- package/build/src/git/terminal-seal.js +7 -5
- package/build/src/git/workspace.d.ts +36 -4
- package/build/src/git/workspace.js +53 -18
- package/build/src/identity/selector.js +1 -1
- package/build/src/index.d.ts +3 -3
- package/build/src/index.js +1 -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 +2 -1
- package/build/src/kanshi/read.js +118 -27
- package/build/src/kanshi/report.d.ts +50 -0
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +32 -0
- package/build/src/library/address.d.ts +12 -3
- package/build/src/library/address.js +77 -46
- package/build/src/library/akuma-creation.d.ts +6 -1
- package/build/src/library/akuma-creation.js +86 -13
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.js +4 -4
- package/build/src/library/catalog.d.ts +1 -1
- package/build/src/library/catalog.js +5 -8
- package/build/src/library/contract.d.ts +5 -6
- package/build/src/library/contract.js +11 -35
- package/build/src/library/delivery.d.ts +2 -1
- package/build/src/library/fleet.d.ts +2 -2
- package/build/src/library/fleet.js +35 -71
- package/build/src/library/keiyaku.d.ts +3 -2
- package/build/src/library/keiyaku.js +1 -0
- package/build/src/library/mutation.d.ts +7 -6
- package/build/src/library/mutation.js +23 -25
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/region.d.ts +12 -0
- package/build/src/library/region.js +15 -1
- package/build/src/library/repo.d.ts +4 -16
- package/build/src/library/repo.js +13 -38
- package/build/src/protocol/attempt.js +6 -6
- package/build/src/protocol/bind.js +4 -4
- package/build/src/protocol/intent.d.ts +15 -2
- package/build/src/protocol/intent.js +21 -6
- package/build/src/protocol/operations.d.ts +73 -22
- package/build/src/protocol/operations.js +292 -88
- package/build/src/protocol/outcome.d.ts +9 -3
- package/build/src/protocol/outcome.js +3 -1
- package/build/src/protocol/placement.d.ts +15 -4
- package/build/src/protocol/placement.js +58 -25
- package/build/src/protocol/read/status.d.ts +8 -1
- package/build/src/protocol/read/status.js +61 -14
- package/build/src/runtime/proc/line-rpc.d.ts +3 -8
- package/build/src/runtime/proc/line-rpc.js +16 -43
- package/build/src/runtime/proc/run.d.ts +15 -29
- package/build/src/runtime/proc/run.js +113 -105
- 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 +2 -2
- package/build/src/settings.js +8 -8
- package/build/src/settlement/fence.d.ts +0 -4
- package/build/src/settlement/fence.js +0 -9
- package/build/src/settlement/holder.d.ts +11 -1
- package/build/src/settlement/holder.js +25 -0
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/settlement/settle.js +52 -89
- package/build/src/task/board.d.ts +3 -3
- package/build/src/task/board.js +6 -9
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +14 -14
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +19 -7
- package/build/src/task/index.js +42 -23
- package/build/src/task/operations.d.ts +15 -9
- package/build/src/task/operations.js +78 -48
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +2 -2
- package/build/src/task/store.js +40 -25
- package/build/src/verification/execution.d.ts +4 -2
- package/build/src/verification/execution.js +9 -5
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +13 -2
- package/build/src/world.js +81 -48
- package/package.json +3 -2
- package/build/src/protocol/read/audit.d.ts +0 -31
- package/build/src/protocol/read/audit.js +0 -55
|
@@ -3,7 +3,7 @@ import { type PlacementRefusal } from "../core/verbs/placement.js";
|
|
|
3
3
|
import type { GitDecodeChannel } from "../git/read-observation.js";
|
|
4
4
|
import { type ReconcileResult } from "../git/reconcile.js";
|
|
5
5
|
import { type GitRepository } from "../git/repository.js";
|
|
6
|
-
import { type TargetPlacementRefusal } from "../git/target-placement.js";
|
|
6
|
+
import { type TargetPlacementObservationInput, type TargetPlacementRefusal } from "../git/target-placement.js";
|
|
7
7
|
import { type AcceptedAdmission } from "./attempt.js";
|
|
8
8
|
import { type ProtocolResult } from "./run.js";
|
|
9
9
|
export type PlacementExecutionFailure = Readonly<{
|
|
@@ -17,14 +17,25 @@ export type TargetMovedStop = Readonly<{
|
|
|
17
17
|
expected: SnapshotId;
|
|
18
18
|
observed: SnapshotId | null;
|
|
19
19
|
}>;
|
|
20
|
-
export type PlacementProtocolResult = (AcceptedAdmission & Readonly<{
|
|
20
|
+
export type PlacementProtocolResult<ExtraRefusal = never> = (AcceptedAdmission & Readonly<{
|
|
21
21
|
physical?: ReconcileResult;
|
|
22
|
-
}>) | Exclude<ProtocolResult<PlacementRefusal | TargetPlacementRefusal>, AcceptedAdmission> | TargetMovedStop | PlacementExecutionFailure;
|
|
22
|
+
}>) | Exclude<ProtocolResult<PlacementRefusal | TargetPlacementRefusal | ExtraRefusal>, AcceptedAdmission> | TargetMovedStop | PlacementExecutionFailure;
|
|
23
23
|
type PlacementProtocolInput = Readonly<{
|
|
24
24
|
contractId: ContractId;
|
|
25
25
|
actor?: ActorId;
|
|
26
26
|
at: string;
|
|
27
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>;
|
|
28
39
|
/** Run the sole placement adjudicator inside the target's physical fence. */
|
|
29
|
-
export declare function admitPlacement(channel: GitDecodeChannel, repository: GitRepository, target: string | undefined, input: PlacementProtocolInput): Promise<PlacementProtocolResult
|
|
40
|
+
export declare function admitPlacement<ExtraRefusal = never>(channel: GitDecodeChannel, repository: GitRepository, target: string | undefined, input: PlacementProtocolInput, onDeliveryMissing?: () => Promise<PlacementProtocolResult<ExtraRefusal> | undefined>): Promise<PlacementProtocolResult<ExtraRefusal>>;
|
|
30
41
|
export {};
|
|
@@ -2,19 +2,36 @@ import { SqliteTransactionLockError } from "../coordination/sqlite-transaction-l
|
|
|
2
2
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
3
3
|
import { contractState } from "../core/facts/observation.js";
|
|
4
4
|
import { decidePlacement } from "../core/verbs/placement.js";
|
|
5
|
+
import { observeGitForAdmissionAt } from "../git/observe.js";
|
|
5
6
|
import { reconcileEffectFailure } from "../git/reconcile.js";
|
|
6
7
|
import { GitPlumbingError } from "../git/repository.js";
|
|
7
|
-
import { acquireTargetPlacementFence, followTargetPlacement, prepareTargetPlacement, observeTargetHead, } from "../git/target-placement.js";
|
|
8
|
+
import { acquireTargetPlacementFence, followTargetPlacement, prepareTargetPlacement, observeTargetHead, observeTargetPlacement, } from "../git/target-placement.js";
|
|
8
9
|
import { admitDecidedOffer, mintAttempts } from "./attempt.js";
|
|
9
10
|
import { prepareProtocolAttempt, runProtocol, } from "./run.js";
|
|
10
11
|
function placementFailure(error) {
|
|
11
12
|
return { kind: "placement-failed", diagnostic: error instanceof Error ? error.message : String(error) };
|
|
12
13
|
}
|
|
13
|
-
function
|
|
14
|
-
if (error instanceof GitPlumbingError || error instanceof SqliteTransactionLockError)
|
|
15
|
-
return
|
|
14
|
+
function expectedOperationalDiagnostic(error) {
|
|
15
|
+
if (error instanceof GitPlumbingError || error instanceof SqliteTransactionLockError) {
|
|
16
|
+
return error instanceof Error ? error.message : String(error);
|
|
17
|
+
}
|
|
16
18
|
throw error;
|
|
17
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
|
+
}
|
|
18
35
|
async function runFencedPlacement(repository, input, protocol) {
|
|
19
36
|
for (let index = 0; index < protocol.attempts.length; index += 1) {
|
|
20
37
|
const prepared = await prepareProtocolAttempt(protocol, protocol.attempts[index]);
|
|
@@ -25,7 +42,7 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
25
42
|
throw new Error("placement offer has no contract state");
|
|
26
43
|
if (prepared.offer.target === undefined)
|
|
27
44
|
throw new Error("targeted placement offer is missing its target movement");
|
|
28
|
-
const observed = observeTargetHead(repository, prepared.offer.target.target);
|
|
45
|
+
const observed = await observeTargetHead(repository, prepared.offer.target.target);
|
|
29
46
|
if (observed !== prepared.offer.target.expectedOid) {
|
|
30
47
|
return {
|
|
31
48
|
kind: "target-moved",
|
|
@@ -35,7 +52,7 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
35
52
|
observed,
|
|
36
53
|
};
|
|
37
54
|
}
|
|
38
|
-
const physical = prepareTargetPlacement(repository, state, prepared.offer.target);
|
|
55
|
+
const physical = await prepareTargetPlacement(repository, state, prepared.offer.target);
|
|
39
56
|
if (physical.kind === "refused")
|
|
40
57
|
return physical;
|
|
41
58
|
const result = await admitDecidedOffer({
|
|
@@ -47,7 +64,7 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
47
64
|
primaryContract: input.contractId,
|
|
48
65
|
});
|
|
49
66
|
if (result.kind === "accepted") {
|
|
50
|
-
return { ...result, physical: followTargetPlacement(repository, physical.placement) };
|
|
67
|
+
return { ...result, physical: await followTargetPlacement(repository, physical.placement) };
|
|
51
68
|
}
|
|
52
69
|
if (result.kind === "publication-failed")
|
|
53
70
|
return result;
|
|
@@ -56,20 +73,8 @@ async function runFencedPlacement(repository, input, protocol) {
|
|
|
56
73
|
}
|
|
57
74
|
return { kind: "exhausted" };
|
|
58
75
|
}
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
const attempts = mintAttempts({ entryCount: 1 });
|
|
62
|
-
const protocol = {
|
|
63
|
-
input,
|
|
64
|
-
channel,
|
|
65
|
-
repository,
|
|
66
|
-
contracts: [input.contractId],
|
|
67
|
-
attempts,
|
|
68
|
-
decide: decidePlacement,
|
|
69
|
-
};
|
|
70
|
-
const run = () => runProtocol(protocol);
|
|
71
|
-
if (target === undefined)
|
|
72
|
-
return await run();
|
|
76
|
+
/** Hold the existing target-placement fence for one owner callback. */
|
|
77
|
+
async function runUnderTargetPlacementFence(repository, target, run, onReleaseFailure) {
|
|
73
78
|
let held;
|
|
74
79
|
try {
|
|
75
80
|
held = await acquireTargetPlacementFence(repository, target);
|
|
@@ -77,10 +82,12 @@ export async function admitPlacement(channel, repository, target, input) {
|
|
|
77
82
|
catch (error) {
|
|
78
83
|
return placementFailure(error);
|
|
79
84
|
}
|
|
85
|
+
let produced;
|
|
80
86
|
let result;
|
|
81
87
|
let exceptional;
|
|
82
88
|
try {
|
|
83
|
-
|
|
89
|
+
produced = await run();
|
|
90
|
+
result = produced;
|
|
84
91
|
}
|
|
85
92
|
catch (error) {
|
|
86
93
|
if (error instanceof AuthorityCorruptionError || error instanceof TypeError)
|
|
@@ -104,11 +111,37 @@ export async function admitPlacement(channel, repository, target, input) {
|
|
|
104
111
|
if (exceptional !== undefined)
|
|
105
112
|
throw exceptional;
|
|
106
113
|
if (result === undefined)
|
|
107
|
-
throw new Error("
|
|
114
|
+
throw new Error("fenced target work produced no result");
|
|
108
115
|
if (releaseFailure !== undefined) {
|
|
109
|
-
return
|
|
110
|
-
?
|
|
116
|
+
return produced !== undefined && onReleaseFailure !== undefined
|
|
117
|
+
? onReleaseFailure(produced, releaseFailure)
|
|
111
118
|
: placementFailure(releaseFailure);
|
|
112
119
|
}
|
|
113
120
|
return result;
|
|
114
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,7 +1,8 @@
|
|
|
1
|
+
import type { ContractTargetLag, ContractWorkspaceObservation } from "../../git/workspace.js";
|
|
1
2
|
import type { GitRepository } from "../../git/repository.js";
|
|
2
3
|
import type { GitDecodeChannel, GitReadObservation } from "../../git/read-observation.js";
|
|
3
4
|
import { type GateCurrent } from "../../core/facts/gate.js";
|
|
4
|
-
import type { ContractId, DeliverData, SnapshotId } from "../../core/facts/types.js";
|
|
5
|
+
import type { ContractId, ContractState, DeliverData, SnapshotId } from "../../core/facts/types.js";
|
|
5
6
|
export type ContractPhase = "waiting" | "bound" | "pending-delivery" | "claimed" | "abandoned";
|
|
6
7
|
export type ContractDisposition = "active" | "terminal";
|
|
7
8
|
export type ContractGateCurrent = GateCurrent;
|
|
@@ -9,13 +10,18 @@ export type ContractGateReport = Readonly<{
|
|
|
9
10
|
gate: string;
|
|
10
11
|
current: ContractGateCurrent;
|
|
11
12
|
}>;
|
|
13
|
+
export type { ContractTargetLag, ContractWorkspaceObservation };
|
|
12
14
|
export type ContractRow = Readonly<{
|
|
13
15
|
id: ContractId;
|
|
16
|
+
title: string | null;
|
|
14
17
|
phase: ContractPhase;
|
|
18
|
+
phaseAt: string;
|
|
15
19
|
disposition: ContractDisposition;
|
|
16
20
|
workspace: "worktree" | "here";
|
|
17
21
|
worktreePath: string | null;
|
|
22
|
+
workspaceObservation: ContractWorkspaceObservation;
|
|
18
23
|
target: string | null;
|
|
24
|
+
targetLag: ContractTargetLag;
|
|
19
25
|
delivery: DeliverData | null;
|
|
20
26
|
targetObservation: Readonly<{
|
|
21
27
|
head: SnapshotId | null;
|
|
@@ -38,6 +44,7 @@ export type ContractObservation = Readonly<{
|
|
|
38
44
|
kind: "present";
|
|
39
45
|
row: ContractRow;
|
|
40
46
|
}>;
|
|
47
|
+
export declare function phaseAtFor(state: Pick<ContractState, "terminal" | "delivery" | "bound">, bindAt: string): string;
|
|
41
48
|
/** Build the Contract board from one immutable git observation. */
|
|
42
49
|
export declare function readContractBoard(observation: GitReadObservation): Promise<ContractBoard>;
|
|
43
50
|
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
@@ -1,28 +1,72 @@
|
|
|
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";
|
|
4
|
-
|
|
5
|
-
|
|
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
|
+
}
|
|
16
|
+
function phaseFor(state) {
|
|
6
17
|
if (state.terminal?.kind === "claimed")
|
|
7
18
|
return "claimed";
|
|
8
19
|
if (state.terminal?.kind === "abandoned")
|
|
9
20
|
return "abandoned";
|
|
10
21
|
if (state.delivery !== null)
|
|
11
22
|
return "pending-delivery";
|
|
12
|
-
if (state.bound !== null
|
|
23
|
+
if (state.bound !== null)
|
|
13
24
|
return "bound";
|
|
14
25
|
return "waiting";
|
|
15
26
|
}
|
|
16
|
-
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) {
|
|
17
54
|
const workspace = state.coordinates.workspace;
|
|
18
55
|
const gates = gateReports(state);
|
|
56
|
+
const { appointed, workspaceObservation, targetLag } = workspace === "worktree"
|
|
57
|
+
? await managedWorkspaceFacts(repository, state, register, targetObservation)
|
|
58
|
+
: await hereWorkspaceFacts(repository, targetObservation);
|
|
19
59
|
return {
|
|
20
60
|
id: state.id,
|
|
21
|
-
|
|
61
|
+
title: titleFor(state),
|
|
62
|
+
phase: phaseFor(state),
|
|
63
|
+
phaseAt: phaseAtFor(state, bindAt),
|
|
22
64
|
disposition: state.terminal === null ? "active" : "terminal",
|
|
23
65
|
workspace,
|
|
24
|
-
worktreePath:
|
|
66
|
+
worktreePath: appointed === undefined ? null : worktreePath(repository, appointed.place),
|
|
67
|
+
workspaceObservation,
|
|
25
68
|
target: state.coordinates.target ?? null,
|
|
69
|
+
targetLag,
|
|
26
70
|
delivery: state.delivery?.data ?? null,
|
|
27
71
|
targetObservation,
|
|
28
72
|
gates: {
|
|
@@ -34,27 +78,30 @@ function rowFor(repository, state, targetObservation, eligible) {
|
|
|
34
78
|
/** Build the Contract board from one immutable git observation. */
|
|
35
79
|
export async function readContractBoard(observation) {
|
|
36
80
|
const observed = await observeActiveContractWorld(observation);
|
|
81
|
+
const register = await readPlaceRegister(observation.repository);
|
|
37
82
|
const rows = [];
|
|
38
83
|
for (const value of observed.contracts.values()) {
|
|
39
84
|
if (value.state === null)
|
|
40
85
|
continue;
|
|
41
86
|
const state = value.state;
|
|
42
|
-
|
|
87
|
+
const bindAt = value.entries[0].at;
|
|
88
|
+
rows.push(observeDeliveryTargetAt(observation, state).then((target) => rowFor(observation.repository, state, bindAt, target, register)));
|
|
43
89
|
}
|
|
44
90
|
return { root: observation.repository.primaryWorktree, state: observed.snapshot, rows: await Promise.all(rows) };
|
|
45
91
|
}
|
|
46
92
|
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
47
93
|
export async function readContractObservationAt(repository, channel, id) {
|
|
48
94
|
return withContractReadObservationAt(repository, channel, id, async (observation) => {
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
|
|
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;
|
|
53
100
|
return state === null
|
|
54
101
|
? { kind: "missing", id }
|
|
55
102
|
: {
|
|
56
103
|
kind: "present",
|
|
57
|
-
row: rowFor(observation.repository, state, await observeDeliveryTargetAt(observation, state),
|
|
104
|
+
row: await rowFor(observation.repository, state, record.entries[0].at, await observeDeliveryTargetAt(observation, state), await readPlaceRegister(observation.repository)),
|
|
58
105
|
};
|
|
59
106
|
});
|
|
60
107
|
}
|
|
@@ -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[]];
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { terminateProcessTree } from "./run.js";
|
|
3
|
-
const DEFAULT_DRAIN_TIMEOUT_MS = 1_000;
|
|
4
|
-
function bounded(promise, milliseconds) {
|
|
5
|
-
return new Promise((resolve, reject) => {
|
|
6
|
-
const timer = setTimeout(() => resolve(undefined), milliseconds);
|
|
7
|
-
void promise.then((value) => { clearTimeout(timer); resolve(value); }, (error) => { clearTimeout(timer); reject(error); });
|
|
8
|
-
});
|
|
9
|
-
}
|
|
1
|
+
import { spawnStdioProcess } from "./stdio.js";
|
|
10
2
|
function object(value) {
|
|
11
3
|
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
12
4
|
? value
|
|
@@ -16,37 +8,25 @@ function text(value) {
|
|
|
16
8
|
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
17
9
|
}
|
|
18
10
|
export class LineRpcProcess {
|
|
19
|
-
|
|
11
|
+
process;
|
|
20
12
|
pending = new Map();
|
|
21
13
|
notifications = new Set();
|
|
22
14
|
serverRequests = new Set();
|
|
23
|
-
exited;
|
|
24
15
|
nextId = 1;
|
|
25
16
|
stdout = "";
|
|
26
|
-
stderr = "";
|
|
27
17
|
closed = false;
|
|
28
18
|
constructor(input) {
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
34
|
-
windowsHide: true,
|
|
35
|
-
});
|
|
36
|
-
this.child.stdout.setEncoding("utf8");
|
|
37
|
-
this.child.stderr.setEncoding("utf8");
|
|
38
|
-
this.child.stdout.on("data", (chunk) => this.consume(chunk));
|
|
39
|
-
this.child.stderr.on("data", (chunk) => { this.stderr = `${this.stderr}${chunk}`.slice(-4_000); });
|
|
40
|
-
this.child.on("error", (error) => this.fail(error));
|
|
41
|
-
this.exited = new Promise((resolve) => this.child.once("close", (code, signal) => {
|
|
19
|
+
this.process = spawnStdioProcess(input);
|
|
20
|
+
this.process.output.setEncoding("utf8");
|
|
21
|
+
this.process.output.on("data", (chunk) => this.consume(chunk));
|
|
22
|
+
void this.process.exited.then((exit) => {
|
|
42
23
|
this.closed = true;
|
|
43
|
-
this.fail(new Error(`line RPC process exited${code === null ? "" : ` with code ${code}`}`));
|
|
44
|
-
|
|
45
|
-
}));
|
|
24
|
+
this.fail(new Error(`line RPC process exited${exit.code === null ? "" : ` with code ${exit.code}`}`));
|
|
25
|
+
});
|
|
46
26
|
}
|
|
47
27
|
onNotification(listener) { this.notifications.add(listener); }
|
|
48
28
|
onServerRequest(listener) { this.serverRequests.add(listener); }
|
|
49
|
-
onExit(listener) { void this.exited.then(listener); }
|
|
29
|
+
onExit(listener) { void this.process.exited.then(listener); }
|
|
50
30
|
consume(chunk) {
|
|
51
31
|
this.stdout += chunk;
|
|
52
32
|
for (;;) {
|
|
@@ -105,7 +85,7 @@ export class LineRpcProcess {
|
|
|
105
85
|
const id = this.nextId++;
|
|
106
86
|
return new Promise((resolve, reject) => {
|
|
107
87
|
this.pending.set(id, { resolve, reject });
|
|
108
|
-
this.
|
|
88
|
+
this.process.input.write(`${JSON.stringify({ id, method, ...(params === undefined ? {} : { params }) })}\n`, (error) => {
|
|
109
89
|
if (error === null || error === undefined)
|
|
110
90
|
return;
|
|
111
91
|
this.pending.delete(id);
|
|
@@ -115,31 +95,24 @@ export class LineRpcProcess {
|
|
|
115
95
|
}
|
|
116
96
|
notify(method) {
|
|
117
97
|
if (!this.closed)
|
|
118
|
-
this.
|
|
98
|
+
this.process.input.write(`${JSON.stringify({ method })}\n`);
|
|
119
99
|
}
|
|
120
|
-
async endInputAndDrain(timeoutMs
|
|
100
|
+
async endInputAndDrain(timeoutMs) {
|
|
121
101
|
if (this.closed) {
|
|
122
|
-
await this.exited;
|
|
102
|
+
await this.process.exited;
|
|
123
103
|
return;
|
|
124
104
|
}
|
|
125
105
|
this.closed = true;
|
|
126
106
|
this.fail(new Error("line RPC process is closed"));
|
|
127
|
-
this.
|
|
128
|
-
const drained = await bounded(this.exited, timeoutMs);
|
|
129
|
-
if (drained === undefined) {
|
|
130
|
-
await terminateProcessTree(this.child.pid, true);
|
|
131
|
-
await this.exited;
|
|
132
|
-
}
|
|
107
|
+
await this.process.endInputAndDrain(timeoutMs);
|
|
133
108
|
}
|
|
134
109
|
async close(force = false) {
|
|
135
110
|
if (this.closed) {
|
|
136
|
-
await this.exited;
|
|
111
|
+
await this.process.exited;
|
|
137
112
|
return;
|
|
138
113
|
}
|
|
139
114
|
this.closed = true;
|
|
140
115
|
this.fail(new Error("line RPC process is closed"));
|
|
141
|
-
this.
|
|
142
|
-
await terminateProcessTree(this.child.pid, force);
|
|
143
|
-
await this.exited;
|
|
116
|
+
await this.process.close(force);
|
|
144
117
|
}
|
|
145
118
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
1
2
|
type ProcessLaunch = Readonly<{
|
|
2
3
|
readonly argv: readonly string[];
|
|
3
4
|
readonly cwd?: string;
|
|
@@ -28,43 +29,28 @@ type ProcessCancelled = Readonly<{
|
|
|
28
29
|
readonly kind: "cancelled";
|
|
29
30
|
}>;
|
|
30
31
|
export type ProcessOutcome = ProcessTerminal | ProcessTimeout | ProcessSpawnError | ProcessUnknownExit | ProcessCancelled;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}>;
|
|
35
|
-
export type ProcessIdentityProbe = Readonly<{
|
|
36
|
-
kind: "gone" | "alive" | "replaced";
|
|
37
|
-
}> | Readonly<{
|
|
38
|
-
kind: "unverifiable";
|
|
39
|
-
diagnostic: string;
|
|
40
|
-
}>;
|
|
41
|
-
export type ProcessCollar = Readonly<{
|
|
42
|
-
pid: number;
|
|
43
|
-
processGroup: number;
|
|
44
|
-
spawnedAt: string;
|
|
32
|
+
type ProcessStreamError = Readonly<{
|
|
33
|
+
readonly kind: "stream-error";
|
|
34
|
+
readonly diagnostic: string;
|
|
45
35
|
}>;
|
|
46
|
-
export type
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
kind: "alive";
|
|
50
|
-
}> | Readonly<{
|
|
51
|
-
kind: "unverifiable";
|
|
52
|
-
diagnostic: string;
|
|
36
|
+
export type ProcessConsumption = Readonly<{
|
|
37
|
+
readonly outcome: ProcessOutcome | ProcessStreamError;
|
|
38
|
+
readonly pid: number | null;
|
|
53
39
|
}>;
|
|
54
|
-
export type PutDownEvidence = "killed" | "already-dead" | "alive-after-sigkill" | "unavailable";
|
|
55
40
|
export type DetachedProcessInput = Readonly<{
|
|
56
41
|
argv: readonly string[];
|
|
57
42
|
cwd: string;
|
|
58
43
|
env?: NodeJS.ProcessEnv;
|
|
59
44
|
log: string;
|
|
60
45
|
}>;
|
|
61
|
-
export
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
export declare function
|
|
67
|
-
export declare function
|
|
46
|
+
export type OwnedProcess = Readonly<{
|
|
47
|
+
pid: number;
|
|
48
|
+
terminate(force?: boolean): Promise<void>;
|
|
49
|
+
release(): void;
|
|
50
|
+
}>;
|
|
51
|
+
export declare function terminateOwnedProcess(child: ChildProcess, force?: boolean): Promise<void>;
|
|
52
|
+
export declare function spawnDetachedProcess(input: DetachedProcessInput): Promise<OwnedProcess>;
|
|
68
53
|
export declare function runProcess(input: ProcessInput): Promise<ProcessOutcome>;
|
|
69
54
|
export declare function runProcessToExit(input: ProcessLaunch): Promise<ProcessOutcome>;
|
|
55
|
+
export declare function consumeProcessStdout(input: ProcessInput, consume: (chunk: Buffer) => void): Promise<ProcessConsumption>;
|
|
70
56
|
export {};
|