@astrosheep/keiyaku 4.5.26 → 4.5.28
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 +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +82 -162
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +153 -76
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +68 -64
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +115 -146
- package/build/src/akuma/akuma-errors.d.ts +6 -0
- package/build/src/akuma/akuma-errors.js +11 -0
- package/build/src/akuma/akuma-handle.d.ts +54 -1
- package/build/src/akuma/akuma-handle.js +79 -8
- package/build/src/akuma/akuma-instance.js +6 -22
- package/build/src/akuma/akuma-observe.d.ts +6 -0
- package/build/src/akuma/akuma-observe.js +3 -1
- package/build/src/akuma/akuma-probe.d.ts +20 -1
- package/build/src/akuma/akuma-probe.js +20 -3
- package/build/src/akuma/akuma.d.ts +13 -0
- package/build/src/akuma/akuma.js +1 -0
- package/build/src/akuma/allowed.d.ts +2 -1
- package/build/src/akuma/allowed.js +9 -4
- package/build/src/akuma/archetype.js +3 -3
- package/build/src/akuma/body.js +8 -3
- package/build/src/akuma/fleet-execution.d.ts +13 -2
- package/build/src/akuma/fleet-execution.js +45 -0
- package/build/src/akuma/fleet-observation.d.ts +241 -0
- package/build/src/akuma/fleet-observation.js +13 -0
- package/build/src/akuma/fleet-owner-port.d.ts +12 -0
- package/build/src/akuma/fleet-owner-port.js +46 -0
- package/build/src/akuma/fleet-request.d.ts +55 -4
- package/build/src/akuma/fleet-request.js +101 -6
- 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 +1 -0
- package/build/src/akuma/heart/rows.js +8 -0
- package/build/src/akuma/heart/soul.js +2 -2
- package/build/src/akuma/identity.js +11 -9
- package/build/src/akuma/projection.d.ts +36 -0
- package/build/src/akuma/projection.js +2 -1
- package/build/src/akuma/provider.d.ts +14 -0
- package/build/src/akuma/provider.js +66 -4
- package/build/src/akuma/providers/acp/events.js +16 -8
- package/build/src/akuma/providers/claude/events.js +5 -7
- package/build/src/akuma/providers/opencode-sdk/events.js +9 -5
- package/build/src/akuma/providers/pi/events.js +4 -3
- package/build/src/akuma/request-lifecycle.js +10 -1
- package/build/src/akuma-body.js +1 -33
- package/build/src/alias/index.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +8 -0
- package/build/src/cli/commands/akuma-invoke.js +67 -6
- package/build/src/cli/commands/akuma.d.ts +1 -0
- package/build/src/cli/commands/akuma.js +19 -30
- package/build/src/cli/commands/contract-help.d.ts +1 -0
- package/build/src/cli/commands/contract-help.js +9 -5
- package/build/src/cli/invoke.js +1 -1
- package/build/src/cli/render/akuma-activity.d.ts +7 -1
- package/build/src/cli/render/akuma-activity.js +164 -50
- package/build/src/cli/render/akuma-tool.d.ts +5 -0
- package/build/src/cli/render/akuma-tool.js +118 -14
- package/build/src/cli/render/akuma.d.ts +12 -1
- package/build/src/cli/render/akuma.js +74 -2
- package/build/src/cli/render/catalog.js +2 -3
- package/build/src/cli/render/contract-observation.d.ts +1 -0
- package/build/src/cli/render/contract-observation.js +20 -1
- package/build/src/cli/render/contract.js +4 -4
- package/build/src/cli/render/execution-progress.d.ts +1 -0
- package/build/src/cli/render/execution-progress.js +77 -3
- package/build/src/cli/render/kanshi.js +5 -19
- package/build/src/cli/render/terminal.js +3 -1
- package/build/src/cli/runtime.d.ts +6 -0
- package/build/src/cli/runtime.js +35 -17
- package/build/src/core/facts/offer.d.ts +1 -2
- package/build/src/core/verbs/abandon.js +1 -1
- package/build/src/core/verbs/amend.js +1 -1
- package/build/src/core/verbs/arc.js +1 -1
- package/build/src/core/verbs/attestation.js +1 -1
- package/build/src/core/verbs/bind.js +1 -1
- package/build/src/core/verbs/deliver.js +1 -1
- package/build/src/core/verbs/placement.js +1 -1
- package/build/src/core/verbs/reintegrate.js +1 -1
- package/build/src/git/admission.js +18 -7
- package/build/src/identity/coordinates.js +1 -1
- package/build/src/identity/normalize.d.ts +3 -0
- package/build/src/identity/normalize.js +10 -0
- package/build/src/identity/selector.d.ts +1 -0
- package/build/src/identity/selector.js +15 -4
- package/build/src/library/address.d.ts +33 -3
- package/build/src/library/address.js +90 -29
- package/build/src/library/akuma-creation.d.ts +1 -1
- package/build/src/library/akuma-creation.js +10 -52
- package/build/src/library/composition.d.ts +14 -1
- package/build/src/library/fleet.d.ts +13 -2
- package/build/src/library/fleet.js +142 -48
- package/build/src/library/keiyaku.d.ts +14 -1
- package/build/src/plugin/public.d.ts +2 -0
- package/build/src/protocol/completion.js +9 -2
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { noteEvent } from "../../provider.js";
|
|
1
|
+
import { noteEvent, otherToolCall } from "../../provider.js";
|
|
2
2
|
export const OPENCODE_EVENT_DISPOSITIONS = {
|
|
3
3
|
"server.instance.disposed": "dropped",
|
|
4
4
|
"installation.updated": "dropped",
|
|
@@ -115,6 +115,10 @@ function strongerCall(previous, next) {
|
|
|
115
115
|
return previous;
|
|
116
116
|
if (previous?.kind === "fileChange" && next.kind !== "fileChange")
|
|
117
117
|
return previous;
|
|
118
|
+
// The correlated start's admitted preview is authority: a later update never
|
|
119
|
+
// overwrites it, empty or conflicting, while a start without one adopts supplied evidence.
|
|
120
|
+
if (next.kind === "other" && previous?.kind === "other" && previous.input !== undefined)
|
|
121
|
+
return { ...next, input: previous.input };
|
|
118
122
|
return next;
|
|
119
123
|
}
|
|
120
124
|
function runCall(name, value) {
|
|
@@ -163,12 +167,12 @@ function callFor(name, input, metadata) {
|
|
|
163
167
|
if (lower === "grep" || lower === "glob" || lower === "search")
|
|
164
168
|
return searchCall(lower, value);
|
|
165
169
|
if (lower === "edit")
|
|
166
|
-
return editCall(value, meta) ??
|
|
170
|
+
return editCall(value, meta) ?? otherToolCall(name, input);
|
|
167
171
|
if (lower === "write")
|
|
168
|
-
return writeCall(value, meta) ??
|
|
172
|
+
return writeCall(value, meta) ?? otherToolCall(name, input);
|
|
169
173
|
if (lower === "apply_patch")
|
|
170
|
-
return applyPatchCall(meta) ??
|
|
171
|
-
return
|
|
174
|
+
return applyPatchCall(meta) ?? otherToolCall(name, input);
|
|
175
|
+
return otherToolCall(name, input);
|
|
172
176
|
}
|
|
173
177
|
function belongs(part, state) {
|
|
174
178
|
return state.sessionId === undefined || part.sessionID === state.sessionId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { noteEvent, unknownEvent } from "../../provider.js";
|
|
1
|
+
import { noteEvent, otherToolCall, unknownEvent } from "../../provider.js";
|
|
2
2
|
import { diffstatFromUnifiedPatch } from "../unified-patch.js";
|
|
3
3
|
export const PI_EVENT_DISPOSITIONS = {
|
|
4
4
|
agent_end: "drop",
|
|
@@ -112,7 +112,8 @@ function toolCall(name, args) {
|
|
|
112
112
|
return (runCall(name, value) ??
|
|
113
113
|
readCall(name, value) ??
|
|
114
114
|
searchCall(name, value) ??
|
|
115
|
-
fileChangeCall(name, value) ??
|
|
115
|
+
fileChangeCall(name, value) ??
|
|
116
|
+
otherToolCall(name, args));
|
|
116
117
|
}
|
|
117
118
|
function translateNote(event) {
|
|
118
119
|
if (event.type === "compaction_end")
|
|
@@ -129,7 +130,7 @@ function translateToolEnd(event, state) {
|
|
|
129
130
|
const started = state.tools.get(event.toolCallId);
|
|
130
131
|
state.tools.delete(event.toolCallId);
|
|
131
132
|
const name = started?.name ?? event.toolName;
|
|
132
|
-
const call = started?.call ??
|
|
133
|
+
const call = started?.call ?? otherToolCall(name);
|
|
133
134
|
return [
|
|
134
135
|
{
|
|
135
136
|
type: "tool",
|
|
@@ -45,7 +45,16 @@ export class BodyRequestPump {
|
|
|
45
45
|
if (this.handled.has(transportId))
|
|
46
46
|
continue;
|
|
47
47
|
const path = join(this.directory, name);
|
|
48
|
-
|
|
48
|
+
let serialized;
|
|
49
|
+
try {
|
|
50
|
+
serialized = await readFile(path, "utf8");
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (error.code !== "ENOENT")
|
|
54
|
+
throw error;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const claim = decodeEnvelope(serialized, transportId);
|
|
49
58
|
if (claim === null) {
|
|
50
59
|
await rm(path, { force: true });
|
|
51
60
|
this.handled.add(transportId);
|
package/build/src/akuma-body.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { LEASH_HELD_EXIT, runAkumaBody } from "./akuma/body.js";
|
|
2
2
|
import { worldRootForAkumaPaths } from "./akuma/identity.js";
|
|
3
3
|
import { World } from "./world.js";
|
|
4
|
-
import {
|
|
5
|
-
import { Akuma as PublicAkuma } from "./akuma/akuma-instance.js";
|
|
6
|
-
import { Schema } from "./akuma/schema.js";
|
|
4
|
+
import { fleetRequestPort } from "./akuma/fleet-owner-port.js";
|
|
7
5
|
import { fleetRequestCommands } from "./akuma/fleet-request.js";
|
|
8
6
|
import { worktreeHooksFrom } from "./git/hooks.js";
|
|
9
7
|
import { contractRequestCommands, executeForwardedAudit, executeForwardedDeliver, executeForwardedReview, } from "./library/contract-operations.js";
|
|
@@ -71,36 +69,6 @@ function contractUpstream(processConfiguration) {
|
|
|
71
69
|
},
|
|
72
70
|
};
|
|
73
71
|
}
|
|
74
|
-
function fleetRequestPort(world) {
|
|
75
|
-
return {
|
|
76
|
-
wait: async (input) => await executeWaitAkuma({
|
|
77
|
-
path: world,
|
|
78
|
-
ids: input.targets,
|
|
79
|
-
completion: input.completion,
|
|
80
|
-
...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
|
|
81
|
-
signal: input.signal,
|
|
82
|
-
}),
|
|
83
|
-
tell: async (input) => await executeTellAkuma({
|
|
84
|
-
path: world,
|
|
85
|
-
id: input.target,
|
|
86
|
-
body: input.body,
|
|
87
|
-
tellId: input.tellId,
|
|
88
|
-
recordedAt: input.recordedAt,
|
|
89
|
-
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
90
|
-
signal: input.signal,
|
|
91
|
-
}),
|
|
92
|
-
tellAnswer: async (input) => await PublicAkuma.select(world, input.target).tell(input.body, {
|
|
93
|
-
schema: Schema.json(JSON.parse(input.schemaJson), (value) => value),
|
|
94
|
-
...(input.interrupt === undefined ? {} : { interrupt: input.interrupt }),
|
|
95
|
-
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
96
|
-
signal: input.signal,
|
|
97
|
-
}),
|
|
98
|
-
kill: async (input) => {
|
|
99
|
-
const result = await executeKillAkuma({ path: world, ids: input.targets, signal: input.signal });
|
|
100
|
-
return result;
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
72
|
function taskMutationRequestPort() {
|
|
105
73
|
return {
|
|
106
74
|
task: async (input) => await executeTaskMutation({
|
package/build/src/alias/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { parseAkuId } from "../akuma/identity.js";
|
|
|
4
4
|
import { replaceFileDurably } from "../coordination/durable-file.js";
|
|
5
5
|
import { acquireSqliteTransactionLock } from "../coordination/sqlite-transaction-lock.js";
|
|
6
6
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
7
|
-
import { parseAkumaAlias } from "../identity/selector.js";
|
|
7
|
+
import { parseAkumaAlias, parseReadableAkumaAlias } from "../identity/selector.js";
|
|
8
8
|
const VERSION = 1;
|
|
9
9
|
function paths(world) {
|
|
10
10
|
if (typeof world !== "string" || world.trim().length === 0) {
|
|
@@ -56,7 +56,7 @@ function decode(path, bytes) {
|
|
|
56
56
|
if (typeof rawAkuId !== "string")
|
|
57
57
|
corruption(`Alias target must be an AkuId: ${path}`);
|
|
58
58
|
try {
|
|
59
|
-
bindings.push({ alias:
|
|
59
|
+
bindings.push({ alias: parseReadableAkumaAlias(rawAlias), akuId: parseAkuId(rawAkuId).id });
|
|
60
60
|
}
|
|
61
61
|
catch (error) {
|
|
62
62
|
return corruption(`Alias binding is invalid: ${path}`, error);
|
|
@@ -114,7 +114,7 @@ export async function readAliases(world) {
|
|
|
114
114
|
return await read(paths(world).authority);
|
|
115
115
|
}
|
|
116
116
|
export async function resolveAlias(world, value) {
|
|
117
|
-
const alias =
|
|
117
|
+
const alias = parseReadableAkumaAlias(value);
|
|
118
118
|
return (await readAliases(world)).find((binding) => binding.alias === alias)?.akuId ?? null;
|
|
119
119
|
}
|
|
120
120
|
export async function moveAlias(input) {
|
|
@@ -6,6 +6,7 @@ import type { Settings } from "../../settings.js";
|
|
|
6
6
|
import type { WorldRoot } from "../../world.js";
|
|
7
7
|
import type { InvokedAkumaCommand } from "./akuma.js";
|
|
8
8
|
import { type ExecutionContext } from "../../akuma/requests.js";
|
|
9
|
+
import type { AkumaTellWaitResult } from "../../akuma/fleet-observation.js";
|
|
9
10
|
export type AkumaInvocationResult = Readonly<{
|
|
10
11
|
kind: "akuma";
|
|
11
12
|
action: "call";
|
|
@@ -42,6 +43,13 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
42
43
|
result: unknown;
|
|
43
44
|
body: string;
|
|
44
45
|
alias?: string;
|
|
46
|
+
}> | Readonly<{
|
|
47
|
+
kind: "akuma";
|
|
48
|
+
action: "tell";
|
|
49
|
+
mode: "wait";
|
|
50
|
+
result: AkumaTellWaitResult;
|
|
51
|
+
body: string;
|
|
52
|
+
alias?: string;
|
|
45
53
|
}> | Readonly<{
|
|
46
54
|
kind: "akuma";
|
|
47
55
|
action: "tell";
|
|
@@ -4,12 +4,13 @@ import { emitInitiatingPluginSignal } from "../../plugin/akuma-signals.js";
|
|
|
4
4
|
import { observeAkumaStatus } from "../../akuma/akuma-observe.js";
|
|
5
5
|
import { AuthorityCorruptionError, Keiyaku, } from "../../index.js";
|
|
6
6
|
import { callObservationStream, waitObservationStream } from "../render/akuma-activity.js";
|
|
7
|
-
import { callObservationHead } from "../render/akuma.js";
|
|
8
|
-
import { killAkuma, tellAkuma, waitAkuma } from "../../library/fleet.js";
|
|
7
|
+
import { callObservationHead, tellWaitProgressStream } from "../render/akuma.js";
|
|
8
|
+
import { killAkuma, tellAkuma, tellWaitAkuma, waitAkuma } from "../../library/fleet.js";
|
|
9
9
|
import { localExecutionContext } from "../../akuma/requests.js";
|
|
10
10
|
import { Akuma, Schema } from "../../akuma/index.js";
|
|
11
|
-
import { addressAkuma } from "../../library/address.js";
|
|
11
|
+
import { addressAkuma, resolveAkuma } from "../../library/address.js";
|
|
12
12
|
import { executionChannel } from "../../akuma/requests.js";
|
|
13
|
+
import { AkumaDecodeError } from "../../akuma/akuma-errors.js";
|
|
13
14
|
import { requestForwardedFleetTellAnswer } from "../../akuma/fleet-request.js";
|
|
14
15
|
/** The window a call observes for when the caller gives no `--wait` duration. */
|
|
15
16
|
const CALL_TIMEOUT_MS = 300_000;
|
|
@@ -165,17 +166,77 @@ async function inputInitiator(input) {
|
|
|
165
166
|
}
|
|
166
167
|
return { initiator };
|
|
167
168
|
}
|
|
169
|
+
function decodeWaitedTellSchema(result, schema) {
|
|
170
|
+
if (result.observation.reason !== "answered")
|
|
171
|
+
return result;
|
|
172
|
+
if (typeof result.observation.answer !== "string") {
|
|
173
|
+
throw new AkumaDecodeError("Answer is not valid JSON", String(result.observation.answer));
|
|
174
|
+
}
|
|
175
|
+
let parsed;
|
|
176
|
+
try {
|
|
177
|
+
parsed = JSON.parse(result.observation.answer);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
throw new AkumaDecodeError(error instanceof Error ? error.message : "Answer is not valid JSON", result.observation.answer);
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
return { ...result, observation: { reason: "answered", answer: schema.decode(parsed) } };
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
throw new AkumaDecodeError(error instanceof Error ? error.message : "Answer failed schema decode", result.observation.answer);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function invokeWaitedTell(command, input, body) {
|
|
190
|
+
const schema = command.schema === undefined ? undefined : await schemaFromFile(command.schema);
|
|
191
|
+
const alias = inputAlias(command.akuma);
|
|
192
|
+
const progress = command.output === "text" ? tellWaitProgressStream(undefined, alias, resultContext()) : undefined;
|
|
193
|
+
const result = await tellWaitAkuma({
|
|
194
|
+
...(await inputInitiator(input)),
|
|
195
|
+
path: input.path,
|
|
196
|
+
akuma: command.akuma,
|
|
197
|
+
body,
|
|
198
|
+
timeoutMs: command.timeoutMs,
|
|
199
|
+
...(schema === undefined ? {} : { schema }),
|
|
200
|
+
...(command.interrupt ? { interrupt: true } : {}),
|
|
201
|
+
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
202
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
203
|
+
...(progress === undefined
|
|
204
|
+
? {}
|
|
205
|
+
: {
|
|
206
|
+
observe: {
|
|
207
|
+
admitted: (tell, id) => writeProgress(progress.admitted(tell, id).join("\n")),
|
|
208
|
+
observe: (observation) => writeProgress(progress.observe(observation).join("\n")),
|
|
209
|
+
},
|
|
210
|
+
}),
|
|
211
|
+
}, input.execution ?? localExecutionContext());
|
|
212
|
+
const rendered = schema === undefined ? result : decodeWaitedTellSchema(result, schema);
|
|
213
|
+
if (progress !== undefined)
|
|
214
|
+
writeProgress(progress.conclude(rendered).join("\n"));
|
|
215
|
+
return {
|
|
216
|
+
kind: "akuma",
|
|
217
|
+
action: "tell",
|
|
218
|
+
mode: "wait",
|
|
219
|
+
result: rendered,
|
|
220
|
+
body,
|
|
221
|
+
...(alias === undefined ? {} : { alias }),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
168
224
|
async function invokeTell(command, input) {
|
|
169
225
|
const body = await promptBody(command, input);
|
|
226
|
+
if (command.timeoutMs !== undefined)
|
|
227
|
+
return await invokeWaitedTell(command, input, body);
|
|
170
228
|
if (command.schema !== undefined) {
|
|
171
229
|
const schema = await schemaFromFile(command.schema);
|
|
172
|
-
const
|
|
230
|
+
const channel = executionChannel(input.execution);
|
|
231
|
+
const values = {
|
|
173
232
|
path: input.path,
|
|
174
233
|
akuma: command.akuma,
|
|
175
234
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
176
|
-
}
|
|
235
|
+
};
|
|
236
|
+
// A forwarded answer lets the parent Fleet prove the target, so it resolves
|
|
237
|
+
// coordinates here and never reads this process's own Heart files.
|
|
238
|
+
const addressed = channel.kind === "body-request" ? await resolveAkuma(values) : await addressAkuma(values);
|
|
177
239
|
const initiator = await inputInitiator(input);
|
|
178
|
-
const channel = executionChannel(input.execution);
|
|
179
240
|
const answer = channel.kind === "body-request"
|
|
180
241
|
? await requestForwardedFleetTellAnswer({
|
|
181
242
|
directory: channel.directory,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { CliUsageError, commandGuide, isBlankInput, usageLine } from "../usage.js";
|
|
2
|
-
import { parseAkuId } from "../../akuma/identity.js";
|
|
3
2
|
import { parseDuration as decodeDuration } from "../../duration.js";
|
|
4
3
|
import { parseAkumaAlias, parseAkumaGlob } from "../../identity/selector.js";
|
|
5
|
-
import { ALLOWED_ACTIONS, decodeAllowedActions } from "../../akuma/allowed.js";
|
|
4
|
+
import { ALLOWED_ACTIONS, DEFAULT_ALLOWED_ACTIONS, decodeAllowedActions, } from "../../akuma/allowed.js";
|
|
6
5
|
import { parsePublicHistoryId } from "../../akuma/identity.js";
|
|
7
6
|
const AKUMA_COMMAND_SPECS = {
|
|
8
7
|
call: {
|
|
@@ -12,23 +11,23 @@ const AKUMA_COMMAND_SPECS = {
|
|
|
12
11
|
contract: "value",
|
|
13
12
|
alias: "value",
|
|
14
13
|
wait: "value",
|
|
15
|
-
detach: "boolean",
|
|
16
14
|
allowed: "repeatable",
|
|
17
15
|
json: "boolean",
|
|
18
16
|
schema: "value",
|
|
19
17
|
},
|
|
20
|
-
usage: "call <akuma-name> [--contract <kei/...>] [--workdir <path>] [--alias
|
|
18
|
+
usage: "call <akuma-name> [--contract <kei/...>] [--workdir <path>] [--alias <name>] [--allowed <product.action>]... [--schema <file>] [--wait <duration>] (<prompt> | -)",
|
|
21
19
|
purpose: "Birth an Akuma from <akuma-name> with one prompt.",
|
|
22
20
|
details: [
|
|
23
21
|
"Give <prompt> as one argument, or use - to read stdin.",
|
|
24
|
-
"Default:
|
|
25
|
-
"--contract
|
|
22
|
+
"Default: return after birth without waiting for the first answer. Explicit --wait observes the first work for that duration.",
|
|
23
|
+
"--contract associates the born Akuma with that Contract for Dispatch; it never selects a workdir.",
|
|
26
24
|
"--workdir selects the execution directory; a relative path is relative to the invocation cwd.",
|
|
27
|
-
"Without --workdir,
|
|
28
|
-
"--alias assigns the world-local @name selector to the born Akuma.",
|
|
25
|
+
"Without --workdir, the call uses the invocation cwd whether or not --contract is present.",
|
|
26
|
+
"--alias <name> assigns the world-local @name selector to the born Akuma; @name is also accepted.",
|
|
29
27
|
`Legal actions: ${ALLOWED_ACTIONS.join(", ")}.`,
|
|
28
|
+
`Default actions: ${DEFAULT_ALLOWED_ACTIONS.join(", ")}.`,
|
|
30
29
|
"Repeated --allowed adds actions to the selected Akuma's defaults; it never narrows them.",
|
|
31
|
-
"An omitted Archetype
|
|
30
|
+
"An omitted Archetype uses the default actions above; an explicit empty default permits none.",
|
|
32
31
|
"A nested birth is clipped to its direct parent's frozen actions. status <aku/...|@alias> shows the born effective set.",
|
|
33
32
|
"--schema reads a JSON Schema file for the answer contract; stdin remains the prompt source.",
|
|
34
33
|
"With --contract, Dispatch succeeds first. If @name exists, the alias then moves.",
|
|
@@ -54,13 +53,14 @@ const AKUMA_COMMAND_SPECS = {
|
|
|
54
53
|
tell: {
|
|
55
54
|
arity: 1,
|
|
56
55
|
stdin: true,
|
|
57
|
-
flags: { interrupt: "boolean", schema: "value", json: "boolean" },
|
|
58
|
-
usage: "tell <aku/...|@alias> [--interrupt] [--schema <file>] (<prompt> | -)",
|
|
56
|
+
flags: { interrupt: "boolean", schema: "value", wait: "value", json: "boolean" },
|
|
57
|
+
usage: "tell <aku/...|@alias> [--interrupt] [--schema <file>] [--wait <duration>] (<prompt> | -)",
|
|
59
58
|
purpose: "Send one prompt to an existing Akuma and wake it.",
|
|
60
59
|
details: [
|
|
61
60
|
"Give <prompt> as one argument, or use - to read stdin.",
|
|
62
61
|
"--interrupt ends the current Body before recording the prompt and waking its successor.",
|
|
63
62
|
"--schema reads a JSON Schema file for the answer contract; stdin remains the prompt source.",
|
|
63
|
+
"--wait observes this exact Tell for the supplied duration after it is admitted.",
|
|
64
64
|
].join("\n"),
|
|
65
65
|
},
|
|
66
66
|
history: {
|
|
@@ -155,11 +155,7 @@ function scanAkuma(action, argv, fail) {
|
|
|
155
155
|
stdin = true;
|
|
156
156
|
}
|
|
157
157
|
else if (token === "-d") {
|
|
158
|
-
|
|
159
|
-
fail(`option ${token} is not valid for ${action}`);
|
|
160
|
-
if (flags.detach !== undefined)
|
|
161
|
-
fail("duplicate option: --detach");
|
|
162
|
-
flags.detach = true;
|
|
158
|
+
fail(`option ${token} is not valid for ${action}`);
|
|
163
159
|
}
|
|
164
160
|
else if (!token.startsWith("--")) {
|
|
165
161
|
if (isBlankInput(token))
|
|
@@ -180,16 +176,9 @@ function positiveIndex(raw, option, fail) {
|
|
|
180
176
|
fail(`${option} exceeds the safe integer range`);
|
|
181
177
|
return value;
|
|
182
178
|
}
|
|
183
|
-
function validateDirect(value,
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
parseAkumaAlias(value);
|
|
187
|
-
else
|
|
188
|
-
parseAkuId(value);
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
fail(error instanceof Error ? error.message : "invalid Akuma selector");
|
|
192
|
-
}
|
|
179
|
+
function validateDirect(value, _fail) {
|
|
180
|
+
// Address validation belongs to the operation boundary so callers receive
|
|
181
|
+
// the compact Akuma refusal instead of a generic usage page.
|
|
193
182
|
return value;
|
|
194
183
|
}
|
|
195
184
|
function validateSet(value, fail) {
|
|
@@ -287,6 +276,7 @@ function parseTell(flags, subject, prompt, output, fail) {
|
|
|
287
276
|
akuma: validateDirect(subject, fail),
|
|
288
277
|
interrupt: flags.interrupt === true,
|
|
289
278
|
...(schema === undefined ? {} : { schema }),
|
|
279
|
+
...(flags.wait === undefined ? {} : { timeoutMs: parseDuration(flags.wait, "--wait", fail) }),
|
|
290
280
|
prompt,
|
|
291
281
|
output,
|
|
292
282
|
};
|
|
@@ -308,15 +298,14 @@ function parseCall(flags, archetype, prompt, output, fail) {
|
|
|
308
298
|
let alias;
|
|
309
299
|
if (flags.alias !== undefined) {
|
|
310
300
|
try {
|
|
311
|
-
|
|
301
|
+
const name = stringFlag(flags.alias, "--alias requires a name", fail);
|
|
302
|
+
alias = parseAkumaAlias(name.startsWith("@") ? name : `@${name}`);
|
|
312
303
|
}
|
|
313
304
|
catch (error) {
|
|
314
305
|
fail(error instanceof Error ? error.message : "invalid Akuma alias");
|
|
315
306
|
}
|
|
316
307
|
}
|
|
317
|
-
|
|
318
|
-
fail("call --wait and --detach are mutually exclusive");
|
|
319
|
-
const mode = flags.detach === true ? "detach" : "wait";
|
|
308
|
+
const mode = flags.wait === undefined ? "detach" : "wait";
|
|
320
309
|
const timeoutMs = flags.wait === undefined ? undefined : parseDuration(flags.wait, "--wait", fail);
|
|
321
310
|
const allowed = parseAllowedFlag(flags.allowed, fail);
|
|
322
311
|
const schema = flags.schema === undefined ? undefined : stringFlag(flags.schema, "call --schema requires a file", fail);
|
|
@@ -94,6 +94,7 @@ export declare const CONTRACT_COMMAND_SPECS: {
|
|
|
94
94
|
};
|
|
95
95
|
readonly usage: "status [<contract>|@name|<aku/...>]...";
|
|
96
96
|
readonly purpose: "Read the world status board or one or more Contract and Akuma projections.";
|
|
97
|
+
readonly details: "An Akuma projection reports that Akuma's frozen execution workdir; --contract associates a Contract without selecting one.";
|
|
97
98
|
};
|
|
98
99
|
readonly show: {
|
|
99
100
|
readonly positional: "optional";
|
|
@@ -25,14 +25,17 @@ export const CONTRACT_COMMAND_SPECS = {
|
|
|
25
25
|
" # <title>",
|
|
26
26
|
" ## Context motivation, authority, baseline, and boundaries",
|
|
27
27
|
" ## Objective one observable end state",
|
|
28
|
-
" ## Design
|
|
29
|
-
"
|
|
28
|
+
" ## Design existing owner modules/entry points, reuse or change, implementation approach, and critical ordering",
|
|
29
|
+
" unresolved architectural choices are settled before binding; private helper names",
|
|
30
|
+
" and equivalent control flow remain Deliverer freedom",
|
|
31
|
+
" ## Region narrowest justified intended writes for this approach, one pattern per line",
|
|
30
32
|
" ## Criteria one or more ### <criterion> entries",
|
|
31
33
|
" ## Verification optional fenced executor declarations",
|
|
32
34
|
"",
|
|
33
|
-
"Region accepts
|
|
34
|
-
"
|
|
35
|
-
"
|
|
35
|
+
"Region accepts the narrowest justified intended writes for this approach, not every potentially",
|
|
36
|
+
"involved file. Do not use broad directory fallbacks or redundant parent/child patterns. Patterns",
|
|
37
|
+
"are fenced lines, list items, or bare lines; the three forms union. Put one repository-relative",
|
|
38
|
+
"path pattern on each nonblank line. A trailing '/' is directory shorthand for 'path/**'.",
|
|
36
39
|
"A pattern containing whitespace binds with a warning. A fence carries no",
|
|
37
40
|
"info string or exactly 'txt'.",
|
|
38
41
|
"",
|
|
@@ -163,6 +166,7 @@ export const CONTRACT_COMMAND_SPECS = {
|
|
|
163
166
|
flags: { json: "boolean" },
|
|
164
167
|
usage: "status [<contract>|@name|<aku/...>]...",
|
|
165
168
|
purpose: "Read the world status board or one or more Contract and Akuma projections.",
|
|
169
|
+
details: "An Akuma projection reports that Akuma's frozen execution workdir; --contract associates a Contract without selecting one.",
|
|
166
170
|
},
|
|
167
171
|
show: {
|
|
168
172
|
positional: "optional",
|
package/build/src/cli/invoke.js
CHANGED
|
@@ -348,7 +348,7 @@ async function callExecutionCwd(input) {
|
|
|
348
348
|
if (input.workdir !== undefined) {
|
|
349
349
|
return await canonicalBirthCwd(resolve(input.cwd, input.workdir), `workdir is not an existing directory: ${input.workdir}`);
|
|
350
350
|
}
|
|
351
|
-
return input.
|
|
351
|
+
return input.cwd;
|
|
352
352
|
}
|
|
353
353
|
async function invokeParsedAkuma(input) {
|
|
354
354
|
const executionCwd = await callExecutionCwd({
|
|
@@ -25,9 +25,15 @@ export declare function snapshotHeading(id: string, alias: string | undefined, c
|
|
|
25
25
|
* source column a plural wait aligns across its selected set.
|
|
26
26
|
*/
|
|
27
27
|
type RowLayout = Readonly<{
|
|
28
|
-
head: (time: string | undefined, glyph: string, verb: string) => string;
|
|
28
|
+
head: (time: string | undefined, glyph: string, verb: string, columns: number) => string;
|
|
29
29
|
continuation: () => string;
|
|
30
30
|
marker: (count: number) => string;
|
|
31
|
+
/** A plural wait shares one minute clock across all of its attributed rows. */
|
|
32
|
+
clock?: {
|
|
33
|
+
previous?: string;
|
|
34
|
+
};
|
|
35
|
+
/** Plural wait rows spend their full remaining width on one terminal line. */
|
|
36
|
+
singleLine?: true;
|
|
31
37
|
}>;
|
|
32
38
|
/**
|
|
33
39
|
* Shared snapshot activity rendering. Full snapshots render the selected
|