@astrosheep/keiyaku 4.5.20 → 4.5.21
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 +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +22 -8
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +237 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +6 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +2 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
- package/build/src/akuma/akuma-handle.d.ts +5 -1
- package/build/src/akuma/akuma-handle.js +4 -1
- package/build/src/akuma/akuma-instance.d.ts +7 -2
- package/build/src/akuma/akuma-instance.js +14 -7
- package/build/src/akuma/akuma-observe.d.ts +11 -0
- package/build/src/akuma/akuma-observe.js +22 -0
- package/build/src/akuma/akuma-product.d.ts +1 -0
- package/build/src/akuma/akuma-product.js +3 -0
- package/build/src/akuma/akuma.d.ts +1 -0
- package/build/src/akuma/body.d.ts +25 -5
- package/build/src/akuma/body.js +65 -8
- package/build/src/akuma/call-request.d.ts +2 -0
- package/build/src/akuma/call-request.js +2 -0
- package/build/src/akuma/fleet-execution.d.ts +28 -0
- package/build/src/akuma/fleet-execution.js +36 -4
- package/build/src/akuma/fleet-request.d.ts +10 -0
- package/build/src/akuma/fleet-request.js +11 -2
- package/build/src/akuma/heart/facts.d.ts +2 -0
- package/build/src/akuma/heart/index.d.ts +1 -0
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/rows.d.ts +2 -0
- package/build/src/akuma/heart/rows.js +7 -5
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +3 -1
- package/build/src/akuma/heart/tells.js +6 -5
- package/build/src/akuma/heart/timeline.js +1 -1
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +1 -1
- package/build/src/akuma/providers/acp/core.js +3 -6
- package/build/src/akuma/providers/claude/index.js +9 -12
- package/build/src/akuma/providers/codex-app-server/index.js +4 -11
- package/build/src/akuma/providers/execution-environment.d.ts +6 -0
- package/build/src/akuma/providers/execution-environment.js +24 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +30 -23
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +8 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +6 -5
- package/build/src/akuma/providers/pi/events.js +7 -2
- package/build/src/akuma/providers/pi/index.js +3 -2
- package/build/src/akuma/request-rendezvous.js +8 -3
- package/build/src/akuma/turn-drive.d.ts +1 -0
- package/build/src/akuma/turn-drive.js +2 -0
- package/build/src/akuma-body.js +2 -0
- package/build/src/body/amend.js +6 -4
- package/build/src/body/decode.d.ts +3 -1
- package/build/src/body/decode.js +53 -17
- package/build/src/body/region.d.ts +9 -1
- package/build/src/body/region.js +87 -12
- package/build/src/body/render.js +1 -1
- package/build/src/body/verification.d.ts +3 -1
- package/build/src/body/verification.js +4 -1
- package/build/src/cli/accepted.js +19 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
- package/build/src/cli/commands/akuma-invoke.js +133 -13
- package/build/src/cli/commands/akuma.js +11 -4
- package/build/src/cli/commands/contract-help.js +17 -4
- package/build/src/cli/commands/contract.js +6 -4
- package/build/src/cli/commands/status-set.js +15 -24
- package/build/src/cli/main.js +5 -0
- package/build/src/cli/parse.d.ts +2 -0
- package/build/src/cli/parse.js +5 -0
- package/build/src/cli/render/akuma-activity.d.ts +99 -2
- package/build/src/cli/render/akuma-activity.js +484 -40
- package/build/src/cli/render/akuma.d.ts +10 -0
- package/build/src/cli/render/akuma.js +28 -21
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/board.js +1 -1
- package/build/src/cli/render/catalog.js +16 -13
- package/build/src/cli/render/contract-history.js +39 -10
- package/build/src/cli/render/contract-observation.js +10 -6
- package/build/src/cli/render/contract.js +109 -106
- package/build/src/cli/render/execution-progress.d.ts +23 -1
- package/build/src/cli/render/execution-progress.js +151 -28
- package/build/src/cli/render/kanshi-akuma.js +27 -39
- package/build/src/cli/render/kanshi.js +33 -26
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/render/receipt.d.ts +1 -1
- package/build/src/cli/render/receipt.js +5 -5
- package/build/src/cli/render/refusal.js +10 -7
- package/build/src/cli/render/region.js +1 -1
- package/build/src/cli/render/settings.js +12 -2
- package/build/src/cli/render/status-line.d.ts +30 -0
- package/build/src/cli/render/status-line.js +58 -0
- package/build/src/cli/render/status-set.js +1 -1
- package/build/src/cli/render/task.d.ts +2 -0
- package/build/src/cli/render/task.js +11 -7
- package/build/src/cli/render/terminal.d.ts +0 -1
- package/build/src/cli/render/terminal.js +47 -15
- package/build/src/cli/result.d.ts +1 -0
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +13 -7
- package/build/src/cli/usage.js +2 -2
- package/build/src/cli/version.d.ts +1 -0
- package/build/src/cli/version.js +25 -0
- package/build/src/git/workspace.d.ts +1 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/identity/mint.d.ts +13 -0
- package/build/src/identity/mint.js +26 -0
- package/build/src/identity/normalize.d.ts +4 -0
- package/build/src/identity/normalize.js +30 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/kanshi/read.js +17 -4
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/akuma-creation.d.ts +2 -0
- package/build/src/library/akuma-creation.js +33 -17
- package/build/src/library/bind.js +18 -16
- package/build/src/library/contract-bind.d.ts +3 -1
- package/build/src/library/contract-bind.js +5 -3
- package/build/src/library/contract-operations.d.ts +2 -2
- package/build/src/library/contract-operations.js +1 -1
- package/build/src/library/contract-types.d.ts +1 -0
- package/build/src/library/fleet.d.ts +4 -1
- package/build/src/library/fleet.js +32 -8
- package/build/src/plugin/akuma-signals.d.ts +6 -0
- package/build/src/plugin/akuma-signals.js +8 -0
- package/build/src/plugin/public.d.ts +4 -0
- package/build/src/plugin/runtime.js +4 -1
- package/build/src/protocol/amend.js +4 -3
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/bind.js +41 -14
- package/build/src/protocol/completion.d.ts +3 -0
- package/build/src/protocol/completion.js +7 -1
- package/build/src/protocol/deliver.js +165 -92
- package/build/src/protocol/execution-observation.d.ts +0 -4
- package/build/src/protocol/intent.d.ts +15 -20
- package/build/src/protocol/intent.js +29 -17
- package/build/src/protocol/operations.d.ts +2 -0
- package/build/src/protocol/placement.js +5 -1
- package/build/src/protocol/read/status.d.ts +1 -0
- package/build/src/protocol/read/status.js +10 -2
- package/build/src/protocol/reintegrate.d.ts +1 -1
- package/build/src/protocol/reintegrate.js +70 -43
- package/build/src/protocol/result-codec.js +9 -7
- package/build/src/protocol/review.js +53 -30
- package/build/src/protocol/run.d.ts +83 -36
- package/build/src/protocol/run.js +90 -75
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settings.js +5 -14
- package/build/src/task/document.d.ts +5 -1
- package/build/src/task/document.js +6 -1
- package/build/src/verification/execution.d.ts +0 -1
- package/build/src/verification/execution.js +0 -24
- package/build/src/verification/observation.d.ts +0 -4
- package/build/src/verification/observation.js +1 -2
- package/package.json +3 -1
- package/build/src/git/verification-environment.d.ts +0 -10
- package/build/src/git/verification-environment.js +0 -281
package/build/src/body/region.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { directChildren, rawSlice } from "../markdown/query.js";
|
|
2
1
|
export class RegionDocumentError extends Error {
|
|
3
2
|
constructor(message) {
|
|
4
3
|
super(message);
|
|
@@ -8,9 +7,6 @@ export class RegionDocumentError extends Error {
|
|
|
8
7
|
function refusal(message) {
|
|
9
8
|
throw new RegionDocumentError(message);
|
|
10
9
|
}
|
|
11
|
-
function nonblank(document, node) {
|
|
12
|
-
return rawSlice(document, node.span).trim().length > 0;
|
|
13
|
-
}
|
|
14
10
|
function compileSegment(segment, pattern) {
|
|
15
11
|
if (segment === "**")
|
|
16
12
|
return { kind: "deep" };
|
|
@@ -113,15 +109,94 @@ function patternsOverlap(left, right) {
|
|
|
113
109
|
}
|
|
114
110
|
return false;
|
|
115
111
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
const THEMATIC_BREAK = /^ {0,3}(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/u;
|
|
113
|
+
const TABLE_DELIMITER = /^ {0,3}\|?[ \t]*:?-+:?[ \t]*(?:\|[ \t]*:?-+:?[ \t]*)*\|?[ \t]*$/u;
|
|
114
|
+
function nonblank(line) {
|
|
115
|
+
return line.trim().length > 0;
|
|
116
|
+
}
|
|
117
|
+
/** The AST has no table, thematic-break, or HTML block kind, so the Region boundary classifies that prose itself. */
|
|
118
|
+
function foreignProseKind(lines) {
|
|
119
|
+
for (const line of lines) {
|
|
120
|
+
if (THEMATIC_BREAK.test(line))
|
|
121
|
+
return "thematic break";
|
|
122
|
+
if (/^ {0,3}</u.test(line))
|
|
123
|
+
return "HTML";
|
|
124
|
+
}
|
|
125
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
126
|
+
if (lines[index - 1].includes("|") && TABLE_DELIMITER.test(lines[index]))
|
|
127
|
+
return "table";
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
function nodeKind(node) {
|
|
132
|
+
return node.type.replaceAll("_", " ");
|
|
133
|
+
}
|
|
134
|
+
function article(kind) {
|
|
135
|
+
return kind === "HTML" || /^[aeiou]/iu.test(kind) ? "an" : "a";
|
|
136
|
+
}
|
|
137
|
+
function itemLines(item) {
|
|
138
|
+
const lines = [];
|
|
139
|
+
for (const child of item.children) {
|
|
140
|
+
if (child.type === "text")
|
|
141
|
+
lines.push(...child.lines);
|
|
142
|
+
else if (child.type === "list")
|
|
143
|
+
for (const nested of child.items)
|
|
144
|
+
lines.push(...itemLines(nested));
|
|
120
145
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
return lines.filter(nonblank);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Structural refusals are separate from pattern compilation so a caller may aggregate every independent failure.
|
|
150
|
+
* The three authoring forms — fenced lines, list items, and bare paragraph lines — union freely. Blank lines never
|
|
151
|
+
* count, and an info string beyond the exact `txt` still implies executable content that belongs to Verification.
|
|
152
|
+
*/
|
|
153
|
+
export function regionStructure(section) {
|
|
154
|
+
for (const node of section.children) {
|
|
155
|
+
if (node.type === "code_block") {
|
|
156
|
+
if (!node.closed)
|
|
157
|
+
return "Region fence must be closed";
|
|
158
|
+
if (node.info !== "" && node.info !== "txt") {
|
|
159
|
+
return "Region fence may not carry an info string other than the exact 'txt'";
|
|
160
|
+
}
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (node.type === "list")
|
|
164
|
+
continue;
|
|
165
|
+
if (node.type === "text") {
|
|
166
|
+
const foreign = foreignProseKind(node.lines);
|
|
167
|
+
if (foreign !== null)
|
|
168
|
+
return `Region may not contain ${article(foreign)} ${foreign} block`;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const kind = nodeKind(node);
|
|
172
|
+
return `Region may not contain ${article(kind)} ${kind} block`;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
function regionPatterns(section) {
|
|
177
|
+
const patterns = [];
|
|
178
|
+
for (const node of section.children) {
|
|
179
|
+
if (node.type === "code_block")
|
|
180
|
+
patterns.push(...node.lines.slice(1, -1).filter(nonblank));
|
|
181
|
+
else if (node.type === "list")
|
|
182
|
+
for (const item of node.items)
|
|
183
|
+
patterns.push(...itemLines(item));
|
|
184
|
+
else if (node.type === "text")
|
|
185
|
+
patterns.push(...node.lines.filter(nonblank));
|
|
186
|
+
}
|
|
187
|
+
return patterns;
|
|
188
|
+
}
|
|
189
|
+
/** A whitespace-bearing pattern is almost certainly strayed prose; bind warns and proceeds rather than rejecting. */
|
|
190
|
+
export function regionWarnings(patterns) {
|
|
191
|
+
return patterns
|
|
192
|
+
.filter((pattern) => /\s/u.test(pattern))
|
|
193
|
+
.map((pattern) => `Region pattern '${pattern}' contains whitespace and will never match a path`);
|
|
194
|
+
}
|
|
195
|
+
export function decodeRegion(_document, section) {
|
|
196
|
+
const structural = regionStructure(section);
|
|
197
|
+
if (structural !== null)
|
|
198
|
+
refusal(structural);
|
|
199
|
+
const patterns = regionPatterns(section);
|
|
125
200
|
if (patterns.length === 0)
|
|
126
201
|
refusal("Region must declare at least one path pattern");
|
|
127
202
|
return patterns.map((pattern) => compileRegionPattern(pattern).source);
|
package/build/src/body/render.js
CHANGED
|
@@ -47,7 +47,7 @@ export function renderContractBody(body, currentArc) {
|
|
|
47
47
|
section(CONTRACT_SECTIONS.context.title, body.context),
|
|
48
48
|
section(CONTRACT_SECTIONS.objective.title, body.objective),
|
|
49
49
|
section(CONTRACT_SECTIONS.design.title, body.design),
|
|
50
|
-
section(CONTRACT_SECTIONS.region.title,
|
|
50
|
+
section(CONTRACT_SECTIONS.region.title, body.region.join("\n")),
|
|
51
51
|
section(CONTRACT_SECTIONS.criteria.title, criteria),
|
|
52
52
|
...(verification.length === 0 ? [] : [section(CONTRACT_SECTIONS.verification.title, verification)]),
|
|
53
53
|
...body.extensions.map((extension) => section(extension.title, extension.content)),
|
|
@@ -4,4 +4,6 @@ export type { VerificationDeclaration, VerificationExecutor } from "../verificat
|
|
|
4
4
|
export declare class VerificationDocumentError extends Error {
|
|
5
5
|
constructor(message: string);
|
|
6
6
|
}
|
|
7
|
-
export declare function decodeVerificationDeclarations(document: DocumentNode, section: SectionNode
|
|
7
|
+
export declare function decodeVerificationDeclarations(document: DocumentNode, section: SectionNode, options?: Readonly<{
|
|
8
|
+
requireTimeout?: boolean;
|
|
9
|
+
}>): readonly VerificationDeclaration[];
|
|
@@ -6,7 +6,7 @@ export class VerificationDocumentError extends Error {
|
|
|
6
6
|
this.name = "VerificationDocumentError";
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
export function decodeVerificationDeclarations(document, section) {
|
|
9
|
+
export function decodeVerificationDeclarations(document, section, options = {}) {
|
|
10
10
|
const blocks = directChildren(section, "code_block");
|
|
11
11
|
if (blocks.length === 0)
|
|
12
12
|
throw new VerificationDocumentError("Verification must contain one or more fenced executor declarations");
|
|
@@ -31,6 +31,9 @@ export function decodeVerificationDeclarations(document, section) {
|
|
|
31
31
|
if (duration?.kind === "parsed" && duration.milliseconds === 0) {
|
|
32
32
|
throw new VerificationDocumentError("Verification timeout must be positive");
|
|
33
33
|
}
|
|
34
|
+
if (options.requireTimeout === true && duration === undefined) {
|
|
35
|
+
throw new VerificationDocumentError("Verification declarations must specify timeout=<duration>");
|
|
36
|
+
}
|
|
34
37
|
return {
|
|
35
38
|
executor: info[1],
|
|
36
39
|
script,
|
|
@@ -24,6 +24,20 @@ function acceptedEnvelope(result, coordinate) {
|
|
|
24
24
|
...(result.executionStops.length === 0 ? {} : { executionStops: result.executionStops }),
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The completed placement's movement identity — the reference it advanced and the head it advanced from — is part
|
|
29
|
+
* of the public accepted shape, so a receipt states the movement without rebuilding it from facts or folded state.
|
|
30
|
+
*/
|
|
31
|
+
function acceptedCompletion(completion) {
|
|
32
|
+
if (completion === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
return {
|
|
35
|
+
integration: completion.integration,
|
|
36
|
+
...(completion.predecessor === undefined ? {} : { predecessor: completion.predecessor }),
|
|
37
|
+
...(completion.target === undefined ? {} : { target: completion.target }),
|
|
38
|
+
...(completion.verification === undefined ? {} : { verification: completion.verification }),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
27
41
|
function acceptedRegion(result) {
|
|
28
42
|
if (result.overlapFailure !== undefined)
|
|
29
43
|
return { overlapFailure: result.overlapFailure };
|
|
@@ -42,6 +56,7 @@ export function acceptedBind(result, coordinates) {
|
|
|
42
56
|
verb: "bind",
|
|
43
57
|
...(result.workspace === undefined ? {} : { workspace: result.workspace }),
|
|
44
58
|
target: coordinates.target ?? null,
|
|
59
|
+
...(result.warnings === undefined ? {} : { warnings: result.warnings }),
|
|
45
60
|
...acceptedRegion(result),
|
|
46
61
|
};
|
|
47
62
|
}
|
|
@@ -56,6 +71,7 @@ export function acceptedAmend(result, coordinate) {
|
|
|
56
71
|
export function acceptedDeliver(result, coordinate) {
|
|
57
72
|
const value = result.value;
|
|
58
73
|
const attestation = attestationFor(result.facts, "verified", coordinate);
|
|
74
|
+
const completion = acceptedCompletion(value.completion);
|
|
59
75
|
const verificationVerdict = value.completion?.verification?.verdict ?? attestation?.data.verdict ?? value.verificationReuse?.verdict;
|
|
60
76
|
return {
|
|
61
77
|
...acceptedEnvelope(result, coordinate),
|
|
@@ -63,7 +79,7 @@ export function acceptedDeliver(result, coordinate) {
|
|
|
63
79
|
tenderSnapshot: value.tenderSnapshot,
|
|
64
80
|
integration: { changeId: value.integration.changeId },
|
|
65
81
|
...(value.leading === undefined ? {} : { leading: value.leading }),
|
|
66
|
-
...(
|
|
82
|
+
...(completion === undefined ? {} : { completion }),
|
|
67
83
|
...(verificationVerdict === undefined ? {} : { verificationVerdict }),
|
|
68
84
|
...(value.verification === undefined ? {} : { verification: value.verification }),
|
|
69
85
|
...(value.verificationReuse === undefined ? {} : { verificationReuse: value.verificationReuse }),
|
|
@@ -78,6 +94,7 @@ export function acceptedReview(result, coordinate) {
|
|
|
78
94
|
if (reviewAttestation === undefined)
|
|
79
95
|
throw new Error("accepted review is missing its attestation fact");
|
|
80
96
|
const verificationAttestation = attestationFor(result.facts, "verified", coordinate);
|
|
97
|
+
const completion = acceptedCompletion(value.completion);
|
|
81
98
|
const verificationVerdict = value.completion?.verification?.verdict ??
|
|
82
99
|
verificationAttestation?.data.verdict ??
|
|
83
100
|
value.verificationReuse?.verdict;
|
|
@@ -85,7 +102,7 @@ export function acceptedReview(result, coordinate) {
|
|
|
85
102
|
...acceptedEnvelope(result, coordinate),
|
|
86
103
|
verb: "review",
|
|
87
104
|
verdict: reviewAttestation.data.verdict,
|
|
88
|
-
...(
|
|
105
|
+
...(completion === undefined ? {} : { completion }),
|
|
89
106
|
...(verificationVerdict === undefined ? {} : { verificationVerdict }),
|
|
90
107
|
...(value.verification === undefined ? {} : { verification: value.verification }),
|
|
91
108
|
...(value.verificationReuse === undefined ? {} : { verificationReuse: value.verificationReuse }),
|
|
@@ -11,6 +11,7 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
11
11
|
result: CallResult;
|
|
12
12
|
world: WorldRoot;
|
|
13
13
|
schemaAnswer?: unknown;
|
|
14
|
+
streamed?: boolean;
|
|
14
15
|
}> | Readonly<{
|
|
15
16
|
kind: "akuma";
|
|
16
17
|
action: "status";
|
|
@@ -21,6 +22,7 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
21
22
|
action: "wait";
|
|
22
23
|
result: AkumaWaitResult;
|
|
23
24
|
alias?: string;
|
|
25
|
+
streamed?: boolean;
|
|
24
26
|
}> | Readonly<{
|
|
25
27
|
kind: "akuma";
|
|
26
28
|
action: "tell";
|
|
@@ -1,11 +1,65 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
2
|
+
import { squareAssignedParticipantName } from "@astrosheep/square";
|
|
3
|
+
import { emitInitiatingPluginSignal } from "../../plugin/akuma-signals.js";
|
|
4
|
+
import { observeAkumaStatus } from "../../akuma/akuma-observe.js";
|
|
5
|
+
import { AuthorityCorruptionError, Keiyaku, } from "../../index.js";
|
|
6
|
+
import { callObservationStream, waitObservationStream } from "../render/akuma-activity.js";
|
|
7
|
+
import { callObservationHead } from "../render/akuma.js";
|
|
3
8
|
import { killAkuma, tellAkuma, waitAkuma } from "../../library/fleet.js";
|
|
4
9
|
import { localExecutionContext } from "../../akuma/requests.js";
|
|
5
10
|
import { Akuma, Schema } from "../../akuma/index.js";
|
|
6
11
|
import { addressAkuma } from "../../library/address.js";
|
|
7
12
|
import { executionChannel } from "../../akuma/requests.js";
|
|
8
13
|
import { requestForwardedFleetTellAnswer } from "../../akuma/fleet-request.js";
|
|
14
|
+
/** The window a call observes for when the caller gives no `--wait` duration. */
|
|
15
|
+
const CALL_TIMEOUT_MS = 300_000;
|
|
16
|
+
function integrationFailure(error) {
|
|
17
|
+
return {
|
|
18
|
+
kind: error instanceof AuthorityCorruptionError ? "authority-corruption" : "infrastructure",
|
|
19
|
+
diagnostic: error instanceof Error ? error.message : String(error),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** The display context the command result renders with, so live progress rows match the result. */
|
|
23
|
+
function resultContext() {
|
|
24
|
+
const tty = process.stderr.isTTY === true;
|
|
25
|
+
return {
|
|
26
|
+
columns: tty && Number.isInteger(process.stderr.columns) ? process.stderr.columns : 80,
|
|
27
|
+
color: tty && process.env.NO_COLOR === undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function writeProgress(body) {
|
|
31
|
+
process.stderr.write(body.endsWith("\n") ? body : `${body}\n`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The live half of an observe-mode call: the resolved birth opens one identity
|
|
35
|
+
* frame (never the detached receipt's cwd row), each later observation prints
|
|
36
|
+
* the settled rows that arrived since the previous one, and the return appends
|
|
37
|
+
* one conclusion. The stream is append-only, so no final snapshot replays.
|
|
38
|
+
*/
|
|
39
|
+
async function observeCallUntilComplete(command, input, born) {
|
|
40
|
+
const stream = callObservationStream(resultContext(), callObservationHead(born));
|
|
41
|
+
try {
|
|
42
|
+
const status = await observeAkumaStatus(input.path, born.akuma, {
|
|
43
|
+
timeoutMs: command.timeoutMs ?? CALL_TIMEOUT_MS,
|
|
44
|
+
observe: (observed) => {
|
|
45
|
+
const lines = stream.observe(observed);
|
|
46
|
+
if (lines.length > 0)
|
|
47
|
+
writeProgress(lines.join("\n"));
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
const conclusion = stream.conclude({ kind: "observed", status });
|
|
51
|
+
if (conclusion.length > 0)
|
|
52
|
+
writeProgress(conclusion);
|
|
53
|
+
return { kind: "observed", status };
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const failure = integrationFailure(error);
|
|
57
|
+
const conclusion = stream.conclude({ kind: "failed", failure });
|
|
58
|
+
if (conclusion.length > 0)
|
|
59
|
+
writeProgress(conclusion);
|
|
60
|
+
return { kind: "failed", failure };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
9
63
|
async function schemaFromFile(path) {
|
|
10
64
|
try {
|
|
11
65
|
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
@@ -21,21 +75,73 @@ function inputAlias(selector) {
|
|
|
21
75
|
async function promptBody(command, input) {
|
|
22
76
|
return command.prompt.kind === "stdin" ? await input.readStdin() : command.prompt.value;
|
|
23
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* The live half of a local wait: each observation round opens every newly seen
|
|
80
|
+
* Akuma with its identity frame, then prints only the rows that settled since
|
|
81
|
+
* the previous round. The first sighting of an Akuma only establishes its
|
|
82
|
+
* baseline, so an already settled Akuma prints no backlog rows. When the wait
|
|
83
|
+
* ends, `conclude` prints its closing scoreboard on the same channel.
|
|
84
|
+
*/
|
|
85
|
+
function waitObserver(stream) {
|
|
86
|
+
return {
|
|
87
|
+
selected: (selected) => stream.select(selected),
|
|
88
|
+
observe: (observed) => {
|
|
89
|
+
const lines = stream.observe(observed);
|
|
90
|
+
if (lines.length > 0)
|
|
91
|
+
writeProgress(lines.join("\n"));
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
24
95
|
async function invokeWait(command, input) {
|
|
25
96
|
const alias = command.akuma.length === 1 ? inputAlias(command.akuma[0]) : undefined;
|
|
97
|
+
const stream = command.output === "text" ? waitObservationStream(resultContext()) : undefined;
|
|
98
|
+
const result = await waitAkuma({
|
|
99
|
+
path: input.path,
|
|
100
|
+
akuma: command.akuma,
|
|
101
|
+
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
102
|
+
...(command.completion === undefined ? {} : { completion: command.completion }),
|
|
103
|
+
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
104
|
+
}, input.execution ?? localExecutionContext(), stream === undefined ? undefined : waitObserver(stream));
|
|
105
|
+
if (stream !== undefined && stream.streamed()) {
|
|
106
|
+
const closing = stream.conclude(result);
|
|
107
|
+
if (closing.length > 0)
|
|
108
|
+
writeProgress(closing);
|
|
109
|
+
return {
|
|
110
|
+
kind: "akuma",
|
|
111
|
+
action: "wait",
|
|
112
|
+
result,
|
|
113
|
+
streamed: true,
|
|
114
|
+
...(alias === undefined ? {} : { alias }),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
26
117
|
return {
|
|
27
118
|
kind: "akuma",
|
|
28
119
|
action: "wait",
|
|
29
|
-
result
|
|
30
|
-
path: input.path,
|
|
31
|
-
akuma: command.akuma,
|
|
32
|
-
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
33
|
-
...(command.completion === undefined ? {} : { completion: command.completion }),
|
|
34
|
-
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
35
|
-
}, input.execution ?? localExecutionContext()),
|
|
120
|
+
result,
|
|
36
121
|
...(alias === undefined ? {} : { alias }),
|
|
37
122
|
};
|
|
38
123
|
}
|
|
124
|
+
async function inputInitiator(input) {
|
|
125
|
+
let initiator;
|
|
126
|
+
try {
|
|
127
|
+
initiator = squareAssignedParticipantName(input.environment);
|
|
128
|
+
}
|
|
129
|
+
catch { }
|
|
130
|
+
if (initiator === undefined)
|
|
131
|
+
return {};
|
|
132
|
+
try {
|
|
133
|
+
await emitInitiatingPluginSignal({
|
|
134
|
+
world: input.path,
|
|
135
|
+
...(input.settings === undefined ? {} : { settings: input.settings }),
|
|
136
|
+
initiator,
|
|
137
|
+
reportDiagnostic: (message) => process.stderr.write(`${message}\n`),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
process.stderr.write(`! plugin initiation: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
142
|
+
}
|
|
143
|
+
return { initiator };
|
|
144
|
+
}
|
|
39
145
|
async function invokeTell(command, input) {
|
|
40
146
|
const body = await promptBody(command, input);
|
|
41
147
|
if (command.schema !== undefined) {
|
|
@@ -45,6 +151,7 @@ async function invokeTell(command, input) {
|
|
|
45
151
|
akuma: command.akuma,
|
|
46
152
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
47
153
|
});
|
|
154
|
+
const initiator = await inputInitiator(input);
|
|
48
155
|
const channel = executionChannel(input.execution);
|
|
49
156
|
const answer = channel.kind === "body-request"
|
|
50
157
|
? await requestForwardedFleetTellAnswer({
|
|
@@ -53,9 +160,11 @@ async function invokeTell(command, input) {
|
|
|
53
160
|
body,
|
|
54
161
|
schema,
|
|
55
162
|
interrupt: command.interrupt,
|
|
163
|
+
...initiator,
|
|
56
164
|
})
|
|
57
165
|
: await Akuma.select(addressed.path, addressed.id).tell(body, {
|
|
58
166
|
schema,
|
|
167
|
+
...initiator,
|
|
59
168
|
...(command.interrupt ? { interrupt: true } : {}),
|
|
60
169
|
});
|
|
61
170
|
const alias = inputAlias(command.akuma);
|
|
@@ -68,8 +177,10 @@ async function invokeTell(command, input) {
|
|
|
68
177
|
...(alias === undefined ? {} : { alias }),
|
|
69
178
|
};
|
|
70
179
|
}
|
|
180
|
+
const initiator = await inputInitiator(input);
|
|
71
181
|
if (command.interrupt) {
|
|
72
182
|
const result = await Keiyaku.interrupt({
|
|
183
|
+
...initiator,
|
|
73
184
|
path: input.path,
|
|
74
185
|
akuma: command.akuma,
|
|
75
186
|
body,
|
|
@@ -86,6 +197,7 @@ async function invokeTell(command, input) {
|
|
|
86
197
|
};
|
|
87
198
|
}
|
|
88
199
|
const result = await tellAkuma({
|
|
200
|
+
...initiator,
|
|
89
201
|
path: input.path,
|
|
90
202
|
akuma: command.akuma,
|
|
91
203
|
body,
|
|
@@ -151,24 +263,32 @@ export async function invokeAkuma(command, input) {
|
|
|
151
263
|
const body = await promptBody(command, input);
|
|
152
264
|
const schema = command.schema === undefined ? undefined : await schemaFromFile(command.schema);
|
|
153
265
|
const caller = input.execution === undefined ? Keiyaku : Keiyaku.withExecution({ execution: input.execution });
|
|
154
|
-
const
|
|
266
|
+
const request = {
|
|
267
|
+
...(await inputInitiator(input)),
|
|
155
268
|
path: input.path,
|
|
156
269
|
archetype: command.archetype,
|
|
157
270
|
body,
|
|
158
271
|
...(input.home === undefined ? {} : { home: input.home }),
|
|
159
272
|
...(input.settings === undefined ? {} : { settings: input.settings }),
|
|
160
273
|
...(input.executionCwd === undefined ? {} : { cwd: input.executionCwd }),
|
|
161
|
-
mode: command.mode,
|
|
162
|
-
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
163
274
|
...(input.contract === undefined ? {} : { contract: input.contract }),
|
|
164
275
|
...(command.alias === undefined ? {} : { alias: command.alias }),
|
|
165
276
|
...(command.allowed === undefined ? {} : { allowed: command.allowed }),
|
|
166
277
|
...(schema === undefined ? {} : { schema }),
|
|
167
|
-
}
|
|
278
|
+
};
|
|
279
|
+
const observing = schema === undefined && command.mode === "wait" && command.output === "text";
|
|
280
|
+
const born = await caller.call(observing
|
|
281
|
+
? { ...request, mode: "detach" }
|
|
282
|
+
: {
|
|
283
|
+
...request,
|
|
284
|
+
mode: command.mode,
|
|
285
|
+
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
286
|
+
});
|
|
287
|
+
const result = observing ? { ...born, observation: await observeCallUntilComplete(command, input, born) } : born;
|
|
168
288
|
if (schema !== undefined && command.mode === "wait" && result.schemaAnswer !== undefined) {
|
|
169
289
|
return { kind: "akuma", action: "call", result, world: input.path, schemaAnswer: result.schemaAnswer };
|
|
170
290
|
}
|
|
171
|
-
return { kind: "akuma", action: "call", result, world: input.path };
|
|
291
|
+
return { kind: "akuma", action: "call", result, world: input.path, ...(observing ? { streamed: true } : {}) };
|
|
172
292
|
}
|
|
173
293
|
case "wait":
|
|
174
294
|
return await invokeWait(command, input);
|
|
@@ -32,6 +32,7 @@ const AKUMA_COMMAND_SPECS = {
|
|
|
32
32
|
"A nested birth is clipped to its direct parent's frozen actions. status <aku/...|@alias> shows the born effective set.",
|
|
33
33
|
"--schema reads a JSON Schema file for the answer contract; stdin remains the prompt source.",
|
|
34
34
|
"With --contract, Dispatch succeeds first. If @name exists, the alias then moves.",
|
|
35
|
+
"While it waits, settled timeline rows stream on stderr; the final answer is written to stdout once.",
|
|
35
36
|
].join("\n"),
|
|
36
37
|
},
|
|
37
38
|
wait: {
|
|
@@ -39,7 +40,16 @@ const AKUMA_COMMAND_SPECS = {
|
|
|
39
40
|
stdin: false,
|
|
40
41
|
flags: { any: "boolean", all: "boolean", timeout: "value", json: "boolean" },
|
|
41
42
|
usage: "wait <akuma-selector>... [--any | --all] [--timeout <duration>]",
|
|
42
|
-
purpose: "Wait for one Akuma or
|
|
43
|
+
purpose: "Wait for one Akuma or a selected Akuma set.",
|
|
44
|
+
details: [
|
|
45
|
+
"Without --any or --all the mode is any: the wait returns when any selected Akuma completes.",
|
|
46
|
+
"--all waits until every selected Akuma completes.",
|
|
47
|
+
"An already completed member counts immediately, so repeating a selection can return at once.",
|
|
48
|
+
"Identity frames, settled rows, and the closing scoreboard stream on stderr.",
|
|
49
|
+
"A streamed plural wait leaves stdout empty, and so does a single wait with no answer.",
|
|
50
|
+
"Only a single selected Akuma that answered writes to stdout, exactly its answer.",
|
|
51
|
+
"With --json nothing streams and stdout carries the result document.",
|
|
52
|
+
].join("\n"),
|
|
43
53
|
},
|
|
44
54
|
tell: {
|
|
45
55
|
arity: 1,
|
|
@@ -199,9 +209,6 @@ function validateSet(value, fail) {
|
|
|
199
209
|
function parseWait(rawSelectors, flags, output, fail) {
|
|
200
210
|
if (flags.any === true && flags.all === true)
|
|
201
211
|
fail("wait --any and --all are mutually exclusive");
|
|
202
|
-
if (rawSelectors.length > 1 && flags.any !== true && flags.all !== true) {
|
|
203
|
-
fail("wait requires --any or --all when selecting multiple Akuma");
|
|
204
|
-
}
|
|
205
212
|
const completion = flags.any === true ? "any" : flags.all === true ? "all" : undefined;
|
|
206
213
|
return {
|
|
207
214
|
command: "wait",
|
|
@@ -15,18 +15,26 @@ export const CONTRACT_COMMAND_SPECS = {
|
|
|
15
15
|
usage: "bind [--task <task/...>] [--target <ref>] [--after <kei/...> ...] [--gates <name,...>] [--actor <actor>] - | bind --fork-of <kei/...> [--target <ref>] [--actor <actor>]",
|
|
16
16
|
purpose: "Create one Contract from stdin Markdown or a sibling fork.",
|
|
17
17
|
details: [
|
|
18
|
+
"--gates <name,...> accepts gate words and configured bundle names together.",
|
|
19
|
+
"A matching bundle expands; otherwise the name is a literal gate. Duplicates",
|
|
20
|
+
"are removed in first-seen order. Gate words match ^[a-z][a-z0-9-]{0,63}$.",
|
|
21
|
+
"Omitting --gates selects gates.default, or reviewed when no default exists.",
|
|
22
|
+
'--gates "" explicitly binds without gates; --gates reviewed needs no bundle.',
|
|
23
|
+
"",
|
|
18
24
|
"stdin is Contract Markdown:",
|
|
19
25
|
" # <title>",
|
|
20
26
|
" ## Context motivation, authority, baseline, and boundaries",
|
|
21
27
|
" ## Objective one observable end state",
|
|
22
28
|
" ## Design closed decisions and ordering",
|
|
23
|
-
" ## Region
|
|
29
|
+
" ## Region intended path patterns as fenced lines, list items, or bare lines",
|
|
24
30
|
" ## Criteria one or more ### <criterion> entries",
|
|
25
31
|
" ## Verification optional fenced executor declarations",
|
|
26
32
|
"",
|
|
27
|
-
"Region
|
|
28
|
-
"repository-relative path pattern on
|
|
29
|
-
"is directory shorthand for 'path/**'.",
|
|
33
|
+
"Region accepts intended path patterns as fenced lines, list items, or bare",
|
|
34
|
+
"lines; the three forms union. Put one repository-relative path pattern on",
|
|
35
|
+
"each nonblank line. A trailing '/' is directory shorthand for 'path/**'.",
|
|
36
|
+
"A pattern containing whitespace binds with a warning. A fence carries no",
|
|
37
|
+
"info string or exactly 'txt'.",
|
|
30
38
|
"",
|
|
31
39
|
"Verification uses one or more closed bash, zsh, or pwsh fences. Its fence",
|
|
32
40
|
"may add timeout=<integer><ms|s|m|h>; the section contains no other prose.",
|
|
@@ -40,6 +48,11 @@ export const CONTRACT_COMMAND_SPECS = {
|
|
|
40
48
|
usage: "amend [<contract>|@<contract>] [--after <kei/...> ... | --clear-after] [--gates <name,...>] [--actor <actor>] [-]",
|
|
41
49
|
purpose: "Amend one Contract's document operations or structured terms.",
|
|
42
50
|
details: [
|
|
51
|
+
"--gates <name,...> replaces gates using gate words and configured bundle names.",
|
|
52
|
+
"A matching bundle expands; otherwise the name is a literal gate. Duplicates",
|
|
53
|
+
"are removed in first-seen order. Gate words match ^[a-z][a-z0-9-]{0,63}$.",
|
|
54
|
+
'Omitting --gates leaves gates unchanged; --gates "" clears them.',
|
|
55
|
+
"",
|
|
43
56
|
" ## Context|Objective|Design|Region|Criteria|Verification|<extension> (replace, or add new extension)",
|
|
44
57
|
" ## Replace: Context|Objective|Design|Region|Criteria|Verification|<extension>",
|
|
45
58
|
" ## Append: Context|Objective|Design|Criteria|<extension>",
|
|
@@ -20,13 +20,15 @@ function optionalFlag(flags, name) {
|
|
|
20
20
|
function refuse(command, message) {
|
|
21
21
|
throw new CliUsageError(message, commandGuide(command, CONTRACT_COMMAND_SPECS[command].usage));
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function parseGateNames(parts, command) {
|
|
24
24
|
const value = optionalFlag(parts.flags, "gates");
|
|
25
25
|
if (value === undefined)
|
|
26
26
|
return undefined;
|
|
27
|
+
if (value === "")
|
|
28
|
+
return [];
|
|
27
29
|
const names = value.split(",");
|
|
28
30
|
if (names.some((name) => name.length === 0)) {
|
|
29
|
-
refuse(command,
|
|
31
|
+
refuse(command, '--gates requires comma-separated names or "" to clear gates');
|
|
30
32
|
}
|
|
31
33
|
return names;
|
|
32
34
|
}
|
|
@@ -53,7 +55,7 @@ function parseBind(parts) {
|
|
|
53
55
|
const task = optionalFlag(parts.flags, "task");
|
|
54
56
|
const target = optionalFlag(parts.flags, "target");
|
|
55
57
|
const after = parts.flags.after === undefined ? [] : Array.isArray(parts.flags.after) ? parts.flags.after : [parts.flags.after];
|
|
56
|
-
const gates =
|
|
58
|
+
const gates = parseGateNames(parts, "bind");
|
|
57
59
|
return {
|
|
58
60
|
command: "bind",
|
|
59
61
|
...(task === undefined ? {} : { task }),
|
|
@@ -69,7 +71,7 @@ function parseAmend(parts) {
|
|
|
69
71
|
const after = parts.flags.after === undefined ? [] : Array.isArray(parts.flags.after) ? parts.flags.after : [parts.flags.after];
|
|
70
72
|
if (parts.flags["clear-after"] === true && after.length > 0)
|
|
71
73
|
refuse("amend", "--clear-after and --after are mutually exclusive");
|
|
72
|
-
const gates =
|
|
74
|
+
const gates = parseGateNames(parts, "amend");
|
|
73
75
|
if (!parts.stdin && parts.flags.after === undefined && parts.flags["clear-after"] !== true && gates === undefined) {
|
|
74
76
|
refuse("amend", "amend requires stdin or --after, --clear-after, or --gates");
|
|
75
77
|
}
|
|
@@ -13,33 +13,25 @@ async function statusSetAkuma(selector, id, alias, world, repo) {
|
|
|
13
13
|
...(result.alias === undefined ? {} : { alias: result.alias }),
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
async function
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
async function statusSetContract(selector, id, world, repo) {
|
|
17
|
+
if (repo === undefined)
|
|
18
|
+
throw new CliUsageError("cannot select a contract while the Contract world is absent");
|
|
19
|
+
const observation = await (await import("../../kanshi/index.js")).observeKanshi({ world, repo, contract: canonicalContractSelector(id) });
|
|
20
|
+
return { selector, kind: "contract", report: observation.report };
|
|
21
|
+
}
|
|
22
|
+
async function statusSetEntry(selector, world, repo, named) {
|
|
19
23
|
if (selector.startsWith("@")) {
|
|
20
|
-
if (
|
|
24
|
+
if (named === undefined)
|
|
21
25
|
throw new CliUsageError("cannot resolve a named status selector");
|
|
22
26
|
const { resolveNamedAddress } = await import("../../library/address.js");
|
|
23
|
-
const address = resolveNamedAddress({ selector, report:
|
|
27
|
+
const address = resolveNamedAddress({ selector, report: named.report, aliases: named.aliases });
|
|
24
28
|
if (address.kind === "akuma")
|
|
25
29
|
return await statusSetAkuma(selector, address.id, selector, world, repo);
|
|
26
|
-
|
|
27
|
-
alias = selector;
|
|
30
|
+
return await statusSetContract(selector, address.id, world, repo);
|
|
28
31
|
}
|
|
29
|
-
if (
|
|
30
|
-
return await statusSetAkuma(selector,
|
|
31
|
-
|
|
32
|
-
throw new CliUsageError("cannot select a contract while the Contract world is absent");
|
|
33
|
-
if (observed === undefined)
|
|
34
|
-
throw new CliUsageError("cannot observe Contract status without a Kanshi report");
|
|
35
|
-
return {
|
|
36
|
-
selector,
|
|
37
|
-
kind: "contract",
|
|
38
|
-
report: (await import("../../kanshi/index.js")).selectKanshi({
|
|
39
|
-
report: observed.report,
|
|
40
|
-
contract: canonicalContractSelector(resolved),
|
|
41
|
-
}),
|
|
42
|
-
};
|
|
32
|
+
if (selector.startsWith("aku/"))
|
|
33
|
+
return await statusSetAkuma(selector, selector, undefined, world, repo);
|
|
34
|
+
return await statusSetContract(selector, selector, world, repo);
|
|
43
35
|
}
|
|
44
36
|
export async function invokeStatusSet(selectors, world, repo) {
|
|
45
37
|
if (selectors.length < 2)
|
|
@@ -47,8 +39,7 @@ export async function invokeStatusSet(selectors, world, repo) {
|
|
|
47
39
|
if (selectors.some((selector) => !selector.startsWith("aku/") && !selector.startsWith("@")) && repo === undefined) {
|
|
48
40
|
throw new CliUsageError("cannot select a contract while the Contract world is absent");
|
|
49
41
|
}
|
|
50
|
-
const
|
|
51
|
-
const observed = needsKanshi
|
|
42
|
+
const named = selectors.some((selector) => selector.startsWith("@"))
|
|
52
43
|
? await (await import("../../kanshi/index.js")).observeKanshi({
|
|
53
44
|
world,
|
|
54
45
|
...(repo === undefined ? {} : { repo }),
|
|
@@ -56,6 +47,6 @@ export async function invokeStatusSet(selectors, world, repo) {
|
|
|
56
47
|
: undefined;
|
|
57
48
|
const entries = [];
|
|
58
49
|
for (const selector of selectors)
|
|
59
|
-
entries.push(await statusSetEntry(selector, world, repo,
|
|
50
|
+
entries.push(await statusSetEntry(selector, world, repo, named));
|
|
60
51
|
return { kind: "status-set", entries };
|
|
61
52
|
}
|
package/build/src/cli/main.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CliUsageError, parseArgv, renderHelp } from "./parse.js";
|
|
2
|
+
import { installedPackageVersion } from "./version.js";
|
|
2
3
|
export async function main(argv = process.argv.slice(2)) {
|
|
3
4
|
try {
|
|
4
5
|
const parsed = parseArgv(argv);
|
|
@@ -8,6 +9,10 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
8
9
|
process.stdout.write(help.endsWith("\n") ? help : `${help}\n`);
|
|
9
10
|
return 0;
|
|
10
11
|
}
|
|
12
|
+
if ("version" in parsed) {
|
|
13
|
+
process.stdout.write(`${await installedPackageVersion()}\n`);
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
11
16
|
return await (await import("./runtime.js")).runCliCommand(parsed);
|
|
12
17
|
}
|
|
13
18
|
catch (error) {
|