@astrosheep/keiyaku 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +73 -56
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms_v2.js +103 -0
  4. package/build/agents/harness/activity-values.js +54 -0
  5. package/build/agents/harness/event-channel.js +55 -20
  6. package/build/agents/harness/events.js +47 -1
  7. package/build/agents/harness/execution-handle.js +292 -61
  8. package/build/agents/harness/index.js +103 -121
  9. package/build/agents/harness/pump.js +36 -47
  10. package/build/agents/harness/runtime.js +3 -0
  11. package/build/agents/launch-snapshot_v2.js +348 -0
  12. package/build/agents/opencode-sdk.js +42 -169
  13. package/build/agents/providers/claude-agent-sdk.js +240 -79
  14. package/build/agents/providers/codex-app-server.js +280 -72
  15. package/build/agents/providers/codex-sdk.js +159 -41
  16. package/build/agents/providers/event-type-tail.js +16 -0
  17. package/build/agents/providers/opencode-sdk.js +165 -59
  18. package/build/agents/providers/pi.js +254 -42
  19. package/build/agents/selector_v2.js +122 -0
  20. package/build/cli/commands/akuma.js +120 -42
  21. package/build/cli/completion.js +6 -7
  22. package/build/cli/flags.js +36 -10
  23. package/build/cli/help.js +42 -26
  24. package/build/cli/index.js +225 -93
  25. package/build/cli/parse.js +194 -75
  26. package/build/cli/projection-address.js +11 -0
  27. package/build/cli/render/address.js +88 -0
  28. package/build/cli/render/arc.js +10 -10
  29. package/build/cli/render/call.js +59 -0
  30. package/build/cli/render/compact-text.js +3 -0
  31. package/build/cli/render/errors.js +4 -2
  32. package/build/cli/render/format.js +6 -0
  33. package/build/cli/render/line-width.js +70 -0
  34. package/build/cli/render/misc.js +7 -4
  35. package/build/cli/render/petition.js +4 -3
  36. package/build/cli/render/projection-activity.js +201 -0
  37. package/build/cli/render/shared.js +46 -12
  38. package/build/cli/render/status.js +59 -10
  39. package/build/cli/render/tool-ledger-rollup.js +74 -0
  40. package/build/cli/render/tool-presentation.js +97 -0
  41. package/build/cli/render/wait.js +229 -0
  42. package/build/cli/skills-install.js +42 -24
  43. package/build/cli/subagent-guard.js +1 -1
  44. package/build/config/akuma-loader_v2.js +222 -0
  45. package/build/config/env-keys.js +0 -4
  46. package/build/config/env.js +0 -6
  47. package/build/config/settings.js +325 -12
  48. package/build/core/addressing.js +224 -0
  49. package/build/core/amend.js +30 -47
  50. package/build/core/arc.js +68 -60
  51. package/build/core/bind.js +105 -25
  52. package/build/core/call-persist.js +69 -0
  53. package/build/core/call.js +658 -0
  54. package/build/core/claim.js +72 -44
  55. package/build/core/command-io.js +19 -19
  56. package/build/core/context.js +11 -36
  57. package/build/core/draft.js +2 -3
  58. package/build/core/entry.js +101 -6
  59. package/build/core/execution-coordinate.js +62 -0
  60. package/build/core/execution-pact.js +141 -0
  61. package/build/core/forfeit.js +2 -3
  62. package/build/core/hints.js +10 -10
  63. package/build/core/ids.js +6 -0
  64. package/build/core/ledger.js +16 -1
  65. package/build/core/petition-claim-gates.js +14 -12
  66. package/build/core/petition-claim.js +1 -0
  67. package/build/core/petition-run.js +6 -2
  68. package/build/core/petition.js +63 -21
  69. package/build/core/places.js +106 -13
  70. package/build/core/projection/generation.js +412 -0
  71. package/build/core/projection/heart.js +316 -0
  72. package/build/core/projection/identity.js +81 -0
  73. package/build/core/projection/leash.js +87 -0
  74. package/build/core/projection/mint.js +154 -0
  75. package/build/core/projection-activity.js +219 -0
  76. package/build/core/projection-coordinate.js +35 -0
  77. package/build/core/projection-core.js +69 -463
  78. package/build/core/projection-generation-continuation.js +31 -0
  79. package/build/core/projection-generation-execution.js +148 -0
  80. package/build/core/projection-generation-identity.js +17 -0
  81. package/build/core/projection-generation-launcher.js +90 -0
  82. package/build/core/projection-generation-process.js +43 -0
  83. package/build/core/projection-generation-runner.js +144 -0
  84. package/build/core/projection-generation-runtime.js +15 -0
  85. package/build/core/projection-generation-store.js +707 -0
  86. package/build/core/projection-identity.js +11 -0
  87. package/build/core/projection-life-observer.js +87 -0
  88. package/build/core/projection-life-protocol.js +95 -0
  89. package/build/core/projection-mint.js +96 -24
  90. package/build/core/projection-runner-lock.js +230 -0
  91. package/build/core/projection-status.js +207 -107
  92. package/build/core/projection-tells.js +401 -0
  93. package/build/core/projection-wait.js +155 -0
  94. package/build/core/projection-wake.js +109 -231
  95. package/build/core/queue_v2.js +342 -0
  96. package/build/core/registry.js +6 -3
  97. package/build/core/render.js +63 -1
  98. package/build/core/renew.js +80 -53
  99. package/build/core/scope.js +186 -137
  100. package/build/core/seal.js +16 -19
  101. package/build/core/status.js +88 -25
  102. package/build/core/stored-agent-event.js +101 -0
  103. package/build/core/transcripts.js +214 -228
  104. package/build/core/verdict.js +27 -15
  105. package/build/core/worktree-bootstrap.js +187 -0
  106. package/build/core/worktree-path.js +72 -18
  107. package/build/flow-error.js +4 -6
  108. package/build/generated/version.js +1 -1
  109. package/build/git/branches.js +6 -1
  110. package/build/index.js +8 -5
  111. package/build/keiyaku.js +1 -3
  112. package/package.json +6 -5
  113. package/skills/keiyaku/SKILL.md +6 -47
  114. package/skills/keiyaku-akuma/SKILL.md +75 -0
  115. package/build/agents/effective-policy.js +0 -32
  116. package/build/agents/index.js +0 -114
  117. package/build/agents/selector.js +0 -28
  118. package/build/cli/render/summon.js +0 -17
  119. package/build/cli/render/tell.js +0 -11
  120. package/build/config/akuma-loader.js +0 -268
  121. package/build/core/queue.js +0 -73
  122. package/build/core/summon-persist.js +0 -73
  123. package/build/core/summon.js +0 -377
