@astrosheep/keiyaku 4.0.1 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/README.md +137 -5
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
  9. package/build/src/akuma/abort.d.ts +2 -0
  10. package/build/src/akuma/abort.js +50 -0
  11. package/build/src/akuma/akuma.d.ts +23 -14
  12. package/build/src/akuma/akuma.js +120 -104
  13. package/build/src/akuma/archetype.d.ts +7 -6
  14. package/build/src/akuma/archetype.js +68 -41
  15. package/build/src/akuma/body.d.ts +3 -5
  16. package/build/src/akuma/body.js +408 -213
  17. package/build/src/akuma/heart/facts.d.ts +25 -34
  18. package/build/src/akuma/heart/facts.js +18 -7
  19. package/build/src/akuma/heart/index.d.ts +39 -42
  20. package/build/src/akuma/heart/index.js +134 -93
  21. package/build/src/akuma/heart/rows.d.ts +9 -31
  22. package/build/src/akuma/heart/rows.js +26 -44
  23. package/build/src/akuma/heart/schema.d.ts +1 -1
  24. package/build/src/akuma/heart/schema.js +7 -15
  25. package/build/src/akuma/heart/soul.d.ts +8 -0
  26. package/build/src/akuma/heart/soul.js +136 -0
  27. package/build/src/akuma/heart/storage.d.ts +28 -14
  28. package/build/src/akuma/heart/storage.js +86 -26
  29. package/build/src/akuma/identity.d.ts +2 -2
  30. package/build/src/akuma/identity.js +9 -9
  31. package/build/src/akuma/index.d.ts +6 -1
  32. package/build/src/akuma/index.js +6 -0
  33. package/build/src/akuma/projection.d.ts +117 -38
  34. package/build/src/akuma/projection.js +208 -97
  35. package/build/src/akuma/provider-recipe.d.ts +24 -0
  36. package/build/src/akuma/provider-recipe.js +100 -0
  37. package/build/src/akuma/provider.d.ts +12 -4
  38. package/build/src/akuma/provider.js +117 -70
  39. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  40. package/build/src/akuma/providers/acp/core.js +159 -0
  41. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  42. package/build/src/akuma/providers/acp/events.js +73 -0
  43. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  44. package/build/src/akuma/providers/acp/index.js +94 -0
  45. package/build/src/akuma/providers/claude/events.js +66 -13
  46. package/build/src/akuma/providers/claude/index.d.ts +2 -1
  47. package/build/src/akuma/providers/claude/index.js +35 -21
  48. package/build/src/akuma/providers/codex-app-server/events.js +4 -1
  49. package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
  50. package/build/src/akuma/providers/codex-app-server/index.js +24 -31
  51. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  52. package/build/src/akuma/providers/grok-build/index.js +70 -0
  53. package/build/src/akuma/providers/index.d.ts +5 -3
  54. package/build/src/akuma/providers/index.js +24 -59
  55. package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
  56. package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
  57. package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
  58. package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
  59. package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
  60. package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
  61. package/build/src/akuma/providers/pi/events.js +49 -11
  62. package/build/src/akuma/providers/pi/index.d.ts +1 -1
  63. package/build/src/akuma/providers/pi/index.js +50 -21
  64. package/build/src/akuma/publication.d.ts +3 -3
  65. package/build/src/akuma/publication.js +28 -40
  66. package/build/src/akuma/requests.d.ts +9 -7
  67. package/build/src/akuma/requests.js +92 -65
  68. package/build/src/alias/index.d.ts +2 -2
  69. package/build/src/alias/index.js +10 -10
  70. package/build/src/body/decode.js +7 -1
  71. package/build/src/body/region.d.ts +2 -0
  72. package/build/src/body/region.js +77 -7
  73. package/build/src/cli/accepted.d.ts +17 -13
  74. package/build/src/cli/accepted.js +72 -34
  75. package/build/src/cli/actor.js +3 -3
  76. package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
  77. package/build/src/cli/commands/akuma-invoke.js +14 -9
  78. package/build/src/cli/commands/akuma.d.ts +13 -3
  79. package/build/src/cli/commands/akuma.js +67 -34
  80. package/build/src/cli/commands/contract.d.ts +18 -5
  81. package/build/src/cli/commands/contract.js +9 -3
  82. package/build/src/cli/commands/task-invoke.d.ts +17 -4
  83. package/build/src/cli/commands/task-invoke.js +43 -20
  84. package/build/src/cli/commands/task-query.d.ts +5 -0
  85. package/build/src/cli/commands/task-query.js +247 -0
  86. package/build/src/cli/commands/task.d.ts +3 -1
  87. package/build/src/cli/commands/task.js +51 -13
  88. package/build/src/cli/coordinates.d.ts +18 -0
  89. package/build/src/cli/coordinates.js +120 -0
  90. package/build/src/cli/draft.d.ts +8 -0
  91. package/build/src/cli/draft.js +96 -0
  92. package/build/src/cli/invoke.d.ts +4 -3
  93. package/build/src/cli/invoke.js +160 -179
  94. package/build/src/cli/main.js +34 -6
  95. package/build/src/cli/parse.d.ts +9 -2
  96. package/build/src/cli/parse.js +29 -7
  97. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  98. package/build/src/cli/render/akuma-tool-command.js +144 -0
  99. package/build/src/cli/render/akuma-tool.d.ts +2 -2
  100. package/build/src/cli/render/akuma-tool.js +30 -4
  101. package/build/src/cli/render/akuma.d.ts +1 -0
  102. package/build/src/cli/render/akuma.js +211 -116
  103. package/build/src/cli/render/audit.d.ts +3 -0
  104. package/build/src/cli/render/audit.js +104 -0
  105. package/build/src/cli/render/contract.d.ts +3 -3
  106. package/build/src/cli/render/contract.js +192 -79
  107. package/build/src/cli/render/kanshi.js +263 -168
  108. package/build/src/cli/render/receipt.d.ts +19 -0
  109. package/build/src/cli/render/receipt.js +106 -0
  110. package/build/src/cli/render/refusal.d.ts +16 -2
  111. package/build/src/cli/render/refusal.js +88 -20
  112. package/build/src/cli/render/region.d.ts +2 -0
  113. package/build/src/cli/render/region.js +17 -0
  114. package/build/src/cli/render/task.d.ts +2 -1
  115. package/build/src/cli/render/task.js +223 -60
  116. package/build/src/cli/render/terminal.d.ts +7 -0
  117. package/build/src/cli/render/terminal.js +46 -0
  118. package/build/src/cli/render/text.js +6 -3
  119. package/build/src/cli/result.d.ts +115 -20
  120. package/build/src/cli/usage.d.ts +1 -0
  121. package/build/src/cli/usage.js +3 -0
  122. package/build/src/contract-worktree.d.ts +6 -5
  123. package/build/src/contract-worktree.js +95 -57
  124. package/build/src/coordination/durable-file.d.ts +4 -3
  125. package/build/src/coordination/durable-file.js +29 -25
  126. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  127. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  128. package/build/src/core/facts/fold.js +1 -6
  129. package/build/src/core/facts/gate.d.ts +1 -0
  130. package/build/src/core/facts/gate.js +1 -0
  131. package/build/src/core/verbs/amend.d.ts +1 -1
  132. package/build/src/core/verbs/amend.js +0 -11
  133. package/build/src/core/verbs/deliver.d.ts +1 -1
  134. package/build/src/core/verbs/deliver.js +1 -7
  135. package/build/src/core/verbs/placement.d.ts +1 -1
  136. package/build/src/core/verbs/placement.js +4 -1
  137. package/build/src/dispatch/index.d.ts +2 -2
  138. package/build/src/dispatch/index.js +17 -17
  139. package/build/src/git/admission.d.ts +1 -1
  140. package/build/src/git/admission.js +11 -11
  141. package/build/src/git/hooks.js +13 -13
  142. package/build/src/git/integration.d.ts +14 -15
  143. package/build/src/git/integration.js +80 -44
  144. package/build/src/git/observe.d.ts +5 -3
  145. package/build/src/git/observe.js +18 -12
  146. package/build/src/git/read-observation.js +9 -9
  147. package/build/src/git/reconcile.d.ts +2 -0
  148. package/build/src/git/reconcile.js +138 -95
  149. package/build/src/git/repository.d.ts +27 -19
  150. package/build/src/git/repository.js +155 -83
  151. package/build/src/git/scratch.d.ts +7 -3
  152. package/build/src/git/scratch.js +44 -37
  153. package/build/src/git/target-placement.d.ts +40 -4
  154. package/build/src/git/target-placement.js +221 -101
  155. package/build/src/git/tender.d.ts +6 -5
  156. package/build/src/git/tender.js +24 -43
  157. package/build/src/git/terminal-seal.d.ts +1 -1
  158. package/build/src/git/terminal-seal.js +7 -5
  159. package/build/src/git/workspace.d.ts +36 -4
  160. package/build/src/git/workspace.js +53 -18
  161. package/build/src/identity/selector.js +1 -1
  162. package/build/src/index.d.ts +3 -3
  163. package/build/src/index.js +1 -1
  164. package/build/src/kanshi/index.d.ts +2 -2
  165. package/build/src/kanshi/index.js +1 -1
  166. package/build/src/kanshi/read.d.ts +2 -1
  167. package/build/src/kanshi/read.js +118 -27
  168. package/build/src/kanshi/report.d.ts +50 -0
  169. package/build/src/kanshi/select.d.ts +5 -0
  170. package/build/src/kanshi/select.js +32 -0
  171. package/build/src/library/address.d.ts +12 -3
  172. package/build/src/library/address.js +77 -46
  173. package/build/src/library/akuma-creation.d.ts +6 -1
  174. package/build/src/library/akuma-creation.js +86 -13
  175. package/build/src/library/audit.d.ts +18 -0
  176. package/build/src/library/audit.js +44 -0
  177. package/build/src/library/bind.js +4 -4
  178. package/build/src/library/catalog.d.ts +1 -1
  179. package/build/src/library/catalog.js +5 -8
  180. package/build/src/library/contract.d.ts +5 -6
  181. package/build/src/library/contract.js +11 -35
  182. package/build/src/library/delivery.d.ts +2 -1
  183. package/build/src/library/fleet.d.ts +2 -2
  184. package/build/src/library/fleet.js +35 -71
  185. package/build/src/library/keiyaku.d.ts +3 -2
  186. package/build/src/library/keiyaku.js +1 -0
  187. package/build/src/library/mutation.d.ts +7 -6
  188. package/build/src/library/mutation.js +23 -25
  189. package/build/src/library/reconcile.d.ts +29 -0
  190. package/build/src/library/reconcile.js +179 -0
  191. package/build/src/library/region.d.ts +12 -0
  192. package/build/src/library/region.js +15 -1
  193. package/build/src/library/repo.d.ts +4 -16
  194. package/build/src/library/repo.js +13 -38
  195. package/build/src/protocol/attempt.js +6 -6
  196. package/build/src/protocol/bind.js +4 -4
  197. package/build/src/protocol/intent.d.ts +15 -2
  198. package/build/src/protocol/intent.js +21 -6
  199. package/build/src/protocol/operations.d.ts +73 -22
  200. package/build/src/protocol/operations.js +292 -88
  201. package/build/src/protocol/outcome.d.ts +9 -3
  202. package/build/src/protocol/outcome.js +3 -1
  203. package/build/src/protocol/placement.d.ts +15 -4
  204. package/build/src/protocol/placement.js +58 -25
  205. package/build/src/protocol/read/status.d.ts +8 -1
  206. package/build/src/protocol/read/status.js +61 -14
  207. package/build/src/runtime/proc/line-rpc.d.ts +3 -8
  208. package/build/src/runtime/proc/line-rpc.js +16 -43
  209. package/build/src/runtime/proc/run.d.ts +15 -29
  210. package/build/src/runtime/proc/run.js +113 -105
  211. package/build/src/runtime/proc/stdio.d.ts +18 -0
  212. package/build/src/runtime/proc/stdio.js +58 -0
  213. package/build/src/settings.d.ts +2 -2
  214. package/build/src/settings.js +8 -8
  215. package/build/src/settlement/fence.d.ts +0 -4
  216. package/build/src/settlement/fence.js +0 -9
  217. package/build/src/settlement/holder.d.ts +11 -1
  218. package/build/src/settlement/holder.js +25 -0
  219. package/build/src/settlement/settle.d.ts +1 -1
  220. package/build/src/settlement/settle.js +52 -89
  221. package/build/src/task/board.d.ts +3 -3
  222. package/build/src/task/board.js +6 -9
  223. package/build/src/task/compose.d.ts +1 -1
  224. package/build/src/task/compose.js +18 -10
  225. package/build/src/task/context.d.ts +3 -3
  226. package/build/src/task/context.js +14 -14
  227. package/build/src/task/document.d.ts +2 -1
  228. package/build/src/task/document.js +15 -5
  229. package/build/src/task/index.d.ts +19 -7
  230. package/build/src/task/index.js +42 -23
  231. package/build/src/task/operations.d.ts +15 -9
  232. package/build/src/task/operations.js +78 -48
  233. package/build/src/task/query.d.ts +67 -0
  234. package/build/src/task/query.js +279 -0
  235. package/build/src/task/store.d.ts +2 -2
  236. package/build/src/task/store.js +40 -25
  237. package/build/src/verification/execution.d.ts +4 -2
  238. package/build/src/verification/execution.js +9 -5
  239. package/build/src/workspace-place.d.ts +41 -0
  240. package/build/src/workspace-place.js +386 -0
  241. package/build/src/world.d.ts +13 -2
  242. package/build/src/world.js +81 -48
  243. package/package.json +3 -2
  244. package/build/src/protocol/read/audit.d.ts +0 -31
  245. package/build/src/protocol/read/audit.js +0 -55
