@astrosheep/keiyaku 4.0.3 → 4.0.5
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/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 +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +15 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +34 -13
- package/build/src/akuma/akuma.d.ts +34 -12
- package/build/src/akuma/akuma.js +118 -63
- package/build/src/akuma/allowed.d.ts +7 -0
- package/build/src/akuma/allowed.js +33 -0
- package/build/src/akuma/archetype.d.ts +7 -4
- package/build/src/akuma/archetype.js +15 -16
- package/build/src/akuma/body.d.ts +6 -1
- package/build/src/akuma/body.js +36 -27
- package/build/src/akuma/heart/facts.d.ts +82 -14
- package/build/src/akuma/heart/index.d.ts +5 -18
- package/build/src/akuma/heart/index.js +14 -84
- package/build/src/akuma/heart/request-authority.d.ts +12 -0
- package/build/src/akuma/heart/request-authority.js +119 -0
- package/build/src/akuma/heart/request-rows.d.ts +16 -0
- package/build/src/akuma/heart/request-rows.js +88 -0
- package/build/src/akuma/heart/rows.d.ts +1 -26
- package/build/src/akuma/heart/rows.js +0 -50
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +22 -10
- package/build/src/akuma/heart/soul.js +2 -36
- package/build/src/akuma/heart/storage.d.ts +1 -0
- package/build/src/akuma/heart/storage.js +15 -0
- package/build/src/akuma/heart/timeline.d.ts +1 -5
- package/build/src/akuma/heart/timeline.js +8 -17
- package/build/src/akuma/index.d.ts +5 -2
- package/build/src/akuma/index.js +1 -0
- package/build/src/akuma/projection.d.ts +17 -3
- package/build/src/akuma/projection.js +40 -3
- package/build/src/akuma/provider-recipe.js +1 -11
- package/build/src/akuma/provider.d.ts +2 -7
- package/build/src/akuma/provider.js +2 -1
- package/build/src/akuma/providers/acp/core.d.ts +3 -1
- package/build/src/akuma/providers/acp/core.js +10 -6
- package/build/src/akuma/providers/acp/events.d.ts +11 -3
- package/build/src/akuma/providers/acp/events.js +78 -4
- package/build/src/akuma/providers/acp/index.js +0 -1
- package/build/src/akuma/providers/claude/events.js +62 -3
- package/build/src/akuma/providers/claude/index.d.ts +0 -4
- package/build/src/akuma/providers/claude/index.js +7 -3
- package/build/src/akuma/providers/codex-app-server/events.js +1 -13
- package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
- package/build/src/akuma/providers/codex-app-server/index.js +0 -2
- package/build/src/akuma/providers/grok-build/index.d.ts +2 -1
- package/build/src/akuma/providers/grok-build/index.js +72 -3
- package/build/src/akuma/providers/opencode-sdk/events.js +71 -6
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
- package/build/src/akuma/providers/opencode-sdk/index.js +8 -4
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +1 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +1 -1
- package/build/src/akuma/providers/pi/events.js +17 -3
- package/build/src/akuma/providers/pi/index.js +11 -4
- package/build/src/akuma/providers/unified-patch.d.ts +4 -0
- package/build/src/akuma/providers/unified-patch.js +14 -0
- package/build/src/akuma/publication.d.ts +1 -1
- package/build/src/akuma/publication.js +1 -1
- package/build/src/akuma/request-serve.d.ts +87 -0
- package/build/src/akuma/request-serve.js +484 -0
- package/build/src/akuma/request-wire.d.ts +124 -0
- package/build/src/akuma/request-wire.js +380 -0
- package/build/src/akuma/requests.d.ts +41 -41
- package/build/src/akuma/requests.js +75 -374
- package/build/src/akuma-body.d.ts +8 -0
- package/build/src/akuma-body.js +84 -0
- package/build/src/body/arc.js +4 -29
- package/build/src/body/decode.js +5 -39
- package/build/src/body/envelope.d.ts +7 -0
- package/build/src/body/envelope.js +37 -0
- package/build/src/cli/accepted.d.ts +4 -1
- package/build/src/cli/accepted.js +39 -9
- package/build/src/cli/commands/akuma-invoke.d.ts +8 -7
- package/build/src/cli/commands/akuma-invoke.js +18 -10
- package/build/src/cli/commands/akuma.d.ts +11 -2
- package/build/src/cli/commands/akuma.js +67 -28
- package/build/src/cli/commands/amend.d.ts +1 -1
- package/build/src/cli/commands/amend.js +1 -1
- package/build/src/cli/commands/contract.d.ts +8 -8
- package/build/src/cli/commands/contract.js +3 -3
- package/build/src/cli/commands/install.js +2 -2
- package/build/src/cli/commands/task-invoke.js +98 -9
- package/build/src/cli/commands/task-query.d.ts +1 -1
- package/build/src/cli/commands/task-query.js +11 -5
- package/build/src/cli/coordinates.d.ts +2 -0
- package/build/src/cli/coordinates.js +12 -5
- package/build/src/cli/invoke.d.ts +1 -0
- package/build/src/cli/invoke.js +116 -75
- package/build/src/cli/main.d.ts +2 -0
- package/build/src/cli/main.js +29 -4
- package/build/src/cli/parse.d.ts +3 -2
- package/build/src/cli/parse.js +25 -8
- package/build/src/cli/render/akuma.d.ts +2 -2
- package/build/src/cli/render/akuma.js +138 -24
- package/build/src/cli/render/audit.js +18 -8
- package/build/src/cli/render/contract.d.ts +2 -0
- package/build/src/cli/render/contract.js +243 -36
- package/build/src/cli/render/kanshi.js +64 -29
- package/build/src/cli/render/receipt.d.ts +2 -1
- package/build/src/cli/render/receipt.js +37 -2
- package/build/src/cli/render/terminal.d.ts +0 -2
- package/build/src/cli/render/terminal.js +0 -29
- package/build/src/cli/render/text.js +3 -1
- package/build/src/cli/result.d.ts +52 -9
- package/build/src/cli/selectors.d.ts +1 -0
- package/build/src/cli/selectors.js +9 -6
- package/build/src/contract-worktree.d.ts +1 -2
- package/build/src/contract-worktree.js +7 -9
- package/build/src/core/facts/codec.js +9 -0
- package/build/src/core/facts/fold.js +13 -1
- package/build/src/core/facts/types.d.ts +8 -1
- package/build/src/core/subject.js +4 -3
- package/build/src/core/verbs/placement.d.ts +9 -1
- package/build/src/core/verbs/placement.js +24 -6
- package/build/src/core/verbs/reintegrate.d.ts +13 -0
- package/build/src/core/verbs/reintegrate.js +24 -0
- package/build/src/dispatch/index.d.ts +1 -1
- package/build/src/dispatch/index.js +50 -39
- package/build/src/git/admission.d.ts +2 -1
- package/build/src/git/hooks.d.ts +0 -4
- package/build/src/git/hooks.js +0 -36
- package/build/src/git/integration.d.ts +7 -8
- package/build/src/git/integration.js +62 -9
- package/build/src/git/observe.d.ts +2 -1
- package/build/src/git/observe.js +6 -5
- package/build/src/git/process.d.ts +26 -0
- package/build/src/git/process.js +94 -0
- package/build/src/git/read-observation.d.ts +2 -1
- package/build/src/git/read-observation.js +3 -2
- package/build/src/git/reconcile.d.ts +8 -2
- package/build/src/git/reconcile.js +63 -14
- package/build/src/git/repository.d.ts +2 -29
- package/build/src/git/repository.js +4 -118
- package/build/src/git/scratch.d.ts +1 -1
- package/build/src/git/scratch.js +1 -1
- package/build/src/git/target-placement.d.ts +1 -1
- package/build/src/git/target-placement.js +9 -7
- package/build/src/git/tender.d.ts +20 -5
- package/build/src/git/tender.js +45 -13
- package/build/src/git/terminal-seal.d.ts +16 -2
- package/build/src/git/terminal-seal.js +15 -5
- package/build/src/git/workspace.d.ts +2 -1
- package/build/src/git/workspace.js +13 -5
- package/build/src/index.d.ts +1 -2
- package/build/src/index.js +1 -1
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +9 -1
- package/build/src/kanshi/read.js +91 -37
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/address.d.ts +5 -14
- package/build/src/library/address.js +27 -23
- package/build/src/library/akuma-creation.d.ts +4 -2
- package/build/src/library/akuma-creation.js +43 -26
- package/build/src/library/audit.d.ts +2 -1
- package/build/src/library/audit.js +1 -1
- package/build/src/library/bind.d.ts +2 -1
- package/build/src/library/bind.js +4 -4
- package/build/src/library/catalog.d.ts +1 -2
- package/build/src/library/catalog.js +11 -6
- package/build/src/library/configuration.d.ts +5 -1
- package/build/src/library/configuration.js +71 -18
- package/build/src/library/contract.d.ts +70 -3
- package/build/src/library/contract.js +213 -27
- package/build/src/library/delivery.d.ts +1 -1
- package/build/src/library/fleet.d.ts +70 -12
- package/build/src/library/fleet.js +236 -56
- package/build/src/library/input.d.ts +0 -1
- package/build/src/library/input.js +1 -5
- package/build/src/library/keiyaku.d.ts +4 -4
- package/build/src/library/keiyaku.js +1 -2
- package/build/src/library/mutation.d.ts +2 -1
- package/build/src/library/reconcile.d.ts +2 -1
- package/build/src/library/reconcile.js +3 -1
- package/build/src/library/region.d.ts +1 -1
- package/build/src/library/repo.d.ts +3 -1
- package/build/src/library/repo.js +8 -4
- package/build/src/protocol/abandon.d.ts +9 -0
- package/build/src/protocol/abandon.js +15 -0
- package/build/src/protocol/amend.d.ts +16 -0
- package/build/src/protocol/amend.js +77 -0
- package/build/src/protocol/arc.d.ts +6 -0
- package/build/src/protocol/arc.js +12 -0
- package/build/src/protocol/attempt.d.ts +2 -1
- package/build/src/protocol/audit.d.ts +53 -0
- package/build/src/protocol/audit.js +140 -0
- package/build/src/protocol/bind.d.ts +2 -3
- package/build/src/protocol/bind.js +2 -16
- package/build/src/protocol/completion.d.ts +32 -0
- package/build/src/protocol/completion.js +130 -0
- package/build/src/protocol/deliver.d.ts +37 -0
- package/build/src/protocol/deliver.js +160 -0
- package/build/src/protocol/intent.d.ts +1 -1
- package/build/src/protocol/intent.js +1 -1
- package/build/src/protocol/operations.d.ts +65 -198
- package/build/src/protocol/operations.js +21 -634
- package/build/src/protocol/placement.d.ts +4 -13
- package/build/src/protocol/placement.js +3 -15
- package/build/src/protocol/read/status.d.ts +4 -2
- package/build/src/protocol/read/status.js +27 -15
- package/build/src/protocol/reconcile.d.ts +35 -0
- package/build/src/protocol/reconcile.js +41 -0
- package/build/src/protocol/reintegrate.d.ts +31 -0
- package/build/src/protocol/reintegrate.js +74 -0
- package/build/src/protocol/review.d.ts +33 -0
- package/build/src/protocol/review.js +148 -0
- package/build/src/protocol/run.d.ts +1 -1
- package/build/src/runtime/proc/run.d.ts +1 -0
- package/build/src/runtime/proc/run.js +9 -2
- package/build/src/settlement/fence.d.ts +1 -1
- package/build/src/settlement/holder.d.ts +1 -1
- package/build/src/settlement/settle.d.ts +2 -1
- package/build/src/settlement/settle.js +4 -1
- package/build/src/task/board.d.ts +18 -4
- package/build/src/task/board.js +73 -29
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +11 -4
- package/build/src/task/index.d.ts +4 -4
- package/build/src/task/index.js +8 -131
- package/build/src/task/input.d.ts +18 -0
- package/build/src/task/input.js +189 -0
- package/build/src/task/mutation.d.ts +39 -0
- package/build/src/task/mutation.js +85 -0
- package/build/src/task/operations.d.ts +4 -19
- package/build/src/task/operations.js +64 -18
- package/build/src/task/query.d.ts +9 -2
- package/build/src/task/query.js +32 -64
- package/build/src/task/store.js +0 -2
- package/build/src/verification/execution.d.ts +1 -1
- package/build/src/verification/execution.js +2 -1
- package/build/src/workspace-place.d.ts +1 -4
- package/build/src/workspace-place.js +0 -15
- package/package.json +5 -3
package/build/src/body/decode.js
CHANGED
|
@@ -1,29 +1,12 @@
|
|
|
1
1
|
import { mintDocumentKey, mintDocumentSegmentKey } from "./keys.js";
|
|
2
|
-
import {
|
|
3
|
-
import { directChildren,
|
|
2
|
+
import { decodeDocumentEnvelope } from "./envelope.js";
|
|
3
|
+
import { directChildren, normalizeTitle, rawSlice, sectionContent, } from "../markdown/query.js";
|
|
4
4
|
import { CONTRACT_SECTIONS, RESERVED_SECTIONS } from "./shape.js";
|
|
5
5
|
import { decodeRegion, RegionDocumentError } from "./region.js";
|
|
6
6
|
import { decodeVerificationDeclarations, VerificationDocumentError } from "./verification.js";
|
|
7
7
|
function refusal(message) {
|
|
8
8
|
throw new TypeError(message);
|
|
9
9
|
}
|
|
10
|
-
function nonblankRaw(document, node) {
|
|
11
|
-
return rawSlice(document, node.span).trim().length > 0;
|
|
12
|
-
}
|
|
13
|
-
function topLevelSections(document) {
|
|
14
|
-
return indexedHeadings(indexDocument(document), { level: 2 })
|
|
15
|
-
.filter((node) => node.type === "section");
|
|
16
|
-
}
|
|
17
|
-
function indexedSections(document) {
|
|
18
|
-
const sections = new Map();
|
|
19
|
-
for (const section of topLevelSections(document)) {
|
|
20
|
-
const title = normalizeTitle(section.title);
|
|
21
|
-
if (sections.has(title))
|
|
22
|
-
refusal(`duplicate contract section '${section.title}'`);
|
|
23
|
-
sections.set(title, section);
|
|
24
|
-
}
|
|
25
|
-
return sections;
|
|
26
|
-
}
|
|
27
10
|
function requireSections(sections) {
|
|
28
11
|
for (const [name, spec] of Object.entries(CONTRACT_SECTIONS)) {
|
|
29
12
|
if (spec.required && !sections.has(name))
|
|
@@ -72,14 +55,6 @@ function criteria(document, section) {
|
|
|
72
55
|
return { title, body };
|
|
73
56
|
});
|
|
74
57
|
}
|
|
75
|
-
function rejectUnownedBytes(document, title) {
|
|
76
|
-
if (title.children.some((node) => nonblankRaw(document, node))) {
|
|
77
|
-
refusal("contract title may not contain content before the first H2 section");
|
|
78
|
-
}
|
|
79
|
-
const stray = document.children.filter((node) => node.type !== "section" && nonblankRaw(document, node));
|
|
80
|
-
if (stray.length > 0)
|
|
81
|
-
refusal("contract document contains content outside an H1 or H2 section");
|
|
82
|
-
}
|
|
83
58
|
function verification(document, section) {
|
|
84
59
|
try {
|
|
85
60
|
return decodeVerificationDeclarations(document, section);
|
|
@@ -91,22 +66,14 @@ function verification(document, section) {
|
|
|
91
66
|
}
|
|
92
67
|
}
|
|
93
68
|
export function decodeContractDocument(source) {
|
|
94
|
-
let
|
|
69
|
+
let envelope;
|
|
95
70
|
try {
|
|
96
|
-
|
|
71
|
+
envelope = decodeDocumentEnvelope(source, "contract");
|
|
97
72
|
}
|
|
98
73
|
catch (error) {
|
|
99
74
|
refusal(error instanceof Error ? error.message : String(error));
|
|
100
75
|
}
|
|
101
|
-
|
|
102
|
-
refusal("contract document may not contain frontmatter");
|
|
103
|
-
const titles = indexedHeadings(indexDocument(document), { level: 1 })
|
|
104
|
-
.filter((node) => node.type === "section");
|
|
105
|
-
if (titles.length !== 1)
|
|
106
|
-
refusal("contract document requires exactly one H1 title");
|
|
107
|
-
const title = titles[0];
|
|
108
|
-
rejectUnownedBytes(document, title);
|
|
109
|
-
const sections = indexedSections(document);
|
|
76
|
+
const { document, title, sections, sectionNodes } = envelope;
|
|
110
77
|
requireSections(sections);
|
|
111
78
|
for (const name of RESERVED_SECTIONS) {
|
|
112
79
|
if (sections.has(name))
|
|
@@ -131,7 +98,6 @@ export function decodeContractDocument(source) {
|
|
|
131
98
|
verification: verificationSection === undefined ? [] : verification(document, verificationSection),
|
|
132
99
|
extensions,
|
|
133
100
|
};
|
|
134
|
-
const sectionNodes = topLevelSections(document);
|
|
135
101
|
const segments = sectionNodes.map((section) => mintDocumentSegmentKey(document.source, section.span));
|
|
136
102
|
return {
|
|
137
103
|
...body,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DocumentNode, SectionNode } from "../markdown/types.js";
|
|
2
|
+
export declare function decodeDocumentEnvelope(source: string, kind: "arc" | "contract"): Readonly<{
|
|
3
|
+
document: DocumentNode;
|
|
4
|
+
title: SectionNode;
|
|
5
|
+
sections: ReadonlyMap<string, SectionNode>;
|
|
6
|
+
sectionNodes: readonly SectionNode[];
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { parseToAST } from "../markdown/parse.js";
|
|
2
|
+
import { indexDocument, indexedHeadings, normalizeTitle, rawSlice } from "../markdown/query.js";
|
|
3
|
+
function refusal(message) {
|
|
4
|
+
throw new TypeError(message);
|
|
5
|
+
}
|
|
6
|
+
function nonblankRaw(document, node) {
|
|
7
|
+
return rawSlice(document, node.span).trim().length > 0;
|
|
8
|
+
}
|
|
9
|
+
function topLevelSections(document) {
|
|
10
|
+
return indexedHeadings(indexDocument(document), { level: 2 })
|
|
11
|
+
.filter((node) => node.type === "section");
|
|
12
|
+
}
|
|
13
|
+
export function decodeDocumentEnvelope(source, kind) {
|
|
14
|
+
const document = parseToAST(source);
|
|
15
|
+
if (document.frontmatter !== undefined)
|
|
16
|
+
refusal(`${kind} document may not contain frontmatter`);
|
|
17
|
+
const titles = indexedHeadings(indexDocument(document), { level: 1 })
|
|
18
|
+
.filter((node) => node.type === "section");
|
|
19
|
+
if (titles.length !== 1)
|
|
20
|
+
refusal(`${kind} document requires exactly one H1 title`);
|
|
21
|
+
const title = titles[0];
|
|
22
|
+
if (title.children.some((node) => nonblankRaw(document, node))) {
|
|
23
|
+
refusal(`${kind} title may not contain content before the first H2 section`);
|
|
24
|
+
}
|
|
25
|
+
if (document.children.some((node) => node.type !== "section" && nonblankRaw(document, node))) {
|
|
26
|
+
refusal(`${kind} document contains content outside an H1 or H2 section`);
|
|
27
|
+
}
|
|
28
|
+
const sectionNodes = topLevelSections(document);
|
|
29
|
+
const sections = new Map();
|
|
30
|
+
for (const section of sectionNodes) {
|
|
31
|
+
const name = normalizeTitle(section.title);
|
|
32
|
+
if (sections.has(name))
|
|
33
|
+
refusal(`duplicate ${kind} section '${section.title}'`);
|
|
34
|
+
sections.set(name, section);
|
|
35
|
+
}
|
|
36
|
+
return { document, title, sections, sectionNodes };
|
|
37
|
+
}
|
|
@@ -5,7 +5,10 @@ type MutationCallOptions = Readonly<{
|
|
|
5
5
|
coordinate?: ContractId;
|
|
6
6
|
projectRefusal?: (refusal: unknown) => unknown;
|
|
7
7
|
}>;
|
|
8
|
-
export declare function acceptedBind(result: BindResult,
|
|
8
|
+
export declare function acceptedBind(result: BindResult, coordinates: Readonly<{
|
|
9
|
+
workspace: "worktree" | "here";
|
|
10
|
+
target?: string;
|
|
11
|
+
}>): AcceptedBindResult;
|
|
9
12
|
export declare function acceptedAmend(result: AmendResult, coordinate: ContractId): AcceptedAmendResult;
|
|
10
13
|
export declare function acceptedDeliver(result: MutationResult<Delivery>, coordinate: ContractId): AcceptedDeliverResult;
|
|
11
14
|
export declare function acceptedReview(result: MutationResult<Review>, coordinate: ContractId): AcceptedReviewResult;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { KeiyakuRefused, KeiyakuRetry, } from "../index.js";
|
|
2
2
|
function acceptedFacts(result) {
|
|
3
|
-
return result.facts.map((fact) =>
|
|
4
|
-
contract: fact.contract,
|
|
5
|
-
entry: fact.entry,
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
return result.facts.map((fact) => fact.kind === "reintegrated"
|
|
4
|
+
? { contract: fact.contract, entry: fact.entry, kind: fact.kind, data: fact.data }
|
|
5
|
+
: { contract: fact.contract, entry: fact.entry, kind: fact.kind });
|
|
6
|
+
}
|
|
7
|
+
function attestationFor(facts, gate) {
|
|
8
|
+
return facts.findLast((fact) => fact.kind === "attestation" && fact.data.gate === gate);
|
|
8
9
|
}
|
|
9
10
|
function acceptedEnvelope(result, coordinate) {
|
|
10
11
|
const contract = coordinate ?? result.facts[0]?.contract;
|
|
@@ -26,11 +27,12 @@ function acceptedRegion(result) {
|
|
|
26
27
|
return { overlapFailure: result.overlapFailure };
|
|
27
28
|
return { overlaps: result.overlaps };
|
|
28
29
|
}
|
|
29
|
-
export function acceptedBind(result,
|
|
30
|
+
export function acceptedBind(result, coordinates) {
|
|
30
31
|
return {
|
|
31
32
|
...acceptedEnvelope(result, undefined),
|
|
32
33
|
verb: "bind",
|
|
33
|
-
|
|
34
|
+
workspace: coordinates.workspace,
|
|
35
|
+
target: coordinates.target ?? null,
|
|
34
36
|
...acceptedRegion(result),
|
|
35
37
|
};
|
|
36
38
|
}
|
|
@@ -44,9 +46,12 @@ export function acceptedAmend(result, coordinate) {
|
|
|
44
46
|
}
|
|
45
47
|
export function acceptedDeliver(result, coordinate) {
|
|
46
48
|
const value = result.value;
|
|
49
|
+
const attestation = attestationFor(result.facts, "verified");
|
|
50
|
+
const verificationVerdict = attestation?.data.verdict ?? value.verificationReuse?.verdict;
|
|
47
51
|
return {
|
|
48
52
|
...acceptedEnvelope(result, coordinate),
|
|
49
53
|
verb: "deliver",
|
|
54
|
+
...(verificationVerdict === undefined ? {} : { verificationVerdict }),
|
|
50
55
|
...(value.verification === undefined ? {} : { verification: value.verification }),
|
|
51
56
|
...(value.verificationReuse === undefined ? {} : { verificationReuse: value.verificationReuse }),
|
|
52
57
|
...(value.placement === undefined ? {} : { placement: value.placement }),
|
|
@@ -56,18 +61,43 @@ export function acceptedDeliver(result, coordinate) {
|
|
|
56
61
|
}
|
|
57
62
|
export function acceptedReview(result, coordinate) {
|
|
58
63
|
const value = result.value;
|
|
64
|
+
const reviewAttestation = attestationFor(result.facts, "reviewed");
|
|
65
|
+
if (reviewAttestation === undefined)
|
|
66
|
+
throw new Error("accepted review is missing its attestation fact");
|
|
67
|
+
const verificationAttestation = attestationFor(result.facts, "verified");
|
|
68
|
+
const verificationVerdict = verificationAttestation?.data.verdict ?? value.verificationReuse?.verdict;
|
|
59
69
|
return {
|
|
60
70
|
...acceptedEnvelope(result, coordinate),
|
|
61
71
|
verb: "review",
|
|
72
|
+
verdict: reviewAttestation.data.verdict,
|
|
73
|
+
...(verificationVerdict === undefined ? {} : { verificationVerdict }),
|
|
74
|
+
...(value.verification === undefined ? {} : { verification: value.verification }),
|
|
75
|
+
...(value.verificationReuse === undefined ? {} : { verificationReuse: value.verificationReuse }),
|
|
62
76
|
...(value.placement === undefined ? {} : { placement: value.placement }),
|
|
63
77
|
...(value.workspace === undefined ? {} : { workspace: value.workspace }),
|
|
78
|
+
...(value.cleanup === undefined ? {} : { cleanup: value.cleanup }),
|
|
79
|
+
...(value.leak === undefined ? {} : { leak: value.leak }),
|
|
64
80
|
};
|
|
65
81
|
}
|
|
66
82
|
export function acceptedArc(result, coordinate) {
|
|
67
|
-
|
|
83
|
+
const arc = result.facts.find((fact) => fact.kind === "arc");
|
|
84
|
+
if (arc === undefined)
|
|
85
|
+
throw new Error("accepted arc is missing its arc fact");
|
|
86
|
+
return {
|
|
87
|
+
...acceptedEnvelope(result, coordinate),
|
|
88
|
+
verb: "arc",
|
|
89
|
+
chapter: { seq: arc.data.seq, title: arc.data.title },
|
|
90
|
+
};
|
|
68
91
|
}
|
|
69
92
|
export function acceptedAbandon(result, coordinate) {
|
|
70
|
-
|
|
93
|
+
const abandoned = result.facts.find((fact) => fact.kind === "abandoned");
|
|
94
|
+
if (abandoned === undefined)
|
|
95
|
+
throw new Error("accepted abandon is missing its abandoned fact");
|
|
96
|
+
return {
|
|
97
|
+
...acceptedEnvelope(result, coordinate),
|
|
98
|
+
verb: "abandon",
|
|
99
|
+
...(abandoned.data.note === undefined ? {} : { note: abandoned.data.note }),
|
|
100
|
+
};
|
|
71
101
|
}
|
|
72
102
|
export function acceptedAudit(result, coordinate) {
|
|
73
103
|
return {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type AkuId, type ActivityHistory } from "../../akuma/index.js";
|
|
2
|
-
import { Keiyaku, type AkumaKillResult, type AkumaHistoryResult, type
|
|
2
|
+
import { Keiyaku, type AkumaKillResult, type AkumaHistoryResult, type AkumaObservation, type AkumaTellResult, type AkumaWaitResult, type CallResult, type ForkResult, type Keiyaku as KeiyakuContract, type Repo } from "../../index.js";
|
|
3
3
|
import type { Settings } from "../../settings.js";
|
|
4
4
|
import type { WorldRoot } from "../../world.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { InvokedAkumaCommand } from "./akuma.js";
|
|
6
6
|
export type AkumaInvocationResult = Readonly<{
|
|
7
7
|
kind: "akuma";
|
|
8
8
|
action: "call";
|
|
@@ -11,7 +11,7 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
11
11
|
}> | Readonly<{
|
|
12
12
|
kind: "akuma";
|
|
13
13
|
action: "status";
|
|
14
|
-
status:
|
|
14
|
+
status: AkumaObservation;
|
|
15
15
|
alias?: string;
|
|
16
16
|
}> | Readonly<{
|
|
17
17
|
kind: "akuma";
|
|
@@ -67,12 +67,13 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
67
67
|
}>;
|
|
68
68
|
type InvokeInput = Readonly<{
|
|
69
69
|
path: WorldRoot;
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
statedCwd?: string;
|
|
71
|
+
home?: string;
|
|
72
|
+
settings?: Settings;
|
|
72
73
|
contract?: KeiyakuContract;
|
|
73
74
|
repo?: Repo;
|
|
74
75
|
readStdin(): Promise<string>;
|
|
75
76
|
}>;
|
|
76
|
-
export declare function invokeAkuma(command:
|
|
77
|
-
export declare function invokeAkumaStatus(path: WorldRoot, akuma: string,
|
|
77
|
+
export declare function invokeAkuma(command: InvokedAkumaCommand, input: InvokeInput): Promise<AkumaInvocationResult>;
|
|
78
|
+
export declare function invokeAkumaStatus(path: WorldRoot, akuma: string, alias?: string, repo?: Repo): Promise<AkumaInvocationResult>;
|
|
78
79
|
export {};
|
|
@@ -13,7 +13,6 @@ async function invokeWait(command, input) {
|
|
|
13
13
|
result: await Keiyaku.wait({
|
|
14
14
|
path: input.path,
|
|
15
15
|
akuma: command.akuma,
|
|
16
|
-
settings: input.settings,
|
|
17
16
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
18
17
|
...(command.completion === undefined ? {} : { completion: command.completion }),
|
|
19
18
|
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
@@ -24,11 +23,21 @@ async function invokeWait(command, input) {
|
|
|
24
23
|
async function invokeTell(command, input) {
|
|
25
24
|
const body = await promptBody(command, input);
|
|
26
25
|
if (command.interrupt) {
|
|
27
|
-
const result = await Keiyaku.interrupt({
|
|
26
|
+
const result = await Keiyaku.interrupt({
|
|
27
|
+
path: input.path,
|
|
28
|
+
akuma: command.akuma,
|
|
29
|
+
body,
|
|
30
|
+
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
31
|
+
});
|
|
28
32
|
const alias = inputAlias(command.akuma);
|
|
29
33
|
return { kind: "akuma", action: "tell", mode: "interrupt", result, body, ...(alias === undefined ? {} : { alias }) };
|
|
30
34
|
}
|
|
31
|
-
const result = await Keiyaku.tell({
|
|
35
|
+
const result = await Keiyaku.tell({
|
|
36
|
+
path: input.path,
|
|
37
|
+
akuma: command.akuma,
|
|
38
|
+
body,
|
|
39
|
+
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
40
|
+
});
|
|
32
41
|
const alias = inputAlias(command.akuma);
|
|
33
42
|
return { kind: "akuma", action: "tell", mode: "ordinary", result, body, ...(alias === undefined ? {} : { alias }) };
|
|
34
43
|
}
|
|
@@ -36,7 +45,6 @@ async function invokeHistory(command, input) {
|
|
|
36
45
|
const result = await Keiyaku.history({
|
|
37
46
|
path: input.path,
|
|
38
47
|
akuma: command.akuma,
|
|
39
|
-
settings: input.settings,
|
|
40
48
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
41
49
|
...(command.before === undefined ? {} : { before: command.before }),
|
|
42
50
|
...(command.since === undefined ? {} : { since: command.since }),
|
|
@@ -64,7 +72,6 @@ async function invokeFork(command, input) {
|
|
|
64
72
|
path: input.path,
|
|
65
73
|
akuma: command.akuma,
|
|
66
74
|
at: command.at,
|
|
67
|
-
settings: input.settings,
|
|
68
75
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
69
76
|
}),
|
|
70
77
|
};
|
|
@@ -77,7 +84,6 @@ async function invokeKill(command, input) {
|
|
|
77
84
|
result: await Keiyaku.kill({
|
|
78
85
|
path: input.path,
|
|
79
86
|
akuma: command.akuma,
|
|
80
|
-
settings: input.settings,
|
|
81
87
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
82
88
|
}),
|
|
83
89
|
...(alias === undefined ? {} : { alias }),
|
|
@@ -91,12 +97,14 @@ export async function invokeAkuma(command, input) {
|
|
|
91
97
|
path: input.path,
|
|
92
98
|
archetype: command.archetype,
|
|
93
99
|
body,
|
|
94
|
-
|
|
95
|
-
...(input.
|
|
100
|
+
...(input.home === undefined ? {} : { home: input.home }),
|
|
101
|
+
...(input.settings === undefined ? {} : { settings: input.settings }),
|
|
102
|
+
...(input.statedCwd === undefined ? {} : { cwd: input.statedCwd }),
|
|
96
103
|
mode: command.mode,
|
|
97
104
|
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
98
105
|
...(input.contract === undefined ? {} : { contract: input.contract }),
|
|
99
106
|
...(command.alias === undefined ? {} : { alias: command.alias }),
|
|
107
|
+
...(command.allowed === undefined ? {} : { allowed: command.allowed }),
|
|
100
108
|
});
|
|
101
109
|
return { kind: "akuma", action: "call", result, world: input.path };
|
|
102
110
|
}
|
|
@@ -107,11 +115,11 @@ export async function invokeAkuma(command, input) {
|
|
|
107
115
|
case "kill": return await invokeKill(command, input);
|
|
108
116
|
}
|
|
109
117
|
}
|
|
110
|
-
export async function invokeAkumaStatus(path, akuma,
|
|
118
|
+
export async function invokeAkumaStatus(path, akuma, alias, repo) {
|
|
111
119
|
return {
|
|
112
120
|
kind: "akuma",
|
|
113
121
|
action: "status",
|
|
114
|
-
status: await Keiyaku.status({ path, akuma,
|
|
122
|
+
status: await Keiyaku.status({ path, akuma, ...(repo === undefined ? {} : { repo }) }),
|
|
115
123
|
...(alias === undefined ? {} : { alias }),
|
|
116
124
|
};
|
|
117
125
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AkumaAlias } from "../../identity/selector.js";
|
|
2
|
+
import { type AllowedActions } from "../../akuma/allowed.js";
|
|
2
3
|
type Output = Readonly<{
|
|
3
4
|
output: "text" | "json";
|
|
4
5
|
}>;
|
|
@@ -21,6 +22,7 @@ export type ParsedAkumaCommand = Output & ((Readonly<{
|
|
|
21
22
|
alias?: AkumaAlias;
|
|
22
23
|
mode: "wait" | "detach";
|
|
23
24
|
timeoutMs?: number;
|
|
25
|
+
allowed?: AllowedActions;
|
|
24
26
|
}> & Prompted) | Readonly<{
|
|
25
27
|
command: "kill";
|
|
26
28
|
akuma: readonly string[];
|
|
@@ -38,15 +40,22 @@ export type ParsedAkumaCommand = Output & ((Readonly<{
|
|
|
38
40
|
before?: number;
|
|
39
41
|
since?: number;
|
|
40
42
|
limit?: number;
|
|
41
|
-
}> & Addressed) |
|
|
43
|
+
}> & Addressed) | Readonly<{
|
|
44
|
+
command: "history";
|
|
45
|
+
contract: string;
|
|
46
|
+
}> | (Readonly<{
|
|
42
47
|
command: "fork";
|
|
43
48
|
at: string;
|
|
44
49
|
}> & Addressed));
|
|
50
|
+
export type InvokedAkumaCommand = Exclude<ParsedAkumaCommand, {
|
|
51
|
+
command: "history";
|
|
52
|
+
contract: string;
|
|
53
|
+
}>;
|
|
45
54
|
export type AkumaAction = ParsedAkumaCommand["command"];
|
|
46
55
|
export declare function isAkumaAction(value: string | undefined): value is AkumaAction;
|
|
47
56
|
export declare function isParsedAkumaCommand(command: Readonly<{
|
|
48
57
|
command: string;
|
|
49
|
-
}>): command is
|
|
58
|
+
}>): command is InvokedAkumaCommand;
|
|
50
59
|
export declare function renderAkumaRootRows(): readonly string[];
|
|
51
60
|
export declare function renderAkumaHelp(action: AkumaAction): string;
|
|
52
61
|
export declare function renderAkumaUsage(action: AkumaAction): string;
|
|
@@ -2,6 +2,7 @@ import { CliUsageError, isBlankInput, usageLine, withJsonAutomationHelp } from "
|
|
|
2
2
|
import { archetypeName, parseAkuId } from "../../akuma/identity.js";
|
|
3
3
|
import { parseDuration as decodeDuration } from "../../duration.js";
|
|
4
4
|
import { parseAkumaAlias, parseAkumaGlob } from "../../identity/selector.js";
|
|
5
|
+
import { decodeAllowedActions } from "../../akuma/allowed.js";
|
|
5
6
|
const AKUMA_COMMAND_SPECS = {
|
|
6
7
|
call: {
|
|
7
8
|
arity: 1,
|
|
@@ -11,15 +12,17 @@ const AKUMA_COMMAND_SPECS = {
|
|
|
11
12
|
alias: "value",
|
|
12
13
|
wait: "value",
|
|
13
14
|
detach: "boolean",
|
|
15
|
+
allowed: "repeatable",
|
|
14
16
|
json: "boolean",
|
|
15
17
|
},
|
|
16
|
-
usage: "call <akuma-name> [--contract <kei/...>] [--alias @name] [--wait <duration> | -d | --detach] [--json] (<prompt> | -)",
|
|
18
|
+
usage: "call <akuma-name> [--contract <kei/...>] [--alias @name] [--allowed <product.action>]... [--wait <duration> | -d | --detach] [--json] (<prompt> | -)",
|
|
17
19
|
purpose: "Birth an Akuma from <akuma-name> with one prompt.",
|
|
18
20
|
details: [
|
|
19
21
|
"Give <prompt> as one argument, or use final - to read stdin.",
|
|
20
22
|
"Default: --wait 5m. An explicit --wait replaces that duration; -d and --detach return after birth.",
|
|
21
23
|
"--contract dispatches the born Akuma to that Contract.",
|
|
22
24
|
"--alias assigns the world-local @name selector to the born Akuma.",
|
|
25
|
+
"Repeated --allowed replaces the Archetype list; --allowed none selects an empty list.",
|
|
23
26
|
"With --contract, Dispatch succeeds first. If @name exists, the alias then moves.",
|
|
24
27
|
].join("\n"),
|
|
25
28
|
},
|
|
@@ -45,8 +48,8 @@ const AKUMA_COMMAND_SPECS = {
|
|
|
45
48
|
arity: 1,
|
|
46
49
|
stdin: false,
|
|
47
50
|
flags: { before: "value", since: "value", limit: "value", last: "boolean", json: "boolean" },
|
|
48
|
-
usage: "history <aku/...> [--before <index> | --since <index>] [--limit <count>] [--last] [--json]",
|
|
49
|
-
purpose: "Read
|
|
51
|
+
usage: "history <aku/...|@alias|kei/...> [--before <index> | --since <index>] [--limit <count>] [--last] [--json]",
|
|
52
|
+
purpose: "Read Akuma execution history or one complete Contract journal and Dispatch timeline.",
|
|
50
53
|
},
|
|
51
54
|
fork: {
|
|
52
55
|
arity: 1,
|
|
@@ -67,7 +70,7 @@ export function isAkumaAction(value) {
|
|
|
67
70
|
return value !== undefined && Object.hasOwn(AKUMA_COMMAND_SPECS, value);
|
|
68
71
|
}
|
|
69
72
|
export function isParsedAkumaCommand(command) {
|
|
70
|
-
return isAkumaAction(command.command);
|
|
73
|
+
return isAkumaAction(command.command) && !("contract" in command && command.command === "history");
|
|
71
74
|
}
|
|
72
75
|
export function renderAkumaRootRows() {
|
|
73
76
|
return Object.values(AKUMA_COMMAND_SPECS).flatMap((spec) => [` ${spec.usage}`, ` ${spec.purpose}`]);
|
|
@@ -80,11 +83,11 @@ export function renderAkumaUsage(action) {
|
|
|
80
83
|
return usageLine(AKUMA_COMMAND_SPECS[action].usage);
|
|
81
84
|
}
|
|
82
85
|
export function parseAkumaCatalogPath(value) {
|
|
83
|
-
if (value === "aku/")
|
|
86
|
+
if (value === "aku" || value === "aku/")
|
|
84
87
|
return { kind: "archetypes" };
|
|
85
88
|
if (value === "aku/*/*")
|
|
86
89
|
return { kind: "akuma" };
|
|
87
|
-
const match = /^aku\/(
|
|
90
|
+
const match = /^aku\/([^/]+)\/?$/u.exec(value);
|
|
88
91
|
if (match === null)
|
|
89
92
|
return null;
|
|
90
93
|
return { kind: "akuma", archetype: archetypeName(match[1]) };
|
|
@@ -104,6 +107,29 @@ function parseDuration(raw, option, fail) {
|
|
|
104
107
|
fail(`${option} duration exceeds the safe millisecond range`);
|
|
105
108
|
return duration.milliseconds;
|
|
106
109
|
}
|
|
110
|
+
function scanNamedOption(input, flags, fail) {
|
|
111
|
+
const token = input.argv[input.index];
|
|
112
|
+
const name = token.slice(2);
|
|
113
|
+
const kind = input.spec.flags[name];
|
|
114
|
+
if (kind === undefined)
|
|
115
|
+
fail(`option ${token} is not valid for ${input.action}`);
|
|
116
|
+
if (kind !== "repeatable" && flags[name] !== undefined)
|
|
117
|
+
fail(`duplicate option: ${token}`);
|
|
118
|
+
if (kind === "boolean") {
|
|
119
|
+
flags[name] = true;
|
|
120
|
+
return input.index;
|
|
121
|
+
}
|
|
122
|
+
const value = input.argv[input.index + 1];
|
|
123
|
+
if (value === undefined || value === "-" || value === "-d" || value.startsWith("--")) {
|
|
124
|
+
fail(`${token} requires a value`);
|
|
125
|
+
}
|
|
126
|
+
if (isBlankInput(value))
|
|
127
|
+
fail(`${token} requires a nonblank value`);
|
|
128
|
+
flags[name] = kind === "repeatable"
|
|
129
|
+
? [...(Array.isArray(flags[name]) ? flags[name] : []), value]
|
|
130
|
+
: value;
|
|
131
|
+
return input.index + 1;
|
|
132
|
+
}
|
|
107
133
|
function scanAkuma(action, argv, fail) {
|
|
108
134
|
const spec = AKUMA_COMMAND_SPECS[action];
|
|
109
135
|
const flags = {};
|
|
@@ -129,24 +155,7 @@ function scanAkuma(action, argv, fail) {
|
|
|
129
155
|
positionals.push(token);
|
|
130
156
|
}
|
|
131
157
|
else {
|
|
132
|
-
|
|
133
|
-
const kind = spec.flags[name];
|
|
134
|
-
if (kind === undefined)
|
|
135
|
-
fail(`option ${token} is not valid for ${action}`);
|
|
136
|
-
if (flags[name] !== undefined)
|
|
137
|
-
fail(`duplicate option: ${token}`);
|
|
138
|
-
if (kind === "boolean")
|
|
139
|
-
flags[name] = true;
|
|
140
|
-
else {
|
|
141
|
-
const value = argv[index + 1];
|
|
142
|
-
if (value === undefined || value === "-" || value === "-d" || value.startsWith("--")) {
|
|
143
|
-
fail(`${token} requires a value`);
|
|
144
|
-
}
|
|
145
|
-
if (isBlankInput(value))
|
|
146
|
-
fail(`${token} requires a nonblank value`);
|
|
147
|
-
flags[name] = value;
|
|
148
|
-
index += 1;
|
|
149
|
-
}
|
|
158
|
+
index = scanNamedOption({ action, spec, argv, index }, flags, fail);
|
|
150
159
|
}
|
|
151
160
|
}
|
|
152
161
|
return { flags, positionals, stdin };
|
|
@@ -200,7 +209,13 @@ function parseWait(rawSelectors, flags, output, fail) {
|
|
|
200
209
|
output,
|
|
201
210
|
};
|
|
202
211
|
}
|
|
203
|
-
function parseHistory(
|
|
212
|
+
function parseHistory(selector, flags, output, fail) {
|
|
213
|
+
if (selector.startsWith("kei/")) {
|
|
214
|
+
if (flags.before !== undefined || flags.since !== undefined || flags.limit !== undefined || flags.last === true) {
|
|
215
|
+
fail("history kei/... does not accept --before, --since, --limit, or --last");
|
|
216
|
+
}
|
|
217
|
+
return { command: "history", contract: selector, output };
|
|
218
|
+
}
|
|
204
219
|
if (flags.before !== undefined && flags.since !== undefined)
|
|
205
220
|
fail("history --before and --since are mutually exclusive");
|
|
206
221
|
if (flags.last === true && (flags.before !== undefined || flags.since !== undefined || flags.limit !== undefined)) {
|
|
@@ -211,7 +226,7 @@ function parseHistory(akuma, flags, output, fail) {
|
|
|
211
226
|
fail("--limit must be no greater than 5000");
|
|
212
227
|
return {
|
|
213
228
|
command: "history",
|
|
214
|
-
akuma,
|
|
229
|
+
akuma: validateDirect(selector, fail),
|
|
215
230
|
last: flags.last === true,
|
|
216
231
|
...(flags.before === undefined ? {} : { before: positiveIndex(flags.before, "--before", fail) }),
|
|
217
232
|
...(flags.since === undefined ? {} : { since: positiveIndex(flags.since, "--since", fail) }),
|
|
@@ -224,9 +239,13 @@ function parseAddressed(action, rawSelectors, flags, output, fail) {
|
|
|
224
239
|
return { command: action, akuma: rawSelectors.map((value) => validateSet(value, fail)), output };
|
|
225
240
|
if (action === "wait")
|
|
226
241
|
return parseWait(rawSelectors, flags, output, fail);
|
|
242
|
+
if (action === "history") {
|
|
243
|
+
const selector = rawSelectors[0];
|
|
244
|
+
if (selector.includes("*"))
|
|
245
|
+
fail("history accepts one complete aku/..., @alias, or kei/... selector");
|
|
246
|
+
return parseHistory(selector, flags, output, fail);
|
|
247
|
+
}
|
|
227
248
|
const akuma = validateDirect(rawSelectors[0], fail);
|
|
228
|
-
if (action === "history")
|
|
229
|
-
return parseHistory(akuma, flags, output, fail);
|
|
230
249
|
const at = stringFlag(flags.at, "fork requires --at <historyId>", fail);
|
|
231
250
|
return { command: action, akuma, at, output };
|
|
232
251
|
}
|
|
@@ -246,6 +265,24 @@ function parsePrompted(action, positionals, stdin, fail) {
|
|
|
246
265
|
function parseTell(flags, subject, prompt, output, fail) {
|
|
247
266
|
return { command: "tell", akuma: validateDirect(subject, fail), interrupt: flags.interrupt === true, prompt, output };
|
|
248
267
|
}
|
|
268
|
+
function parseAllowedFlag(raw, fail) {
|
|
269
|
+
if (raw === undefined)
|
|
270
|
+
return undefined;
|
|
271
|
+
if (!Array.isArray(raw))
|
|
272
|
+
fail("--allowed requires a value");
|
|
273
|
+
const selected = raw;
|
|
274
|
+
if (selected.includes("none")) {
|
|
275
|
+
if (selected.length !== 1)
|
|
276
|
+
fail("--allowed none cannot be combined with another value");
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
return decodeAllowedActions(selected, "--allowed");
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
fail(error instanceof Error ? error.message : "invalid --allowed action");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
249
286
|
function parseCall(flags, archetype, prompt, output, fail) {
|
|
250
287
|
let alias;
|
|
251
288
|
if (flags.alias !== undefined) {
|
|
@@ -260,6 +297,7 @@ function parseCall(flags, archetype, prompt, output, fail) {
|
|
|
260
297
|
fail("call --wait and --detach are mutually exclusive");
|
|
261
298
|
const mode = flags.detach === true ? "detach" : "wait";
|
|
262
299
|
const timeoutMs = flags.wait === undefined ? undefined : parseDuration(flags.wait, "--wait", fail);
|
|
300
|
+
const allowed = parseAllowedFlag(flags.allowed, fail);
|
|
263
301
|
return {
|
|
264
302
|
command: "call",
|
|
265
303
|
archetype,
|
|
@@ -267,6 +305,7 @@ function parseCall(flags, archetype, prompt, output, fail) {
|
|
|
267
305
|
...(alias === undefined ? {} : { alias }),
|
|
268
306
|
mode,
|
|
269
307
|
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
308
|
+
...(allowed === undefined ? {} : { allowed }),
|
|
270
309
|
prompt,
|
|
271
310
|
output,
|
|
272
311
|
};
|
|
@@ -4,7 +4,7 @@ export function amendFromCommand({ command, repo, contract, markdown, gates, act
|
|
|
4
4
|
? []
|
|
5
5
|
: command.after?.map((id) => contractFromInput(repo, id).id);
|
|
6
6
|
return contract.amend({
|
|
7
|
-
markdown,
|
|
7
|
+
...(markdown === undefined ? {} : { markdown }),
|
|
8
8
|
...(actor === undefined ? {} : { actor }),
|
|
9
9
|
...(hooks === undefined ? {} : { hooks }),
|
|
10
10
|
...(after === undefined ? {} : { after }),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ContractFlagKind = "boolean" | "value" | "repeat-value";
|
|
1
|
+
export type ContractFlagKind = "boolean" | "value" | "raw-value" | "repeat-value";
|
|
2
2
|
export type ContractCommandSpec = Readonly<{
|
|
3
3
|
positional: "none" | "optional";
|
|
4
4
|
stdin: "none" | "optional" | "required";
|
|
@@ -17,24 +17,24 @@ export declare const CONTRACT_COMMAND_SPECS: {
|
|
|
17
17
|
readonly target: "value";
|
|
18
18
|
readonly here: "boolean";
|
|
19
19
|
readonly after: "repeat-value";
|
|
20
|
-
readonly gates: "value";
|
|
20
|
+
readonly gates: "raw-value";
|
|
21
21
|
readonly json: "boolean";
|
|
22
22
|
};
|
|
23
|
-
readonly usage: "bind [--task <task/...>] [--target <ref>] [--here] [--after <kei/...> ...] [--gates <name
|
|
23
|
+
readonly usage: "bind [--task <task/...>] [--target <ref>] [--here] [--after <kei/...> ...] [--gates <name,...>] [--actor <actor>] [--json] -";
|
|
24
24
|
readonly purpose: "Create one Contract from stdin Markdown.";
|
|
25
25
|
};
|
|
26
26
|
readonly amend: {
|
|
27
27
|
readonly positional: "optional";
|
|
28
|
-
readonly stdin: "
|
|
28
|
+
readonly stdin: "optional";
|
|
29
29
|
readonly flags: {
|
|
30
30
|
readonly actor: "value";
|
|
31
31
|
readonly after: "repeat-value";
|
|
32
32
|
readonly "clear-after": "boolean";
|
|
33
|
-
readonly gates: "value";
|
|
33
|
+
readonly gates: "raw-value";
|
|
34
34
|
readonly json: "boolean";
|
|
35
35
|
};
|
|
36
|
-
readonly usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name
|
|
37
|
-
readonly purpose: "
|
|
36
|
+
readonly usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name,...>] [--actor <actor>] [--json] [-]";
|
|
37
|
+
readonly purpose: "Amend one Contract's document operations or structured terms.";
|
|
38
38
|
};
|
|
39
39
|
readonly deliver: {
|
|
40
40
|
readonly positional: "optional";
|
|
@@ -106,7 +106,7 @@ export declare const CONTRACT_COMMAND_SPECS: {
|
|
|
106
106
|
readonly flags: {
|
|
107
107
|
readonly json: "boolean";
|
|
108
108
|
};
|
|
109
|
-
readonly usage: "ls task/ [--json]\n keiyaku ls kei/ [--json]\n keiyaku ls aku/ [--json]\n keiyaku ls aku/<akuma
|
|
109
|
+
readonly usage: "ls task[/] [--json]\n keiyaku ls kei[/] [--json]\n keiyaku ls aku[/] [--json]\n keiyaku ls aku/<akuma>[/] [--json]\n keiyaku ls \"aku/*/*\" [--json]";
|
|
110
110
|
readonly purpose: "List one identity directory.";
|
|
111
111
|
};
|
|
112
112
|
readonly audit: {
|