@@ -1,5 +1,4 @@
1
1
  import { resolveDefaultAgentName, resolveReviewerAgentName, } from "../../config/settings.js";
2
- import { normalizeAkumaProfile } from "../../config/akuma-loader.js";
3
2
  import { FlowError } from "../../flow-error.js";
4
3
  function formatRoleMarkers(settings, name) {
5
4
  const markers = [];
@@ -9,29 +8,59 @@ function formatRoleMarkers(settings, name) {
9
8
  markers.push("reviewer");
10
9
  return markers.length > 0 ? ` (${markers.join(", ")})` : "";
11
10
  }
12
- function formatProfileSummary(profile) {
13
- const model = profile.model ? `, model ${profile.model}` : "";
14
- return `provider ${profile.provider}, executable ${profile.executable}${model}`;
11
+ function sourceBadge(source) {
12
+ return `[${source}]`;
15
13
  }
16
- function sourceBadge(definition) {
17
- return `[${definition.source}]`;
14
+ function isValidAkumaCandidate(candidate) {
15
+ return candidate.profile !== undefined && candidate.reason === undefined;
18
16
  }
19
- export function renderAkumaList(catalog, settings) {
20
- const lines = ["Available Akumas:", ""];
21
- for (const definition of Object.values(catalog.definitions).sort((a, b) => a.name.localeCompare(b.name))) {
22
- const profile = normalizeAkumaProfile(definition.profile);
23
- lines.push(`- ${definition.name}${formatRoleMarkers(settings, definition.name)} ${sourceBadge(definition)}: ${formatProfileSummary(profile)}`);
24
- if (profile.description) {
25
- lines.push(` ${profile.description}`);
26
- }
17
+ function isValidProviderCandidate(candidate) {
18
+ return candidate.instance !== undefined && candidate.reason === undefined;
19
+ }
20
+ function resolveAkumaInspection(candidate, providerInstances) {
21
+ if (!isValidAkumaCandidate(candidate)) {
22
+ return {
23
+ status: "invalid",
24
+ name: candidate.name,
25
+ source: candidate.source,
26
+ path: candidate.path,
27
+ reason: candidate.reason,
28
+ };
27
29
  }
28
- for (const shadow of catalog.shadows) {
29
- lines.push(`- ${shadow.name} [${shadow.source}] (shadowed by ${shadow.shadowedBy})`);
30
+ const instanceName = candidate.profile.provider;
31
+ const providerCandidate = providerInstances.selected[instanceName];
32
+ if (providerCandidate === undefined) {
33
+ return {
34
+ status: "invalid",
35
+ name: candidate.name,
36
+ source: candidate.source,
37
+ path: candidate.path,
38
+ reason: `missing provider instance '${instanceName}'`,
39
+ };
30
40
  }
31
- for (const invalid of catalog.invalid) {
32
- lines.push(`- ${invalid.name} (invalid: ${invalid.reason})`);
41
+ if (!isValidProviderCandidate(providerCandidate)) {
42
+ return {
43
+ status: "invalid",
44
+ name: candidate.name,
45
+ source: candidate.source,
46
+ path: candidate.path,
47
+ reason: `invalid provider instance '${instanceName}': ${providerCandidate.reason}`,
48
+ };
33
49
  }
34
- return lines.join("\n");
50
+ const providerShadows = providerInstances.shadows.filter((shadow) => shadow.name === instanceName);
51
+ return {
52
+ status: "valid",
53
+ name: candidate.name,
54
+ source: candidate.source,
55
+ path: candidate.path,
56
+ profile: candidate.profile,
57
+ body: candidate.body,
58
+ instanceName,
59
+ instance: providerCandidate.instance,
60
+ kind: providerCandidate.instance.kind,
61
+ providerSource: providerCandidate.source,
62
+ providerShadows,
63
+ };
35
64
  }
36
65
  function appendOptionalLine(lines, label, value) {
37
66
  if (value === undefined)
@@ -46,34 +75,83 @@ function appendOptionalLine(lines, label, value) {
46
75
  }
47
76
  lines.push(`${label}: ${String(value)}`);
48
77
  }
49
- export function renderAkumaShow(catalog, settings, name) {
50
- const definition = catalog.definitions[name];
51
- if (definition === undefined) {
78
+ function appendPromptPreview(lines, body) {
79
+ const promptLines = body === "" ? [] : body.split(/\r?\n/);
80
+ lines.push("prompt:");
81
+ lines.push(...promptLines.slice(0, 8).map((line) => ` ${line}`));
82
+ lines.push(`(${promptLines.length} lines total)`);
83
+ }
84
+ function chooseCallHintName(validNames, settings) {
85
+ if (validNames.length === 0)
86
+ return null;
87
+ const configuredDefault = resolveDefaultAgentName(settings);
88
+ if (validNames.includes(configuredDefault))
89
+ return configuredDefault;
90
+ return validNames[0] ?? null;
91
+ }
92
+ export function renderAkumaList(catalog, providerInstances, settings) {
93
+ const lines = ["Available Akumas:", ""];
94
+ const validNames = [];
95
+ for (const name of Object.keys(catalog.selected).sort((a, b) => a.localeCompare(b))) {
96
+ const candidate = catalog.selected[name];
97
+ if (candidate === undefined)
98
+ continue;
99
+ const resolved = resolveAkumaInspection(candidate, providerInstances);
100
+ const markers = formatRoleMarkers(settings, resolved.name);
101
+ if (resolved.status === "invalid") {
102
+ lines.push(`- ${resolved.name}${markers} ${sourceBadge(resolved.source)} (invalid: ${resolved.reason})`);
103
+ continue;
104
+ }
105
+ validNames.push(resolved.name);
106
+ const model = resolved.profile.model ? `, model ${resolved.profile.model}` : "";
107
+ lines.push(`- ${resolved.name}${markers} ${sourceBadge(resolved.source)}: instance ${resolved.instanceName} (${resolved.kind}, ${resolved.providerSource})${model}`);
108
+ if (resolved.profile.description) {
109
+ lines.push(` ${resolved.profile.description}`);
110
+ }
111
+ }
112
+ for (const shadow of catalog.shadows) {
113
+ lines.push(`- ${shadow.name} [${shadow.source}] (shadowed by ${shadow.shadowedBy})`);
114
+ }
115
+ const hintName = chooseCallHintName(validNames, settings);
116
+ if (hintName !== null) {
117
+ lines.push("");
118
+ lines.push("Call one:");
119
+ lines.push(` » keiyaku call ${hintName} "your task"`);
120
+ }
121
+ return lines.join("\n");
122
+ }
123
+ export function renderAkumaShow(catalog, providerInstances, settings, name) {
124
+ const candidate = catalog.selected[name];
125
+ if (candidate === undefined) {
52
126
  throw new FlowError("UNKNOWN_SUBAGENT", `Unknown agent '${name}'.`);
53
127
  }
54
- const profile = normalizeAkumaProfile(definition.profile);
55
- const promptLines = definition.body === "" ? [] : definition.body.split(/\r?\n/);
128
+ const resolved = resolveAkumaInspection(candidate, providerInstances);
56
129
  const lines = [
57
- `Akuma: ${name}`,
58
- `source: ${sourceBadge(definition)}`,
59
- `definition file: ${definition.path ?? "(built-in)"}`,
60
- `roles: ${formatRoleMarkers(settings, name).replace(/^\s*\(|\)$/g, "") || "(none)"}`,
61
- `provider: ${profile.provider}`,
62
- `executable: ${profile.executable}`,
130
+ `Akuma: ${resolved.name}`,
131
+ `source: ${sourceBadge(resolved.source)}`,
132
+ `definition file: ${resolved.path ?? "(built-in)"}`,
133
+ `roles: ${formatRoleMarkers(settings, resolved.name).replace(/^\s*\(|\)$/g, "") || "(none)"}`,
134
+ `validity: ${resolved.status}`,
63
135
  ];
64
- appendOptionalLine(lines, "description", profile.description);
65
- appendOptionalLine(lines, "model", profile.model);
66
- if (profile.provider === "codex-sdk") {
67
- appendOptionalLine(lines, "profile", profile.profile);
68
- appendOptionalLine(lines, "config", profile.config);
136
+ if (resolved.status === "invalid") {
137
+ lines.push(`reason: ${resolved.reason}`);
138
+ return lines.join("\n");
69
139
  }
70
- if (profile.provider === "claude-agent-sdk") {
71
- appendOptionalLine(lines, "effort", profile.effort);
72
- appendOptionalLine(lines, "permissionMode", profile.permissionMode);
73
- appendOptionalLine(lines, "settingSources", profile.settingSources);
140
+ lines.push(`provider instance: ${resolved.instanceName}`);
141
+ lines.push(`provider kind: ${resolved.kind}`);
142
+ lines.push(`provider source: ${sourceBadge(resolved.providerSource)}`);
143
+ lines.push("provider validity: valid");
144
+ lines.push(`provider fields: ${JSON.stringify(resolved.instance)}`);
145
+ for (const shadow of resolved.providerShadows) {
146
+ lines.push(`provider shadow: ${sourceBadge(shadow.source)} shadowed by ${shadow.shadowedBy}`);
74
147
  }
75
- lines.push("prompt:");
76
- lines.push(...promptLines.slice(0, 8).map((line) => ` ${line}`));
77
- lines.push(`(${promptLines.length} lines total)`);
148
+ appendOptionalLine(lines, "description", resolved.profile.description);
149
+ appendOptionalLine(lines, "model", resolved.profile.model);
150
+ appendOptionalLine(lines, "effort", resolved.profile.effort);
151
+ appendOptionalLine(lines, "effortOptions", resolved.profile.effortOptions);
152
+ appendOptionalLine(lines, "access", resolved.profile.access);
153
+ appendOptionalLine(lines, "network", resolved.profile.network);
154
+ appendOptionalLine(lines, "webSearch", resolved.profile.webSearch);
155
+ appendPromptPreview(lines, resolved.body);
78
156
  return lines.join("\n");
79
157
  }
@@ -1,13 +1,12 @@
1
1
  import { assertSettingsKnobUsable, loadKeiyakuSettings } from "../config/settings.js";
2
- import { loadAkumaCatalog } from "../config/akuma-loader.js";
3
- import { listContractIds } from "../core/status.js";
2
+ import { loadAkumaCatalogV2 } from "../config/akuma-loader_v2.js";
3
+ import { listContractIds } from "../core/ledger.js";
4
4
  const TOP_LEVEL_COMMANDS = [
5
5
  "bind",
6
6
  "arc",
7
- "summon",
8
- "ask",
7
+ "call",
9
8
  "tell",
10
- "resume",
9
+ "revive",
11
10
  "log",
12
11
  "akuma",
13
12
  "skills",
@@ -29,14 +28,14 @@ async function contractAddressCandidates(cwd, word) {
29
28
  async function akumaCandidates(cwd, word) {
30
29
  const loaded = await loadKeiyakuSettings(cwd);
31
30
  assertSettingsKnobUsable(loaded, "agents");
32
- return filterPrefix(Object.keys((await loadAkumaCatalog(cwd)).definitions), word);
31
+ return filterPrefix(Object.keys((await loadAkumaCatalogV2(cwd)).selected), word);
33
32
  }
34
33
  export async function renderCompletionCandidates(input) {
35
34
  const word = input.word ?? "";
36
35
  if (word.startsWith("@")) {
37
36
  return (await contractAddressCandidates(input.cwd, word)).join("\n");
38
37
  }
39
- if (input.previous === "summon" || input.previous === "ask" || input.previous === "show") {
38
+ if (input.previous === "call" || input.previous === "show") {
40
39
  return (await akumaCandidates(input.cwd, word)).join("\n");
41
40
  }
42
41
  if (input.previous === "akuma") {
@@ -4,9 +4,19 @@ export const FLAG_SPECS = {
4
4
  cwd: {
5
5
  kind: "value",
6
6
  placeholder: "DIR",
7
- description: "Run against another repository. Defaults to the current working directory.",
7
+ description: "Select the effective command directory (-C/--cwd). Defaults to the process working directory.",
8
8
  },
9
- agent: {
9
+ repo: {
10
+ kind: "value",
11
+ placeholder: "DIR",
12
+ description: "Select the repository that supplies contract ledgers.",
13
+ },
14
+ contract: {
15
+ kind: "value",
16
+ placeholder: "ADDR",
17
+ description: "Select a commission by place, slug, or full id (same namespace as @addr).",
18
+ },
19
+ akuma: {
10
20
  kind: "value",
11
21
  placeholder: "NAME",
12
22
  description: `Start a new ${ACTOR_IDENTITY} session with the configured agent name.`,
@@ -19,28 +29,33 @@ export const FLAG_SPECS = {
19
29
  effort: {
20
30
  kind: "value",
21
31
  placeholder: "LEVEL",
22
- description: "Override effort for the generation being launched: low, medium, high, or max.",
32
+ description: "Override effort for the generation being launched with an opaque provider-native value.",
23
33
  },
24
34
  projection: {
25
35
  kind: "value",
26
36
  placeholder: "ID",
27
- description: "Projection id for an explicit terminal recovery override.",
37
+ description: "Akuma projection id.",
38
+ },
39
+ timeout: {
40
+ kind: "value",
41
+ placeholder: "DURATION",
42
+ description: "Wait at most a positive duration such as 45s, 5m, or 2h (maximum 24h).",
28
43
  },
29
44
  incognito: {
30
45
  kind: "boolean",
31
- description: "Do not persist response history and do not allow resume.",
46
+ description: "Do not persist response history and do not allow revive.",
32
47
  },
33
48
  bare: {
34
49
  kind: "boolean",
35
50
  description: "Skip contract attachment; Akuma, history, sandbox, credentials, projection, and repository policy remain active.",
36
51
  },
37
- "draft-only": {
52
+ detach: {
38
53
  kind: "boolean",
39
- description: "Write a draft artifact without creating a contract workspace.",
54
+ description: "Return after durable launch instead of waiting for completion.",
40
55
  },
41
- worktree: {
56
+ "draft-only": {
42
57
  kind: "boolean",
43
- description: "Bind the contract in a separate worktree instead of the current workspace.",
58
+ description: "Write a draft artifact without creating a contract workspace.",
44
59
  },
45
60
  exclusive: {
46
61
  kind: "boolean",
@@ -53,7 +68,7 @@ export const FLAG_SPECS = {
53
68
  },
54
69
  force: {
55
70
  kind: "boolean",
56
- description: "Replace an existing installed Keiyaku skill link or directory.",
71
+ description: "Replace an existing installed Keiyaku skill link or directory for any bundled skill.",
57
72
  },
58
73
  reason: {
59
74
  kind: "value",
@@ -64,6 +79,11 @@ export const FLAG_SPECS = {
64
79
  kind: "boolean",
65
80
  description: "Preview claim effects without changing refs, ledgers, queue, registry, or worktrees.",
66
81
  },
82
+ waive: {
83
+ kind: "value",
84
+ placeholder: "PATH",
85
+ description: "Allow one explicit out-of-scope path for this seal. May be repeated.",
86
+ },
67
87
  shell: {
68
88
  kind: "value",
69
89
  placeholder: "SHELL",
@@ -83,6 +103,11 @@ export const FLAG_SPECS = {
83
103
  kind: "boolean",
84
104
  description: "Print completion candidates instead of a shell installation script.",
85
105
  },
106
+ target: {
107
+ kind: "value",
108
+ placeholder: "REF",
109
+ description: "Filter target-keyed status facts by branch name or full refs/heads/<name>.",
110
+ },
86
111
  };
87
112
  export const CONTROL_FLAGS = new Set(Object.keys(FLAG_SPECS));
88
113
  export const VALUE_FLAGS = new Set(Object.entries(FLAG_SPECS)
@@ -92,5 +117,6 @@ export const BOOLEAN_FLAGS = new Set(Object.entries(FLAG_SPECS)
92
117
  .filter(([, spec]) => spec.kind === "boolean")
93
118
  .map(([name]) => name));
94
119
  export const SHORT_FLAG_ALIASES = {
120
+ C: "cwd",
95
121
  f: "force",
96
122
  };
package/build/cli/help.js CHANGED
@@ -3,30 +3,36 @@ function command(name, summary, usage, stdin, flags, purpose, extra = {}) {
3
3
  return { command: name, summary, usage, stdin, flags, purpose, ...extra };
4
4
  }
5
5
  export const CLI_COMMAND_METADATA = {
6
- bind: command("bind", "Create a contract ledger and workspace files", ["keiyaku bind [--cwd DIR] [--worktree] < keiyaku.md"], "required", ["cwd", "worktree", "after", "exclusive", "draft-only"], "Bind a Keiyaku from a contract draft."),
7
- arc: command("arc", "Open the next arc and seal the current arc", ["keiyaku arc [--cwd DIR] < arc.md"], "required", ["cwd"], "Record the next title, objective, and brief. An open arc is sealed first.", {
6
+ bind: command("bind", "Create a contract ledger and workspace files", ["keiyaku bind [-C|--cwd DIR] [--repo DIR] < keiyaku.md"], "required", ["cwd", "repo", "after", "exclusive", "draft-only"], "Bind a Keiyaku from a contract draft.", {
7
+ notes: ["bind creates a commission and does not accept @addr or --contract."],
8
+ }),
9
+ arc: command("arc", "Open the next arc and seal the current arc", ["keiyaku arc [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--waive PATH] < arc.md", "keiyaku @addr arc [-C|--cwd DIR] [--repo DIR] [--waive PATH] < arc.md"], "required", ["cwd", "repo", "contract", "waive"], "Record the next title, objective, and brief. An open arc is sealed first.", {
8
10
  input: ["# <arc title>", "", "## Objective", "<what this arc should accomplish>", "", "## Brief", "<scope, constraints, relevant files, instructions>"],
9
11
  notes: ["An empty seal is valid.", "The command does not create delivery commits."],
10
12
  }),
11
- summon: command("summon", "Start an Akuma helper session", ["keiyaku summon NAME [prompt|-]"], "none", ["cwd", "agent", "model", "effort", "incognito", "bare"], "Run a scoped helper task."),
12
- ask: command("ask", "Start an Akuma helper session", ["keiyaku ask NAME [prompt|-]"], "none", ["cwd", "agent", "model", "effort", "incognito", "bare"], "Run a scoped helper task."),
13
- resume: command("resume", "Resume an Akuma helper session", ["keiyaku resume RESPONSE_PATH [prompt|-]", "keiyaku resume --projection ID [--effort LEVEL]"], "none", ["cwd", "model", "effort", "projection"], "Continue a persisted helper session."),
14
- tell: command("tell", "Send intent to a projection mailbox", ["keiyaku tell [--effort LEVEL] PROJECTION MESSAGE"], "none", ["cwd", "effort"], "Write intent to the mailbox and wake only when eligible."),
15
- log: command("log", "Render a contract ledger", ["keiyaku log [@id] [--cwd DIR]"], "none", ["cwd"], "Read a contract ledger."),
16
- akuma: command("akuma", "Inspect Akuma profiles", ["keiyaku akuma list|show"], "none", [], "Inspect configured helper profiles.", { subcommands: ["list", "ls", "show"] }),
17
- "akuma ls": command("akuma ls", "List Akuma profiles", ["keiyaku akuma ls [--cwd DIR]"], "none", ["cwd"], "List configured helper profiles."),
18
- "akuma list": command("akuma list", "List Akuma profiles", ["keiyaku akuma list [--cwd DIR]"], "none", ["cwd"], "List configured helper profiles."),
19
- "akuma show": command("akuma show", "Show an Akuma profile", ["keiyaku akuma show NAME [--cwd DIR]"], "none", ["cwd"], "Show one configured helper profile."),
13
+ call: command("call", "Start an Akuma helper session", ["keiyaku call NAME [prompt|-]", "keiyaku call NAME --detach [prompt|-]", "keiyaku @addr call NAME [prompt|-]", "keiyaku call NAME --contract ADDR [prompt|-]"], "none", ["cwd", "repo", "contract", "akuma", "model", "effort", "incognito", "bare", "detach"], "Run a scoped helper task."),
14
+ revive: command("revive", "Revive an Akuma helper session", ["keiyaku revive ARTIFACT_ID"], "none", ["cwd", "repo", "model", "effort"], "Continue a persisted helper session."),
15
+ wait: command("wait", "Wait for an akuma projection", ["keiyaku wait <short-id> [--timeout DURATION]", "keiyaku @addr wait <short-id> [--timeout DURATION]"], "none", ["cwd", "repo", "contract", "timeout"], "Read an akuma projection until its outcome is available, or show a timeout snapshot."),
16
+ tell: command("tell", "Send intent to a projection mailbox", ["keiyaku tell [--effort LEVEL] PROJECTION MESSAGE", "keiyaku @addr tell [--effort LEVEL] PROJECTION MESSAGE"], "none", ["cwd", "repo", "contract", "effort"], "Write intent to the mailbox and wake only when eligible."),
17
+ log: command("log", "Render a contract ledger", ["keiyaku log [-C|--cwd DIR] [--repo DIR] [--contract ADDR]", "keiyaku @addr log [-C|--cwd DIR] [--repo DIR]"], "none", ["cwd", "repo", "contract"], "Read a contract ledger."),
18
+ akuma: command("akuma", "Inspect Akuma profiles", ["keiyaku akuma list|show"], "none", [], "Inspect configured helper profiles.", {
19
+ subcommands: ["list", "ls", "show"],
20
+ notes: ["Define user profiles in <KEIYAKU_HOME>/akuma/<name>.md.", "Define project profiles in .keiyaku/akuma/<name>.md.", "See README Configuration for the Markdown frontmatter format."],
21
+ examples: ["keiyaku akuma list", "keiyaku akuma show akuma-codex"],
22
+ }),
23
+ "akuma ls": command("akuma ls", "List Akuma profiles", ["keiyaku akuma ls [-C|--cwd DIR] [--repo DIR]"], "none", ["cwd", "repo"], "List configured helper profiles.", { notes: ["Project profiles override user profiles, which override builtins."] }),
24
+ "akuma list": command("akuma list", "List Akuma profiles", ["keiyaku akuma list [-C|--cwd DIR] [--repo DIR]"], "none", ["cwd", "repo"], "List configured helper profiles.", { notes: ["Project profiles override user profiles, which override builtins."] }),
25
+ "akuma show": command("akuma show", "Show an Akuma profile", ["keiyaku akuma show NAME [-C|--cwd DIR] [--repo DIR]"], "none", ["cwd", "repo"], "Show one configured helper profile.", { notes: ["The output identifies the winning source and normalized provider configuration."] }),
20
26
  skills: command("skills", "Install official skills", ["keiyaku skills install"], "none", [], "Install bundled official Keiyaku skills into supported agent skill directories.", { subcommands: ["install"] }),
21
- "skills install": command("skills install", "Install the official Keiyaku skill", ["keiyaku skills install [-f|--force]"], "none", ["force"], "Install the bundled official Keiyaku skill into supported agent skill directories.", { notes: ["Force permits replacement of foreign collisions."] }),
22
- amend: command("amend", "Record an amendment", ["keiyaku amend [--cwd DIR] < amendment.md"], "required", ["cwd"], "Append a prose amendment and optional structured scope delta."),
23
- renew: command("renew", "Rewrite delivery onto the current base", ["keiyaku renew [--cwd DIR]", "keiyaku @<id> renew [--cwd DIR]"], "none", ["cwd"], "Capture receipts, rewrite delivery onto the default branch, then seal and record the renewal.", { notes: ["Refuses loose commits without an open arc.", "Refuses while an Akuma is in flight.", "Conflicts restore the worktree without ledger writes."] }),
24
- petition: command("petition", "Run the gated settlement pipeline", ["keiyaku petition [--cwd DIR]", "keiyaku @<id> petition [--cwd DIR]"], "none", ["cwd"], "Seal an open arc, queue the contract, and run verdict and claim processing.", { notes: ["Base drift requires explicit `keiyaku renew` before petition."] }),
25
- forfeit: command("forfeit", "Forfeit an addressed contract", ["keiyaku forfeit [--cwd DIR] [--reason TEXT]"], "none", ["cwd", "reason"], "Record an abandoned contract without sealing it."),
27
+ "skills install": command("skills install", "Install the official Keiyaku skills", ["keiyaku skills install [-f|--force]"], "none", ["force"], "Install the bundled official Keiyaku skills into supported agent skill directories.", { notes: ["Force permits replacement of foreign collisions."] }),
28
+ amend: command("amend", "Record an amendment", ["keiyaku amend [-C|--cwd DIR] [--repo DIR] [--contract ADDR] < amendment.md", "keiyaku @addr amend [-C|--cwd DIR] [--repo DIR] < amendment.md"], "required", ["cwd", "repo", "contract"], "Append a prose amendment and optional structured scope delta."),
29
+ renew: command("renew", "Rewrite delivery onto the current base", ["keiyaku renew [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--waive PATH]", "keiyaku @<id> renew [-C|--cwd DIR] [--repo DIR] [--waive PATH]"], "none", ["cwd", "repo", "contract", "waive"], "Capture receipts, rewrite delivery onto the default branch, then seal and record the renewal.", { notes: ["Refuses loose commits without an open arc.", "Refuses while an Akuma is in flight.", "Conflicts restore the worktree without ledger writes."] }),
30
+ petition: command("petition", "Run the gated settlement pipeline", ["keiyaku petition [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--waive PATH]", "keiyaku @<id> petition [-C|--cwd DIR] [--repo DIR] [--waive PATH]"], "none", ["cwd", "repo", "contract", "waive"], "Seal an open arc, queue the contract, and run verdict and claim processing.", { notes: ["Base drift requires explicit `keiyaku renew` before petition."] }),
31
+ forfeit: command("forfeit", "Forfeit an addressed contract", ["keiyaku forfeit [-C|--cwd DIR] [--repo DIR] [--contract ADDR] [--reason TEXT]", "keiyaku @addr forfeit [-C|--cwd DIR] [--repo DIR] [--reason TEXT]"], "none", ["cwd", "repo", "contract", "reason"], "Record an abandoned contract without sealing it."),
26
32
  guide: command("guide", "Print the Keiyaku guide", ["keiyaku guide"], "none", [], "Print workflow guidance."),
27
- completion: command("completion", "Print shell completion", ["keiyaku completion [--shell bash|zsh]"], "none", ["cwd", "shell", "word", "previous", "complete"], "Print command and address candidates."),
28
- status: command("status", "Show the Kanshi board", ["keiyaku status [--cwd DIR]"], "none", ["cwd"], "Read contract, queue, and projection facts without mutation."),
29
- "dump-env": command("dump-env", "Print the environment template", ["keiyaku dump-env"], "none", [], "Print supported environment keys."),
33
+ completion: command("completion", "Print shell completion", ["keiyaku completion [--shell bash|zsh]"], "none", ["cwd", "repo", "shell", "word", "previous", "complete"], "Print command and address candidates."),
34
+ status: command("status", "Show the Kanshi board", ["keiyaku status [-C|--cwd DIR] [--repo DIR] [--target REF]"], "none", ["cwd", "repo", "target"], "Read contract, queue, and projection facts without mutation."),
35
+ "dump-env": command("dump-env", "Print the environment template", ["keiyaku dump-env"], "none", [], "Print supported environment keys.", { notes: ["Keiyaku loads <KEIYAKU_HOME>/.env, then .keiyaku/.env; process environment values win."] }),
30
36
  };
31
37
  function indent(lines) {
32
38
  return lines.map((line) => line ? ` ${line}` : "");
@@ -38,6 +44,9 @@ function section(lines, title, body) {
38
44
  }
39
45
  function flagUsage(name, specs) {
40
46
  const spec = specs[name];
47
+ if (name === "cwd") {
48
+ return `-C, --cwd ${spec?.placeholder ?? "DIR"}`;
49
+ }
41
50
  return spec?.kind === "value" ? `--${name} ${spec.placeholder ?? "VALUE"}` : `--${name}`;
42
51
  }
43
52
  export function formatSubcommandList(subcommands) {
@@ -62,7 +71,7 @@ export function renderCliHelp(version) {
62
71
  "",
63
72
  "Usage:",
64
73
  " keiyaku <command> [flags]",
65
- " keiyaku @<id-prefix> <command> [flags]",
74
+ " keiyaku @<commission> <command> [flags]",
66
75
  "",
67
76
  "Flow:",
68
77
  " bind -> arc -> delivery work -> arc | renew | petition",
@@ -71,9 +80,9 @@ export function renderCliHelp(version) {
71
80
  " bind Create a contract ledger and workspace files.",
72
81
  " arc Open the next arc; seals an open arc first.",
73
82
  " renew Rewrite delivery onto the current base and seal it.",
74
- " summon Start an Akuma helper session.",
75
- " ask Start an Akuma helper session.",
76
- " resume Resume an Akuma helper session.",
83
+ " call Start an Akuma helper session.",
84
+ " wait Wait for an akuma projection.",
85
+ " revive Revive an Akuma helper session.",
77
86
  " tell Send intent to an Akuma projection.",
78
87
  " log Render a contract ledger.",
79
88
  " akuma Inspect helper profiles.",
@@ -88,7 +97,14 @@ export function renderCliHelp(version) {
88
97
  "",
89
98
  "Input:",
90
99
  " bind, arc, and amend read Markdown from stdin.",
91
- " summon, ask, and resume read a prompt argument or stdin.",
100
+ " call and revive read a prompt argument or stdin.",
101
+ "",
102
+ "Configuration:",
103
+ " Akuma profiles <KEIYAKU_HOME>/akuma/*.md or .keiyaku/akuma/*.md",
104
+ " Settings <KEIYAKU_HOME>/settings.json or .keiyaku/settings.json",
105
+ " Inspect keiyaku akuma list | keiyaku akuma show NAME",
106
+ " Environment keiyaku dump-env",
107
+ " Full format README Configuration",
92
108
  ].join("\n");
93
109
  }
94
110
  export function buildKeiyakuGuide(version) {
@@ -101,8 +117,8 @@ export function buildKeiyakuGuide(version) {
101
117
  "- `arc` records intent and seals the prior open arc automatically.",
102
118
  "- `renew` captures old receipts before rewriting delivery onto the default branch.",
103
119
  "- `petition` seals an open arc, requires a fresh base, and starts settlement.",
104
- "- `summon`, `ask`, and `resume` provide helper execution without changing the ledger lifecycle.",
105
- "- `skills install` installs the bundled official Keiyaku skill into supported agent skill directories; force permits replacement of foreign collisions.",
120
+ "- `call` and `revive` provide helper execution without changing the ledger lifecycle.",
121
+ "- `skills install` installs the bundled official Keiyaku skills into supported agent skill directories; force permits replacement of foreign collisions.",
106
122
  "- `status` is read-only and reports next actions, drift, queue state, and projections.",
107
123
  ].join("\n");
108
124
  }