@@ -1,13 +1,20 @@
1
+ import { AkumaWorldScopeError } from "../index.js";
1
2
  import { CliUsageError, parseArgv, renderContractHelp, renderRootHelp, } from "./parse.js";
2
3
  import { renderText } from "./render/text.js";
3
4
  import { renderTaskIncompleteDiagnostic, renderTaskText, taskExitCode } from "./render/task.js";
4
- import { akumaExitCode, renderAkumaJson, renderAkumaText } from "./render/akuma.js";
5
+ import { akumaExitCode, akumaRawAnswer, renderAkumaJson, renderAkumaText } from "./render/akuma.js";
5
6
  import { isParsedAkumaCommand, renderAkumaHelp } from "./commands/akuma.js";
6
7
  import { installExitCode, renderInstallHelp, renderInstallText } from "./commands/install.js";
7
8
  import { renderTaskHelp } from "./commands/task.js";
8
9
  import { renderSettingsText, settingsJsonValue } from "./render/settings.js";
9
10
  import { renderCatalogText } from "./render/catalog.js";
11
+ import { BindDraftError } from "./draft.js";
12
+ import { renderBindDraftReceipt } from "./render/refusal.js";
10
13
  function writeTask(command, result) {
14
+ const context = {
15
+ columns: process.stdout.isTTY === true && Number.isInteger(process.stdout.columns) ? process.stdout.columns : 80,
16
+ color: false,
17
+ };
11
18
  if (command.output === "json")
12
19
  process.stdout.write(`${JSON.stringify(result)}\n`);
13
20
  else if (command.action === "compose" && typeof result === "object" && result !== null && "kind" in result && result.kind === "incomplete") {
@@ -17,7 +24,7 @@ function writeTask(command, result) {
17
24
  process.stdout.write(result.draft);
18
25
  }
19
26
  else
20
- process.stdout.write(`${renderTaskText(command, result)}\n`);
27
+ process.stdout.write(`${renderTaskText(command, result, context)}\n`);
21
28
  return taskExitCode(result);
22
29
  }
23
30
  function writeAkuma(command, result) {
@@ -25,8 +32,9 @@ function writeAkuma(command, result) {
25
32
  columns: process.stdout.isTTY === true && Number.isInteger(process.stdout.columns) ? process.stdout.columns : 80,
26
33
  color: process.stdout.isTTY === true && process.env.NO_COLOR === undefined,
27
34
  });
28
- const rawLast = command.command === "history" && command.last && command.output === "text";
29
- process.stdout.write(rawLast ? output : `${output}\n`);
35
+ const raw = command.output === "text"
36
+ && ((command.command === "history" && command.last) || akumaRawAnswer(result) !== undefined);
37
+ process.stdout.write(raw ? output : `${output}\n`);
30
38
  return akumaExitCode(result);
31
39
  }
