@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
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WorldRoot } from "../world.js";
|
|
2
|
+
import type { BindDraftReceipt } from "./result.js";
|
|
3
|
+
export declare class BindDraftError extends Error {
|
|
4
|
+
readonly original: unknown;
|
|
5
|
+
readonly draft: BindDraftReceipt;
|
|
6
|
+
constructor(original: unknown, draft: BindDraftReceipt);
|
|
7
|
+
}
|
|
8
|
+
export declare function preserveBindDraft(world: WorldRoot, markdown: string, now?: number): Promise<BindDraftReceipt>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstatSync, mkdirSync, readFileSync, readdirSync, unlinkSync, utimesSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { repairDerivedFile, replaceFileDurably } from "../coordination/durable-file.js";
|
|
5
|
+
const RETENTION_MS = 7 * 24 * 60 * 60 * 1_000;
|
|
6
|
+
const DRAFT_NAME = /^bind-[0-9a-f]{64}\.md$/u;
|
|
7
|
+
export class BindDraftError extends Error {
|
|
8
|
+
original;
|
|
9
|
+
draft;
|
|
10
|
+
constructor(original, draft) {
|
|
11
|
+
super(original instanceof Error ? original.message : String(original));
|
|
12
|
+
this.name = "BindDraftError";
|
|
13
|
+
this.original = original;
|
|
14
|
+
this.draft = draft;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function diagnostic(error) {
|
|
18
|
+
return error instanceof Error ? error.message : String(error);
|
|
19
|
+
}
|
|
20
|
+
function sweep(directory, now) {
|
|
21
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
22
|
+
if (!entry.isFile() || !DRAFT_NAME.test(entry.name))
|
|
23
|
+
continue;
|
|
24
|
+
const path = join(directory, entry.name);
|
|
25
|
+
try {
|
|
26
|
+
if (now - lstatSync(path).mtimeMs > RETENTION_MS)
|
|
27
|
+
unlinkSync(path);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (error.code !== "ENOENT")
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function preserveBindDraft(world, markdown, now = Date.now()) {
|
|
36
|
+
const digest = createHash("sha256").update(markdown, "utf8").digest("hex");
|
|
37
|
+
const name = `bind-${digest}.md`;
|
|
38
|
+
const relativePath = `.keiyaku/draft/${name}`;
|
|
39
|
+
const directory = join(world, ".keiyaku", "draft");
|
|
40
|
+
const path = join(directory, name);
|
|
41
|
+
const warnings = [];
|
|
42
|
+
try {
|
|
43
|
+
mkdirSync(directory, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return { warning: `bind draft could not be preserved: ${diagnostic(error)}` };
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
await repairDerivedFile(join(directory, ".gitignore"), "*\n");
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
warnings.push(`bind draft ignore could not be maintained: ${diagnostic(error)}`);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
let equal = false;
|
|
56
|
+
try {
|
|
57
|
+
const status = lstatSync(path);
|
|
58
|
+
equal = status.isFile() && !status.isSymbolicLink() && readFileSync(path).equals(Buffer.from(markdown));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error.code !== "ENOENT")
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
if (equal) {
|
|
65
|
+
try {
|
|
66
|
+
const touched = new Date(now);
|
|
67
|
+
utimesSync(path, touched, touched);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error.code !== "ENOENT")
|
|
71
|
+
throw error;
|
|
72
|
+
await replaceFileDurably(path, markdown);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
await replaceFileDurably(path, markdown);
|
|
77
|
+
}
|
|
78
|
+
if (!readFileSync(path).equals(Buffer.from(markdown))) {
|
|
79
|
+
throw new Error(`bind draft bytes do not match their content address: ${relativePath}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
warnings.push(`bind draft could not be preserved: ${diagnostic(error)}`);
|
|
84
|
+
return { warning: warnings.join("; ") };
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
sweep(directory, now);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
warnings.push(`bind draft sweep failed: ${diagnostic(error)}`);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
path: relativePath,
|
|
94
|
+
...(warnings.length === 0 ? {} : { warning: warnings.join("; ") }),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { type ContractId, type Settings } from "../index.js";
|
|
1
|
+
import { type ActorId, type ContractId, type Settings } from "../index.js";
|
|
2
2
|
import { type AkumaInvocationResult } from "./commands/akuma-invoke.js";
|
|
3
3
|
import { type InstallInvocationResult } from "./commands/install.js";
|
|
4
4
|
import { type TaskInvocationResult } from "./commands/task-invoke.js";
|
|
5
5
|
import { type ParsedExecution } from "./parse.js";
|
|
6
6
|
import type { InvocationResult } from "./result.js";
|
|
7
|
-
export type { AcceptedFact,
|
|
7
|
+
export type { AcceptedFact, InvocationResult, Lag } from "./result.js";
|
|
8
8
|
type InvokeRuntime = Readonly<{
|
|
9
9
|
cwd?: string;
|
|
10
10
|
environment?: NodeJS.ProcessEnv;
|
|
11
|
-
readStdin?: () => string
|
|
11
|
+
readStdin?: () => Promise<string>;
|
|
12
|
+
actor?: ActorId;
|
|
12
13
|
}>;
|
|
13
14
|
export type SettingsInvocationResult = Readonly<{
|
|
14
15
|
kind: "settings";
|
package/build/src/cli/invoke.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { gatesFrom, Keiyaku, NoGitWorldError, Repo, requireBranchesToBeUpToDateFrom, settings, SettingsError, worktreeHooksFrom } from "../index.js";
|
|
4
|
-
import { kanshi, selectKanshi } from "../kanshi/index.js";
|
|
1
|
+
import { AkumaWorldScopeError, gatesFrom, Keiyaku, requireBranchesToBeUpToDateFrom, settings, SettingsError, worktreeHooksFrom } from "../index.js";
|
|
2
|
+
import { kanshi, selectKanshi, selectRegion } from "../kanshi/index.js";
|
|
5
3
|
import { resolveActor } from "./actor.js";
|
|
6
|
-
import { resultFromMutationCall } from "./accepted.js";
|
|
4
|
+
import { acceptedAbandon, acceptedAmend, acceptedArc, acceptedAudit, acceptedBind, acceptedDeliver, acceptedReview, resultFromMutationCall, } from "./accepted.js";
|
|
7
5
|
import { amendFromCommand } from "./commands/amend.js";
|
|
8
6
|
import { invokeAkuma, invokeAkumaStatus } from "./commands/akuma-invoke.js";
|
|
9
7
|
import { isParsedAkumaCommand } from "./commands/akuma.js";
|
|
@@ -11,42 +9,53 @@ import { bindFromCommand } from "./commands/bind.js";
|
|
|
11
9
|
import { installHarnesses } from "./commands/install.js";
|
|
12
10
|
import { invokeTask } from "./commands/task-invoke.js";
|
|
13
11
|
import { CliUsageError, renderCommandUsage } from "./parse.js";
|
|
12
|
+
import { isBlankInput } from "./usage.js";
|
|
14
13
|
import { contractFromInput, resolveContextualContract, resolveKanshiContract } from "./selectors.js";
|
|
15
14
|
import { resolveNamedAddress } from "../library/address.js";
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
import { assertExplicitRepoUse, resolveCliCoordinates } from "./coordinates.js";
|
|
16
|
+
import { BindDraftError, preserveBindDraft } from "./draft.js";
|
|
17
|
+
async function readStdin() {
|
|
18
|
+
const chunks = [];
|
|
19
|
+
for await (const chunk of process.stdin)
|
|
20
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
21
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
20
22
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
function selectedStdinDiagnostic(command) {
|
|
24
|
+
switch (command.command) {
|
|
25
|
+
case "bind":
|
|
26
|
+
case "amend":
|
|
27
|
+
case "arc":
|
|
28
|
+
return `${command.command} requires a nonblank stdin document`;
|
|
29
|
+
case "review":
|
|
30
|
+
return command.summaryFromStdin === true ? "review requires a nonblank summary" : undefined;
|
|
31
|
+
case "call":
|
|
32
|
+
case "tell":
|
|
33
|
+
return command.prompt.kind === "stdin" ? `${command.command} requires a nonblank prompt` : undefined;
|
|
34
|
+
case "task":
|
|
35
|
+
switch (command.stdin) {
|
|
36
|
+
case "document": return "task add requires a nonblank stdin document";
|
|
37
|
+
case "compose": return "task compose requires a nonblank stdin document";
|
|
38
|
+
case "body": return "task update --body requires a nonblank value";
|
|
39
|
+
case "append": return "task update --append requires a nonblank value";
|
|
40
|
+
case "note": return "task update --note requires a nonblank value";
|
|
41
|
+
default: return undefined;
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
return undefined;
|
|
29
45
|
}
|
|
30
46
|
}
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
async function withAcquiredStdin(command, runtime) {
|
|
48
|
+
const diagnostic = selectedStdinDiagnostic(command);
|
|
49
|
+
if (diagnostic === undefined)
|
|
50
|
+
return runtime;
|
|
51
|
+
const bytes = await (runtime.readStdin ?? readStdin)();
|
|
52
|
+
if (isBlankInput(bytes))
|
|
53
|
+
throw new CliUsageError(diagnostic);
|
|
54
|
+
return { ...runtime, readStdin: async () => bytes };
|
|
38
55
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
return World.at(coordinate);
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
if (error instanceof WorldError)
|
|
47
|
-
throw new CliUsageError(error.message);
|
|
48
|
-
throw error;
|
|
49
|
-
}
|
|
56
|
+
function settingsAt(root, environment) {
|
|
57
|
+
const home = environment.KEIYAKU_HOME?.trim();
|
|
58
|
+
return settings({ ...(root === undefined ? {} : { root }), ...(home === undefined || home.length === 0 ? {} : { home }) });
|
|
50
59
|
}
|
|
51
60
|
function selectedGates(value, name) {
|
|
52
61
|
try {
|
|
@@ -88,93 +97,47 @@ function actorFromEdge(actor, environment) {
|
|
|
88
97
|
}
|
|
89
98
|
return resolved;
|
|
90
99
|
}
|
|
91
|
-
function repoAt(coordinate) {
|
|
92
|
-
return Repo.at({ path: coordinate });
|
|
93
|
-
}
|
|
94
|
-
function optionalRepoAt(coordinate) {
|
|
95
|
-
try {
|
|
96
|
-
return repoAt(coordinate);
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
if (error instanceof NoGitWorldError)
|
|
100
|
-
return undefined;
|
|
101
|
-
throw error;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function repoUse(command) {
|
|
105
|
-
switch (command.command) {
|
|
106
|
-
case "bind":
|
|
107
|
-
case "amend":
|
|
108
|
-
case "deliver":
|
|
109
|
-
case "review":
|
|
110
|
-
case "arc":
|
|
111
|
-
case "abandon":
|
|
112
|
-
case "audit":
|
|
113
|
-
case "reconcile":
|
|
114
|
-
case "show":
|
|
115
|
-
return "required";
|
|
116
|
-
case "ls":
|
|
117
|
-
return command.query.kind === "contracts" ? "required" : "none";
|
|
118
|
-
case "status":
|
|
119
|
-
case "tell":
|
|
120
|
-
case "history":
|
|
121
|
-
case "fork":
|
|
122
|
-
return "optional";
|
|
123
|
-
case "wait":
|
|
124
|
-
case "kill":
|
|
125
|
-
return command.akuma.some((selector) => selector.startsWith("kei/")) ? "required" : "optional";
|
|
126
|
-
case "call":
|
|
127
|
-
return command.contract === undefined ? "none" : "required";
|
|
128
|
-
case "settings":
|
|
129
|
-
case "task":
|
|
130
|
-
case "install":
|
|
131
|
-
return "none";
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
function refuseUnusedRepo(command) {
|
|
135
|
-
if (command.command === "call")
|
|
136
|
-
throw new CliUsageError("--repo has no consumer without --contract");
|
|
137
|
-
throw new CliUsageError(`--repo has no consumer for ${command.command}`);
|
|
138
|
-
}
|
|
139
|
-
function repoFor(use, coordinate) {
|
|
140
|
-
switch (use) {
|
|
141
|
-
case "none": return undefined;
|
|
142
|
-
case "optional": return optionalRepoAt(coordinate);
|
|
143
|
-
case "required": return repoAt(coordinate);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
100
|
async function selectContract(repo, selector, scope) {
|
|
147
101
|
if (selector !== undefined && !selector.startsWith("@"))
|
|
148
102
|
return contractFromInput(repo, selector);
|
|
149
103
|
const id = resolveContextualContract(await Keiyaku.list({ repo }), selector, scope);
|
|
150
104
|
return contractFromInput(repo, id);
|
|
151
105
|
}
|
|
152
|
-
async function
|
|
153
|
-
|
|
106
|
+
async function bindDraftReceipt(establishWorld, markdown) {
|
|
107
|
+
try {
|
|
108
|
+
return preserveBindDraft(await establishWorld(), markdown);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return { warning: `bind draft could not be preserved: ${error instanceof Error ? error.message : String(error)}` };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function invokeBind({ parsed, repo, edge, configuration, hooks, establishWorld }) {
|
|
115
|
+
const markdown = await edge.readStdin();
|
|
154
116
|
const gates = selectedGates(configuration, parsed.gates);
|
|
155
117
|
const actor = actorFromEdge(parsed.actor, edge.environment);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const bound =
|
|
118
|
+
try {
|
|
119
|
+
const result = await resultFromMutationCall("bind", () => bindFromCommand({
|
|
120
|
+
command: parsed,
|
|
121
|
+
repo,
|
|
122
|
+
markdown,
|
|
123
|
+
gates,
|
|
124
|
+
...(actor === undefined ? {} : { actor }),
|
|
125
|
+
hooks,
|
|
126
|
+
}), (accepted) => {
|
|
127
|
+
const bound = accepted.facts.find((fact) => fact.kind === "bind");
|
|
166
128
|
if (bound === undefined || bound.kind !== "bind")
|
|
167
129
|
throw new Error("accepted bind is missing its bind fact");
|
|
168
|
-
return
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
130
|
+
return acceptedBind(accepted, bound.data.coordinates.target ?? null);
|
|
131
|
+
});
|
|
132
|
+
if (result.kind !== "refused")
|
|
133
|
+
return result;
|
|
134
|
+
return { ...result, draft: await bindDraftReceipt(establishWorld, markdown) };
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (!(error instanceof TypeError))
|
|
138
|
+
throw error;
|
|
139
|
+
throw new BindDraftError(error, await bindDraftReceipt(establishWorld, markdown));
|
|
140
|
+
}
|
|
178
141
|
}
|
|
179
142
|
function deliverRefusal(refusal) {
|
|
180
143
|
if (typeof refusal !== "object" || refusal === null || !("kind" in refusal) || refusal.kind !== "dirty-workspace") {
|
|
@@ -190,50 +153,28 @@ async function invokeDeliver(parsed, seat, requireBranchesToBeUpToDate) {
|
|
|
190
153
|
requireBranchesToBeUpToDate,
|
|
191
154
|
includeDirty: parsed.includeDirty,
|
|
192
155
|
hooks: seat.hooks,
|
|
193
|
-
}), {
|
|
156
|
+
}), (result) => acceptedDeliver(result, seat.id), {
|
|
194
157
|
coordinate: seat.id,
|
|
195
158
|
projectRefusal: deliverRefusal,
|
|
196
|
-
project: (result) => ({
|
|
197
|
-
obligations: {
|
|
198
|
-
...(result.value.verification === undefined ? {} : { verification: result.value.verification }),
|
|
199
|
-
...(result.value.placement === undefined ? {} : { placement: result.value.placement }),
|
|
200
|
-
...(result.value.cleanup === undefined ? {} : { cleanup: result.value.cleanup }),
|
|
201
|
-
...(result.value.leak === undefined ? {} : { leak: result.value.leak }),
|
|
202
|
-
},
|
|
203
|
-
}),
|
|
204
159
|
});
|
|
205
160
|
}
|
|
206
161
|
async function invokeReview(parsed, seat, readStdin) {
|
|
207
|
-
const summary = parsed.summaryFromStdin === true ? readStdin() : parsed.summary;
|
|
162
|
+
const summary = parsed.summaryFromStdin === true ? await readStdin() : parsed.summary;
|
|
208
163
|
return resultFromMutationCall("review", () => seat.contract.review({
|
|
209
164
|
verdict: parsed.verdict,
|
|
210
165
|
...(seat.actor === undefined ? {} : { actor: seat.actor }),
|
|
211
166
|
...(summary === undefined ? {} : { summary }),
|
|
212
167
|
hooks: seat.hooks,
|
|
213
|
-
}), {
|
|
214
|
-
coordinate: seat.id,
|
|
215
|
-
project: (result) => ({
|
|
216
|
-
obligations: result.value.placement === undefined ? {} : { placement: result.value.placement },
|
|
217
|
-
workspace: result.value.workspace,
|
|
218
|
-
}),
|
|
219
|
-
});
|
|
168
|
+
}), (result) => acceptedReview(result, seat.id), { coordinate: seat.id });
|
|
220
169
|
}
|
|
221
|
-
async function invokeAudit(parsed, seat) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
renderedDiff = diff === null ? unavailableDiff(delivery) : diff;
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
report: result.value,
|
|
233
|
-
...(renderedDiff === undefined ? {} : { diff: renderedDiff }),
|
|
234
|
-
};
|
|
235
|
-
},
|
|
236
|
-
});
|
|
170
|
+
async function invokeAudit(parsed, seat, requireBranchesToBeUpToDate) {
|
|
171
|
+
return resultFromMutationCall("audit", () => seat.contract.audit({
|
|
172
|
+
...(seat.actor === undefined ? {} : { actor: seat.actor }),
|
|
173
|
+
includeDirty: parsed.includeDirty,
|
|
174
|
+
showDiff: parsed.showDiff,
|
|
175
|
+
requireBranchesToBeUpToDate,
|
|
176
|
+
hooks: seat.hooks,
|
|
177
|
+
}), (result) => acceptedAudit(result, seat.id), { coordinate: seat.id });
|
|
237
178
|
}
|
|
238
179
|
async function invokeExisting({ parsed, repo, edge, scope, configuration, hooks }) {
|
|
239
180
|
const { id, contract } = await selectContract(repo, parsed.contract, scope);
|
|
@@ -241,32 +182,32 @@ async function invokeExisting({ parsed, repo, edge, scope, configuration, hooks
|
|
|
241
182
|
const seat = { contract, id, ...(actor === undefined ? {} : { actor }), hooks };
|
|
242
183
|
switch (parsed.command) {
|
|
243
184
|
case "amend": {
|
|
244
|
-
const markdown = edge.readStdin();
|
|
185
|
+
const markdown = await edge.readStdin();
|
|
245
186
|
const gates = parsed.gates === undefined
|
|
246
187
|
? undefined
|
|
247
188
|
: selectedGates(configuration, parsed.gates);
|
|
248
|
-
return resultFromMutationCall("amend", () => amendFromCommand({ command: parsed, repo, contract, markdown, gates, ...(actor === undefined ? {} : { actor }), hooks }), { coordinate: id });
|
|
189
|
+
return resultFromMutationCall("amend", () => amendFromCommand({ command: parsed, repo, contract, markdown, gates, ...(actor === undefined ? {} : { actor }), hooks }), (result) => acceptedAmend(result, id), { coordinate: id });
|
|
249
190
|
}
|
|
250
191
|
case "deliver":
|
|
251
192
|
return invokeDeliver(parsed, seat, selectedGitPolicy(configuration));
|
|
252
193
|
case "review":
|
|
253
194
|
return invokeReview(parsed, seat, edge.readStdin);
|
|
254
195
|
case "arc": {
|
|
255
|
-
const markdown = edge.readStdin();
|
|
196
|
+
const markdown = await edge.readStdin();
|
|
256
197
|
return resultFromMutationCall("arc", () => contract.arc({
|
|
257
198
|
markdown,
|
|
258
199
|
...(actor === undefined ? {} : { actor }),
|
|
259
200
|
hooks,
|
|
260
|
-
}), { coordinate: id });
|
|
201
|
+
}), (result) => acceptedArc(result, id), { coordinate: id });
|
|
261
202
|
}
|
|
262
203
|
case "abandon":
|
|
263
204
|
return resultFromMutationCall("abandon", () => contract.abandon({
|
|
264
205
|
...(actor === undefined ? {} : { actor }),
|
|
265
206
|
...(parsed.note === undefined ? {} : { note: parsed.note }),
|
|
266
207
|
hooks,
|
|
267
|
-
}), { coordinate: id });
|
|
208
|
+
}), (result) => acceptedAbandon(result, id), { coordinate: id });
|
|
268
209
|
case "audit":
|
|
269
|
-
return invokeAudit(parsed, seat);
|
|
210
|
+
return invokeAudit(parsed, seat, selectedGitPolicy(configuration));
|
|
270
211
|
default:
|
|
271
212
|
return parsed;
|
|
272
213
|
}
|
|
@@ -279,7 +220,7 @@ async function invokeAkumaCommand(parsed, input) {
|
|
|
279
220
|
const selected = contractFromInput(repo, parsed.contract);
|
|
280
221
|
return await invokeAkuma(parsed, {
|
|
281
222
|
path,
|
|
282
|
-
executionCwd,
|
|
223
|
+
...(executionCwd === undefined ? {} : { executionCwd }),
|
|
283
224
|
settings: configuration,
|
|
284
225
|
contract: selected.contract,
|
|
285
226
|
readStdin: edge.readStdin,
|
|
@@ -287,7 +228,7 @@ async function invokeAkumaCommand(parsed, input) {
|
|
|
287
228
|
}
|
|
288
229
|
return await invokeAkuma(parsed, {
|
|
289
230
|
path,
|
|
290
|
-
executionCwd,
|
|
231
|
+
...(executionCwd === undefined ? {} : { executionCwd }),
|
|
291
232
|
settings: configuration,
|
|
292
233
|
...(repo === undefined ? {} : { repo }),
|
|
293
234
|
readStdin: edge.readStdin,
|
|
@@ -298,13 +239,15 @@ async function invokeAkumaFromEdge(parsed, input) {
|
|
|
298
239
|
return await invokeAkumaCommand(parsed, input);
|
|
299
240
|
}
|
|
300
241
|
catch (error) {
|
|
242
|
+
if (error instanceof AkumaWorldScopeError)
|
|
243
|
+
throw error;
|
|
301
244
|
if (error instanceof TypeError)
|
|
302
245
|
throw new CliUsageError(error.message);
|
|
303
246
|
throw error;
|
|
304
247
|
}
|
|
305
248
|
}
|
|
306
|
-
function akumaWorldFor(parsed,
|
|
307
|
-
const world = parsed.command === "call" ?
|
|
249
|
+
async function akumaWorldFor(parsed, located, candidate, establish) {
|
|
250
|
+
const world = parsed.command === "call" ? candidate ?? await establish() : located;
|
|
308
251
|
if (world === null)
|
|
309
252
|
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
310
253
|
return world;
|
|
@@ -319,7 +262,7 @@ async function invokeCatalog(parsed, world, repo, edge) {
|
|
|
319
262
|
if (parsed.query.kind === "archetypes") {
|
|
320
263
|
return {
|
|
321
264
|
kind: "catalog",
|
|
322
|
-
catalog: await Keiyaku.ls({ query: parsed.query, settings: settingsAt(undefined, edge.environment) }),
|
|
265
|
+
catalog: await Keiyaku.ls({ query: parsed.query, settings: await settingsAt(undefined, edge.environment) }),
|
|
323
266
|
};
|
|
324
267
|
}
|
|
325
268
|
if (world === null)
|
|
@@ -336,7 +279,7 @@ async function invokeCatalog(parsed, world, repo, edge) {
|
|
|
336
279
|
}
|
|
337
280
|
}
|
|
338
281
|
async function invokeStatus(parsed, world, repo, edge) {
|
|
339
|
-
const configuration = settingsAt(world ?? undefined, edge.environment);
|
|
282
|
+
const configuration = await settingsAt(world ?? undefined, edge.environment);
|
|
340
283
|
if (parsed.akuma === true) {
|
|
341
284
|
if (world === null)
|
|
342
285
|
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
@@ -348,7 +291,7 @@ async function invokeStatus(parsed, world, repo, edge) {
|
|
|
348
291
|
}
|
|
349
292
|
if (parsed.contract.startsWith("@")) {
|
|
350
293
|
try {
|
|
351
|
-
const address = resolveNamedAddress({
|
|
294
|
+
const address = await resolveNamedAddress({
|
|
352
295
|
path: world,
|
|
353
296
|
selector: parsed.contract,
|
|
354
297
|
contracts: repo === undefined ? [] : (await Keiyaku.list({ repo })).rows,
|
|
@@ -371,26 +314,59 @@ async function invokeStatus(parsed, world, repo, edge) {
|
|
|
371
314
|
const contract = resolveKanshiContract(report, parsed.contract);
|
|
372
315
|
return { kind: "status", report: selectKanshi({ report, contract }), selection: "contract" };
|
|
373
316
|
}
|
|
374
|
-
async function
|
|
375
|
-
const
|
|
376
|
-
|
|
317
|
+
async function invokeRegion(parsed, world, repo) {
|
|
318
|
+
const read = async (region) => {
|
|
319
|
+
try {
|
|
320
|
+
return await kanshi({ world, repo, region });
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
if (error instanceof TypeError)
|
|
324
|
+
throw new CliUsageError(error.message);
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
if (parsed.contract === undefined) {
|
|
329
|
+
const selection = parsed.path !== undefined
|
|
330
|
+
? { kind: "path", path: parsed.path }
|
|
331
|
+
: parsed.overlap ? { kind: "overlap" } : { kind: "declarations" };
|
|
332
|
+
const report = await read(selection);
|
|
333
|
+
return { kind: "region", region: report.region ?? { kind: "absent" } };
|
|
334
|
+
}
|
|
335
|
+
const report = await read({ kind: "declarations" });
|
|
336
|
+
const contract = resolveKanshiContract(report, parsed.contract);
|
|
337
|
+
if (report.contracts.kind !== "present" || report.contracts.value.rows.every((row) => row.id !== contract || row.disposition !== "active")) {
|
|
338
|
+
throw new CliUsageError(`unknown contract selector: ${parsed.contract}`);
|
|
339
|
+
}
|
|
340
|
+
if (report.region?.kind !== "present" || report.region.value.kind !== "declarations") {
|
|
341
|
+
return { kind: "region", region: report.region ?? { kind: "absent" } };
|
|
342
|
+
}
|
|
343
|
+
const selection = parsed.overlap ? { kind: "overlap", contract } : { kind: "contract", contract };
|
|
344
|
+
return { kind: "region", region: { kind: "present", value: selectRegion({ declarations: report.region.value.declarations, selection }) } };
|
|
345
|
+
}
|
|
346
|
+
// eslint-disable-next-line complexity -- command dispatch keeps the CLI's existing boundary in one place.
|
|
347
|
+
async function invokeParsed(invocation, runtime) {
|
|
348
|
+
const coordinates = await resolveCliCoordinates({
|
|
349
|
+
...(runtime.cwd === undefined ? {} : { processCwd: runtime.cwd }),
|
|
350
|
+
...(invocation.cwd === undefined ? {} : { cwd: invocation.cwd }),
|
|
351
|
+
...(invocation.repo === undefined ? {} : { repo: invocation.repo }),
|
|
352
|
+
command: invocation.command,
|
|
353
|
+
});
|
|
354
|
+
const { cwd, repo, world, candidateWorld, establishWorld } = coordinates;
|
|
377
355
|
const edge = {
|
|
378
356
|
environment: runtime.environment ?? process.env,
|
|
379
|
-
readStdin: runtime.readStdin ??
|
|
357
|
+
readStdin: runtime.readStdin ?? readStdin,
|
|
380
358
|
};
|
|
381
359
|
const parsed = invocation.command;
|
|
382
|
-
const repoCoordinate = resolve(cwd, invocation.repo ?? ".");
|
|
383
|
-
const repo = repoFor(use, repoCoordinate);
|
|
384
|
-
const world = locateWorld(cwd);
|
|
385
360
|
if (parsed.command === "settings") {
|
|
386
|
-
return { kind: "settings", value: settingsAt(world ?? undefined, edge.environment) };
|
|
361
|
+
return { kind: "settings", value: await settingsAt(world ?? undefined, edge.environment) };
|
|
387
362
|
}
|
|
388
363
|
if (parsed.command === "task") {
|
|
389
364
|
try {
|
|
390
365
|
return await invokeTask(parsed, {
|
|
391
366
|
world,
|
|
392
|
-
establish:
|
|
367
|
+
establish: coordinates.establishWorld,
|
|
393
368
|
readStdin: edge.readStdin,
|
|
369
|
+
...(runtime.actor === undefined ? {} : { actor: runtime.actor }),
|
|
394
370
|
});
|
|
395
371
|
}
|
|
396
372
|
catch (error) {
|
|
@@ -400,11 +376,13 @@ async function invokeParsed(invocation, runtime, use) {
|
|
|
400
376
|
}
|
|
401
377
|
}
|
|
402
378
|
if (isParsedAkumaCommand(parsed)) {
|
|
403
|
-
const akumaWorld = akumaWorldFor(parsed,
|
|
404
|
-
const configuration = settingsAt(akumaWorld, edge.environment);
|
|
379
|
+
const akumaWorld = await akumaWorldFor(parsed, world, candidateWorld, coordinates.establishWorld);
|
|
380
|
+
const configuration = await settingsAt(akumaWorld, edge.environment);
|
|
405
381
|
return await invokeAkumaFromEdge(parsed, {
|
|
406
382
|
path: akumaWorld,
|
|
407
|
-
|
|
383
|
+
...(parsed.command === "call" && parsed.contract !== undefined && invocation.cwd === undefined
|
|
384
|
+
? {}
|
|
385
|
+
: { executionCwd: cwd }),
|
|
408
386
|
...(repo === undefined ? {} : { repo }),
|
|
409
387
|
configuration,
|
|
410
388
|
edge,
|
|
@@ -416,8 +394,10 @@ async function invokeParsed(invocation, runtime, use) {
|
|
|
416
394
|
return await invokeStatus(parsed, world, repo, edge);
|
|
417
395
|
if (repo === undefined)
|
|
418
396
|
throw new Error(`${parsed.command} requires a resolved Repo`);
|
|
397
|
+
if (parsed.command === "region")
|
|
398
|
+
return invokeRegion(parsed, world, repo);
|
|
419
399
|
const scope = cwd;
|
|
420
|
-
const configuration = settingsAt(world ?? undefined, edge.environment);
|
|
400
|
+
const configuration = await settingsAt(world ?? undefined, edge.environment);
|
|
421
401
|
const hooks = selectedHooks(configuration);
|
|
422
402
|
if (parsed.command === "show") {
|
|
423
403
|
const selected = await selectContract(repo, parsed.contract, scope);
|
|
@@ -432,27 +412,28 @@ async function invokeParsed(invocation, runtime, use) {
|
|
|
432
412
|
return { kind: "observation", command: "reconcile", ...await contract.reconcile({ hooks, retryHooks: parsed.retryHooks }) };
|
|
433
413
|
}
|
|
434
414
|
case "bind":
|
|
435
|
-
return invokeBind(parsed, repo, edge, configuration, hooks);
|
|
415
|
+
return invokeBind({ parsed, repo, edge, configuration, hooks, establishWorld });
|
|
436
416
|
default:
|
|
437
417
|
return invokeExisting({ parsed, repo, edge, scope, configuration, hooks });
|
|
438
418
|
}
|
|
439
419
|
}
|
|
440
|
-
|
|
441
|
-
|
|
420
|
+
function withResolvedTaskActor(command, runtime) {
|
|
421
|
+
if (command.command !== "task" || (command.action !== "add" && command.action !== "compose"))
|
|
422
|
+
return runtime;
|
|
423
|
+
const actor = actorFromEdge(typeof command.flags.actor === "string" ? command.flags.actor : undefined, runtime.environment ?? process.env);
|
|
424
|
+
return actor === undefined ? runtime : { ...runtime, actor };
|
|
442
425
|
}
|
|
443
426
|
export async function invoke(invocation, runtime = {}) {
|
|
444
427
|
try {
|
|
445
428
|
const command = invocation.command;
|
|
446
|
-
|
|
447
|
-
if (invocation.repo !== undefined && use === "none")
|
|
448
|
-
refuseUnusedRepo(command);
|
|
429
|
+
assertExplicitRepoUse(command, invocation.repo);
|
|
449
430
|
if (command.command === "install")
|
|
450
|
-
return
|
|
431
|
+
return installHarnesses(command.harnesses, runtime.environment ?? process.env);
|
|
451
432
|
return await invokeParsed({
|
|
452
433
|
...(invocation.cwd === undefined ? {} : { cwd: invocation.cwd }),
|
|
453
434
|
...(invocation.repo === undefined ? {} : { repo: invocation.repo }),
|
|
454
435
|
command,
|
|
455
|
-
},
|
|
436
|
+
}, await withAcquiredStdin(command, withResolvedTaskActor(command, runtime)));
|
|
456
437
|
}
|
|
457
438
|
catch (error) {
|
|
458
439
|
if (error instanceof CliUsageError && error.projection === undefined) {
|