32
40
  function renderHelp(coordinate) {
@@ -49,6 +57,7 @@ function writeCatalog(command, result) {
49
57
  process.stdout.write(`${command.output === "json" ? JSON.stringify(result.catalog) : renderCatalogText(result.catalog)}\n`);
50
58
  return 0;
51
59
  }
60
+ // eslint-disable-next-line complexity -- output dispatch is the single CLI presentation boundary.
52
61
  function writeResult(command, result) {
53
62
  if (command.command === "install") {
54
63
  const value = result;
@@ -71,6 +80,11 @@ function writeResult(command, result) {
71
80
  return writeGuidance(command, contractResult);
72
81
  if (contractResult.kind === "catalog")
73
82
  return writeCatalog(command, contractResult);
83
+ if (contractResult.kind === "region") {
84
+ const output = command.output === "json" ? JSON.stringify(contractResult.region) : renderText(contractResult);
85
+ process.stdout.write(`${output}\n`);
86
+ return 0;
87
+ }
74
88
  const output = command.output === "json"
75
89
  ? JSON.stringify(contractResult.kind === "status" ? contractResult.report : contractResult)
76
90
  : renderText(contractResult, {
@@ -80,19 +94,33 @@ function writeResult(command, result) {
80
94
  process.stdout.write(`${output}\n`);
81
95
  return contractResult.kind === "refused" ? 1 : contractResult.kind === "retry" ? 2 : 0;
82
96
  }
97
+ function writeWorldScopeRefusal(error, output) {
98
+ const body = output === "json"
99
+ ? JSON.stringify(error.refusal)
100
+ : `${error.refusal.kind} ${error.refusal.world} ${error.refusal.ids.join(" ")}`;
101
+ process.stderr.write(`${body}\n`);
102
+ return 1;
103
+ }
83
104
  export async function main(argv = process.argv.slice(2)) {
105
+ let output = "text";
84
106
  try {
85
107
  const parsed = parseArgv(argv);
86
108
  if ("help" in parsed) {
87
109
  process.stdout.write(`${renderHelp(parsed.help)}\n`);
88
110
  return 0;
89
111
  }
112
+ output = parsed.command.output;
90
113
  const { invoke } = await import("./invoke.js");
91
114
  const result = await invoke(parsed, { cwd: process.cwd() });
92
115
  return writeResult(parsed.command, result);
93
116
  }
94
117
  catch (error) {
95
- process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
96
- return error instanceof CliUsageError ? 1 : 3;
118
+ if (error instanceof AkumaWorldScopeError)
119
+ return writeWorldScopeRefusal(error, output);
120
+ const original = error instanceof BindDraftError ? error.original : error;
121
+ process.stderr.write(`${original instanceof Error ? original.message : String(original)}\n`);
122
+ if (error instanceof BindDraftError)
123
+ process.stderr.write(`${renderBindDraftReceipt(error.draft)}\n`);
124
+ return original instanceof CliUsageError ? 1 : 3;
97
125
  }
98
126
  }
@@ -67,7 +67,8 @@ export type ParsedLs = Output & Readonly<{
67
67
  export type ParsedAudit = Output & Readonly<{
68
68
  command: "audit";
69
69
  contract?: string;
70
- showDiffBody: boolean;
70
+ includeDirty: boolean;
71
+ showDiff: boolean;
71
72
  actor?: string;
72
73
  }>;
73
74
  type ParsedReconcile = Output & Readonly<{
@@ -78,10 +79,16 @@ type ParsedReconcile = Output & Readonly<{
78
79
  export type ParsedSettings = Output & Readonly<{
79
80
  command: "settings";
80
81
  }>;
82
+ export type ParsedRegion = Output & Readonly<{
83
+ command: "region";
84
+ contract?: string;
85
+ overlap: boolean;
86
+ path?: string;
87
+ }>;
81
88
  export type ParsedCommand = ParsedBind | ParsedAmend | ParsedDeliver | ParsedReview | ParsedArc | ParsedAbandon | ParsedStatus | (Output & Readonly<{
82
89
  command: "show";
83
90
  contract?: string;
84
- }>) | ParsedLs | ParsedAudit | ParsedReconcile | ParsedSettings | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
91
+ }>) | ParsedLs | ParsedAudit | ParsedReconcile | ParsedSettings | ParsedRegion | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
85
92
  export type CliHelpCoordinate = Readonly<{
86
93
  kind: "root";
87
94
  }> | Readonly<{
@@ -1,8 +1,8 @@
1
1
  import { isTaskAction, parseTaskCommand, renderTaskUsage, } from "./commands/task.js";
2
2
  import { isAkumaAction, parseAkumaCatalogPath, parseAkumaCommand, renderAkumaRootRows, renderAkumaUsage, } from "./commands/akuma.js";
3
3
  import { INSTALL_USAGE, parseInstallCommand, renderInstallHelp } from "./commands/install.js";
4
- import { CONTRACT_COMMAND_SPECS } from "./commands/contract.js";
5
- import { CliUsageError, usageLine } from "./usage.js";
4
+ import { AMEND_MINIMAL_STDIN_HELP, CONTRACT_COMMAND_SPECS } from "./commands/contract.js";
5
+ import { CliUsageError, isBlankInput, usageLine } from "./usage.js";
6
6
  export { CliUsageError } from "./usage.js";
7
7
  const ROOT_USAGE = "usage: keiyaku [-C <path>] [--repo <path>] <command> [<contract>|@<contract>] [--flag ...] [-]";
8
8
  export function renderRootHelp() {
@@ -24,7 +24,8 @@ export function renderRootHelp() {
24
24
  }
25
25
  export function renderContractHelp(command) {
26
26
  const spec = CONTRACT_COMMAND_SPECS[command];
27
- return `${spec.purpose}\n\n${usageLine(spec.usage)}`;
27
+ const help = `${spec.purpose}\n\n${usageLine(spec.usage)}`;
28
+ return command === "amend" ? `${help}\n\n${AMEND_MINIMAL_STDIN_HELP}` : help;
28
29
  }
29
30
  function contractUsage(command) {
30
31
  return usageLine(CONTRACT_COMMAND_SPECS[command].usage);
@@ -70,6 +71,8 @@ function scanOption(command, argv, state, index) {
70
71
  const value = argv[index + 1];
71
72
  if (value === undefined || value === "-" || value.startsWith("--"))
72
73
  refuse(command, `${token} requires a value`);
74
+ if (isBlankInput(value))
75
+ refuse(command, `${token} requires a nonblank value`);
73
76
  if (kind === "repeat-value") {
74
77
  const values = state.flags[name];
75
78
  state.flags[name] = [...(Array.isArray(values) ? values : values === undefined ? [] : [values]), value];
@@ -97,6 +100,8 @@ function scanArgv(argv) {
97
100
  index = scanOption(command, argv, state, index);
98
101
  continue;
99
102
  }
103
+ if (isBlankInput(token))
104
+ refuse(command, `${command} requires a nonblank value`);
100
105
  state.positionals.push(token);
101
106
  }
102
107
  if (spec.positional === "none" && state.positionals.length > 0) {
@@ -161,8 +166,9 @@ function parseReview(parts) {
161
166
  refuse("review", "review requires exactly one verdict flag");
162
167
  }
163
168
  const summary = optionalFlag(parts.flags, "summary");
164
- if (parts.stdin && summary !== undefined)
165
- refuse("review", "review stdin '-' and --summary are mutually exclusive");
169
+ if (parts.stdin === (summary !== undefined)) {
170
+ refuse("review", "review requires exactly one of --summary <text> or stdin '-'");
171
+ }
166
172
  const contract = parts.positionals[0];
167
173
  return {
168
174
  command: "review",
@@ -214,6 +220,20 @@ function parseShow(parts) {
214
220
  const contract = parts.positionals[0];
215
221
  return { command: "show", ...(contract === undefined ? {} : { contract }), output: parts.output };
216
222
  }
223
+ function parseRegion(parts) {
224
+ const contract = parts.positionals[0];
225
+ const path = optionalFlag(parts.flags, "path");
226
+ const overlap = parts.flags.overlap === true;
227
+ if (path !== undefined && (contract !== undefined || overlap))
228
+ refuse("region", "--path cannot combine with a contract or --overlap");
229
+ return {
230
+ command: "region",
231
+ ...(contract === undefined ? {} : { contract }),
232
+ ...(path === undefined ? {} : { path }),
233
+ overlap,
234
+ output: parts.output,
235
+ };
236
+ }
217
237
  function parseLs(parts) {
218
238
  const path = parts.positionals[0];
219
239
  if (path === "task/")
@@ -254,7 +274,7 @@ function invocationOptions(argv) {
254
274
  throw new CliUsageError("-C/--cwd may appear only once", renderRootHelp());
255
275
  }
256
276
  const value = argv[index + 1];
257
- if (value === undefined || value === "-" || value.startsWith("-")) {
277
+ if (value === undefined || value === "-" || value.startsWith("-") || isBlankInput(value)) {
258
278
  throw new CliUsageError(`${token} requires a path`, renderRootHelp());
259
279
  }
260
280
  if (token === "--repo")
@@ -304,7 +324,8 @@ function parseCommand(parts) {
304
324
  return {
305
325
  command: "audit",
306
326
  ...(contract === undefined ? {} : { contract }),
307
- showDiffBody: parts.flags["show-diff-body"] === true,
327
+ includeDirty: parts.flags["include-dirty"] === true,
328
+ showDiff: parts.flags.diff === true,
308
329
  ...(parts.actor === undefined ? {} : { actor: parts.actor }),
309
330
  output: parts.output,
310
331
  };
@@ -319,6 +340,7 @@ function parseCommand(parts) {
319
340
  };
320
341
  }
321
342
  case "settings": return { command: "settings", output: parts.output };
343
+ case "region": return parseRegion(parts);
322
344
  }
323
345
  }
324
346
  export function parseArgv(argv) {
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Unwrap only complete provider transport launchers. This is deliberately not
3
+ * a shell parser: uncertainty preserves the persisted command's presentation.
4
+ */
5
+ /** Return a display subject only when the full transport shape is unambiguous. */
6
+ export declare function normalizeToolCommand(command: string): string;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Unwrap only complete provider transport launchers. This is deliberately not
3
+ * a shell parser: uncertainty preserves the persisted command's presentation.
4
+ */
5
+ const HORIZONTAL_WHITESPACE = new Set([" ", "\t"]);
6
+ const UNSUPPORTED_UNQUOTED = new Set(["$", "`", "|", "&", ";", "<", ">", "(", ")"]);
7
+ const DOUBLE_QUOTE_ESCAPES = new Set(["\"", "\\", "$", "`"]);
8
+ const POWERSHELL_OPTION_FLAGS = new Set(["-nologo", "-noprofile"]);
9
+ const POWERSHELL_COMMAND_FLAGS = new Set(["-command", "-c"]);
10
+ const SCAN_FAIL = { ok: false };
11
+ function scanned(index, value) {
12
+ return { ok: true, index, value };
13
+ }
14
+ function isLineBoundary(character) {
15
+ return character === "\n" || character === "\r";
16
+ }
17
+ function isAbsoluteExecutable(value) {
18
+ return value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value);
19
+ }
20
+ function executableName(value) {
21
+ const segments = value.split(/[\\/]/u);
22
+ return segments[segments.length - 1].toLowerCase();
23
+ }
24
+ function isBashOrZsh(value) {
25
+ const name = executableName(value);
26
+ return (value === "bash" || value === "zsh" || isAbsoluteExecutable(value))
27
+ && (name === "bash" || name === "zsh");
28
+ }
29
+ function isPowerShell(value) {
30
+ const name = executableName(value);
31
+ return (value.toLowerCase() === "powershell" || value.toLowerCase() === "pwsh" || isAbsoluteExecutable(value))
32
+ && (name === "powershell" || name === "powershell.exe" || name === "pwsh" || name === "pwsh.exe");
33
+ }
34
+ function scanSingleQuoted(command, index) {
35
+ const end = command.indexOf("'", index + 1);
36
+ return end < 0 ? SCAN_FAIL : scanned(end + 1, command.slice(index + 1, end));
37
+ }
38
+ function scanDoubleQuotedEscape(command, index) {
39
+ const next = command[index + 1];
40
+ if (next === undefined || isLineBoundary(next))
41
+ return SCAN_FAIL;
42
+ return scanned(index + 2, DOUBLE_QUOTE_ESCAPES.has(next) ? next : `\\${next}`);
43
+ }
44
+ function scanDoubleQuoted(command, index) {
45
+ let cursor = index + 1;
46
+ let value = "";
47
+ while (cursor < command.length) {
48
+ const quoted = command[cursor];
49
+ if (quoted === "\"")
50
+ return scanned(cursor + 1, value);
51
+ if (quoted === "$" || quoted === "`")
52
+ return SCAN_FAIL;
53
+ if (quoted === "\\") {
54
+ const escaped = scanDoubleQuotedEscape(command, cursor);
55
+ if (!escaped.ok)
56
+ return SCAN_FAIL;
57
+ value += escaped.value;
58
+ cursor = escaped.index;
59
+ continue;
60
+ }
61
+ value += quoted;
62
+ cursor += 1;
63
+ }
64
+ return SCAN_FAIL;
65
+ }
66
+ function scanUnquotedEscape(command, index) {
67
+ const next = command[index + 1];
68
+ if (next === undefined || isLineBoundary(next))
69
+ return SCAN_FAIL;
70
+ return scanned(index + 2, next);
71
+ }
72
+ function scanTokenSegment(command, index) {
73
+ const character = command[index];
74
+ if (isLineBoundary(character) || UNSUPPORTED_UNQUOTED.has(character))
75
+ return SCAN_FAIL;
76
+ if (character === "'")
77
+ return scanSingleQuoted(command, index);
78
+ if (character === "\"")
79
+ return scanDoubleQuoted(command, index);
80
+ if (character === "\\")
81
+ return scanUnquotedEscape(command, index);
82
+ return scanned(index + 1, character);
83
+ }
84
+ function scanToken(command, index) {
85
+ let cursor = index;
86
+ let value = "";
87
+ let consumed = false;
88
+ while (cursor < command.length && !HORIZONTAL_WHITESPACE.has(command[cursor])) {
89
+ const segment = scanTokenSegment(command, cursor);
90
+ if (!segment.ok)
91
+ return SCAN_FAIL;
92
+ value += segment.value;
93
+ cursor = segment.index;
94
+ consumed = true;
95
+ }
96
+ return consumed ? scanned(cursor, value) : SCAN_FAIL;
97
+ }
98
+ function parseTransportArgv(command) {
99
+ const argv = [];
100
+ let index = 0;
101
+ while (index < command.length) {
102
+ while (HORIZONTAL_WHITESPACE.has(command[index]))
103
+ index += 1;
104
+ if (index === command.length)
105
+ break;
106
+ if (isLineBoundary(command[index]))
107
+ return undefined;
108
+ const token = scanToken(command, index);
109
+ if (!token.ok)
110
+ return undefined;
111
+ argv.push(token.value);
112
+ index = token.index;
113
+ }
114
+ return argv;
115
+ }
116
+ function unwrapBashOrZsh(argv) {
117
+ const [shell, flag, script] = argv;
118
+ if (argv.length !== 3 || !shell || !script || !isBashOrZsh(shell))
119
+ return undefined;
120
+ return flag === "-c" || flag === "-lc" ? script : undefined;
121
+ }
122
+ function unwrapPowerShell(argv) {
123
+ const [shell, ...arguments_] = argv;
124
+ if (!shell || !isPowerShell(shell) || arguments_.length < 2)
125
+ return undefined;
126
+ const options = new Set();
127
+ for (let index = 0; index < arguments_.length - 1; index += 1) {
128
+ const flag = arguments_[index].toLowerCase();
129
+ if (POWERSHELL_COMMAND_FLAGS.has(flag)) {
130
+ return index === arguments_.length - 2 && arguments_[index + 1] ? arguments_[index + 1] : undefined;
131
+ }
132
+ if (!POWERSHELL_OPTION_FLAGS.has(flag) || options.has(flag))
133
+ return undefined;
134
+ options.add(flag);
135
+ }
136
+ return undefined;
137
+ }
138
+ /** Return a display subject only when the full transport shape is unambiguous. */
139
+ export function normalizeToolCommand(command) {
140
+ const argv = parseTransportArgv(command);
141
+ if (!argv)
142
+ return command;
143
+ return unwrapBashOrZsh(argv) ?? unwrapPowerShell(argv) ?? command;
144
+ }
@@ -1,5 +1,5 @@
1
- import type { ActivityRow } from "../../akuma/index.js";
2
- type ToolRow = Extract<ActivityRow, {
1
+ import type { ActivityRow, SnapshotRow } from "../../akuma/index.js";
2
+ type ToolRow = Extract<ActivityRow | SnapshotRow, {
3
3
  kind: "tool";
4
4
  }>;
5
5
  export type ToolRepr = Readonly<{
@@ -1,3 +1,4 @@
1
+ import { normalizeToolCommand } from "./akuma-tool-command.js";
1
2
  function oneLine(value) {
2
3
  return value.replace(/\s+/gu, " ").trim();
3
4
  }
@@ -12,7 +13,7 @@ function duration(milliseconds) {
12
13
  return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
13
14
  }
14
15
  function result(row) {
15
- if (row.state === "running")
16
+ if (row.state === "active" || row.state === "unsettled")
16
17
  return undefined;
17
18
  const disposition = row.state.exitCode !== undefined
18
19
  ? row.state.exitCode === 0 ? "ok" : `exit ${row.state.exitCode}`
@@ -24,6 +25,31 @@ function result(row) {
24
25
  ];
25
26
  return parts.length === 0 ? undefined : parts.join(" · ");
26
27
  }
28
+ function readText(call) {
29
+ const path = oneLine(call.path);
30
+ if (call.offset !== undefined && call.limit !== undefined) {
31
+ return `${path} · L${call.offset}-${call.offset + call.limit - 1}`;
32
+ }
33
+ if (call.offset !== undefined)
34
+ return `${path} · from L${call.offset}`;
35
+ if (call.limit !== undefined)
36
+ return `${path} · ${call.limit} lines`;
37
+ return path;
38
+ }
39
+ function searchLabel(scope) {
40
+ if (scope === "files")
41
+ return "find";
42
+ if (scope === "web")
43
+ return "web";
44
+ return "search";
45
+ }
46
+ function searchText(call) {
47
+ return [
48
+ oneLine(call.query),
49
+ ...(call.path === undefined ? [] : [oneLine(call.path)]),
50
+ ...(call.glob === undefined ? [] : [oneLine(call.glob)]),
51
+ ].join(" · ");
52
+ }
27
53
  function fileChange(call) {
28
54
  const first = call.changes[0];
29
55
  if (first === undefined)
@@ -48,13 +74,13 @@ export function toolRepr(row) {
48
74
  let core;
49
75
  switch (row.call.kind) {
50
76
  case "run":
51
- core = { label: "run", text: `$ ${oneLine(row.call.command)}`, overflow: "middle-ellipsis" };
77
+ core = { label: "run", text: `$ ${oneLine(normalizeToolCommand(row.call.command))}`, overflow: "middle-ellipsis" };
52
78
  break;
53
79
  case "read":
54
- core = { label: "read", text: oneLine(row.call.path) };
80
+ core = { label: "read", text: readText(row.call) };
55
81
  break;
56
82
  case "search":
57
- core = { label: "search", text: oneLine(row.call.query) };
83
+ core = { label: searchLabel(row.call.scope), text: searchText(row.call) };
58
84
  break;
59
85
  case "fileChange":
60
86
  core = fileChange(row.call);
@@ -1,6 +1,7 @@
1
1
  import type { AkumaInvocationResult } from "../commands/akuma-invoke.js";
2
2
  import type { ParsedCommand } from "../parse.js";
3
3
  import { type TextRenderContext } from "./terminal.js";
4
+ export declare function akumaRawAnswer(result: AkumaInvocationResult): string | undefined;
4
5
  export declare function renderAkumaText(command: ParsedCommand, result: AkumaInvocationResult, context?: TextRenderContext): string;
5
6
  export declare function akumaExitCode(result: AkumaInvocationResult): number;
6
7
  export declare function akumaJsonValue(command: ParsedCommand, result: AkumaInvocationResult): unknown;