@astrosheep/keiyaku 4.5.7 → 4.5.9

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 (244) hide show
  1. package/README.md +10 -0
  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/opencode.js +3 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +12 -11
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +33 -12
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +35 -96
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +28 -49
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +21 -15
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +148 -89
  12. package/build/src/akuma/abort.d.ts +2 -1
  13. package/build/src/akuma/abort.js +6 -23
  14. package/build/src/akuma/akuma-handle.js +4 -2
  15. package/build/src/akuma/akuma-observe.d.ts +2 -0
  16. package/build/src/akuma/akuma-observe.js +1 -0
  17. package/build/src/akuma/akuma-product.js +9 -7
  18. package/build/src/akuma/akuma.d.ts +392 -9
  19. package/build/src/akuma/akuma.js +31 -1
  20. package/build/src/akuma/allowed.d.ts +1 -1
  21. package/build/src/akuma/allowed.js +1 -0
  22. package/build/src/akuma/archetype.js +1 -1
  23. package/build/src/akuma/body.d.ts +8 -5
  24. package/build/src/akuma/body.js +12 -5
  25. package/build/src/akuma/call-request.d.ts +80 -0
  26. package/build/src/akuma/call-request.js +211 -0
  27. package/build/src/akuma/heart/facts.d.ts +16 -78
  28. package/build/src/akuma/heart/facts.js +11 -0
  29. package/build/src/akuma/heart/index.d.ts +3 -2
  30. package/build/src/akuma/heart/index.js +4 -1
  31. package/build/src/akuma/heart/request-authority.d.ts +5 -4
  32. package/build/src/akuma/heart/request-authority.js +20 -34
  33. package/build/src/akuma/heart/request-rows.js +12 -23
  34. package/build/src/akuma/heart/schema.d.ts +1 -1
  35. package/build/src/akuma/heart/schema.js +5 -13
  36. package/build/src/akuma/index.d.ts +1 -1
  37. package/build/src/akuma/index.js +1 -1
  38. package/build/src/akuma/projection-read.d.ts +1 -0
  39. package/build/src/akuma/projection-read.js +8 -1
  40. package/build/src/akuma/projection.d.ts +907 -137
  41. package/build/src/akuma/projection.js +193 -9
  42. package/build/src/akuma/provider.d.ts +30 -3
  43. package/build/src/akuma/provider.js +111 -0
  44. package/build/src/akuma/providers/acp/core.d.ts +2 -2
  45. package/build/src/akuma/providers/acp/core.js +13 -6
  46. package/build/src/akuma/providers/acp/index.js +5 -4
  47. package/build/src/akuma/providers/claude/events.d.ts +2 -2
  48. package/build/src/akuma/providers/claude/events.js +16 -3
  49. package/build/src/akuma/providers/claude/index.d.ts +3 -3
  50. package/build/src/akuma/providers/claude/index.js +16 -5
  51. package/build/src/akuma/providers/codex-app-server/events.d.ts +2 -2
  52. package/build/src/akuma/providers/codex-app-server/events.js +25 -4
  53. package/build/src/akuma/providers/codex-app-server/index.js +18 -6
  54. package/build/src/akuma/providers/grok-build/index.js +5 -4
  55. package/build/src/akuma/providers/opencode-sdk/index.js +66 -25
  56. package/build/src/akuma/providers/opencode-sdk/session.d.ts +3 -2
  57. package/build/src/akuma/providers/opencode-sdk/session.js +28 -11
  58. package/build/src/akuma/providers/pi/index.js +72 -58
  59. package/build/src/akuma/request-lifecycle.d.ts +4 -10
  60. package/build/src/akuma/request-lifecycle.js +7 -5
  61. package/build/src/akuma/request-rendezvous.d.ts +26 -0
  62. package/build/src/akuma/request-rendezvous.js +100 -0
  63. package/build/src/akuma/request-serve.d.ts +6 -66
  64. package/build/src/akuma/request-serve.js +83 -210
  65. package/build/src/akuma/request-wire.d.ts +109 -115
  66. package/build/src/akuma/request-wire.js +63 -318
  67. package/build/src/akuma/requests.d.ts +19 -47
  68. package/build/src/akuma/requests.js +51 -107
  69. package/build/src/akuma/turn-drive.d.ts +5 -3
  70. package/build/src/akuma/turn-drive.js +39 -11
  71. package/build/src/akuma-body.d.ts +7 -2
  72. package/build/src/akuma-body.js +68 -46
  73. package/build/src/body/amend.js +18 -19
  74. package/build/src/cli/accepted.d.ts +1 -1
  75. package/build/src/cli/accepted.js +2 -2
  76. package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
  77. package/build/src/cli/commands/akuma-invoke.js +17 -9
  78. package/build/src/cli/commands/akuma.js +8 -8
  79. package/build/src/cli/commands/contract-invoke.d.ts +3 -2
  80. package/build/src/cli/commands/contract-invoke.js +42 -30
  81. package/build/src/cli/commands/contract.d.ts +16 -20
  82. package/build/src/cli/commands/contract.js +58 -25
  83. package/build/src/cli/commands/install.d.ts +2 -1
  84. package/build/src/cli/commands/install.js +3 -2
  85. package/build/src/cli/commands/task-invoke.d.ts +3 -0
  86. package/build/src/cli/commands/task-invoke.js +23 -140
  87. package/build/src/cli/commands/task.js +54 -20
  88. package/build/src/cli/invoke.js +39 -25
  89. package/build/src/cli/main.js +2 -1
  90. package/build/src/cli/parse.d.ts +2 -2
  91. package/build/src/cli/parse.js +56 -27
  92. package/build/src/cli/render/akuma-activity.d.ts +3 -0
  93. package/build/src/cli/render/akuma-activity.js +45 -29
  94. package/build/src/cli/render/akuma-tool.d.ts +5 -1
  95. package/build/src/cli/render/akuma.js +4 -8
  96. package/build/src/cli/render/audit.js +1 -1
  97. package/build/src/cli/render/catalog.js +80 -21
  98. package/build/src/cli/render/contract-observation.d.ts +2 -0
  99. package/build/src/cli/render/contract-observation.js +11 -0
  100. package/build/src/cli/render/contract.js +35 -62
  101. package/build/src/cli/render/kanshi-akuma.d.ts +8 -0
  102. package/build/src/cli/render/kanshi-akuma.js +132 -0
  103. package/build/src/cli/render/kanshi.js +131 -213
  104. package/build/src/cli/render/receipt.d.ts +1 -2
  105. package/build/src/cli/render/receipt.js +76 -26
  106. package/build/src/cli/render/refusal.js +2 -10
  107. package/build/src/cli/render/region.js +5 -2
  108. package/build/src/cli/render/settings.d.ts +1 -1
  109. package/build/src/cli/render/settings.js +27 -8
  110. package/build/src/cli/render/task.js +22 -5
  111. package/build/src/cli/render/terminal.d.ts +32 -1
  112. package/build/src/cli/render/terminal.js +77 -1
  113. package/build/src/cli/result.d.ts +3 -3
  114. package/build/src/cli/runtime.js +4 -2
  115. package/build/src/cli/selectors.d.ts +2 -1
  116. package/build/src/cli/selectors.js +4 -3
  117. package/build/src/cli/square-edge.js +120 -36
  118. package/build/src/cli/usage.js +2 -1
  119. package/build/src/contract-guidance.d.ts +5 -0
  120. package/build/src/contract-guidance.js +121 -0
  121. package/build/src/contract-worktree.d.ts +0 -1
  122. package/build/src/contract-worktree.js +32 -83
  123. package/build/src/coordination/sqlite-transaction-lock.d.ts +1 -0
  124. package/build/src/coordination/sqlite-transaction-lock.js +5 -0
  125. package/build/src/core/facts/codec.d.ts +2 -0
  126. package/build/src/core/facts/codec.js +4 -0
  127. package/build/src/core/verbs/placement.d.ts +6 -1
  128. package/build/src/core/verbs/placement.js +5 -3
  129. package/build/src/dispatch/index.d.ts +0 -2
  130. package/build/src/dispatch/index.js +54 -55
  131. package/build/src/git/admission.js +2 -2
  132. package/build/src/git/hooks.d.ts +9 -15
  133. package/build/src/git/hooks.js +23 -317
  134. package/build/src/git/nuke.d.ts +2 -1
  135. package/build/src/git/nuke.js +39 -21
  136. package/build/src/git/private-state-seat.d.ts +12 -0
  137. package/build/src/git/private-state-seat.js +39 -0
  138. package/build/src/git/process.d.ts +6 -0
  139. package/build/src/git/process.js +26 -11
  140. package/build/src/git/read-observation.js +29 -20
  141. package/build/src/git/reconcile.d.ts +13 -1
  142. package/build/src/git/reconcile.js +70 -11
  143. package/build/src/git/ref-migration.d.ts +22 -0
  144. package/build/src/git/ref-migration.js +55 -0
  145. package/build/src/git/repository.d.ts +10 -6
  146. package/build/src/git/repository.js +16 -8
  147. package/build/src/git/target-placement.d.ts +1 -0
  148. package/build/src/git/target-placement.js +5 -0
  149. package/build/src/git/tender.d.ts +1 -0
  150. package/build/src/git/terminal-reconcile.d.ts +1 -1
  151. package/build/src/git/terminal-reconcile.js +22 -20
  152. package/build/src/git/workspace.d.ts +14 -0
  153. package/build/src/git/workspace.js +44 -0
  154. package/build/src/kanshi/index.d.ts +1 -1
  155. package/build/src/kanshi/read.js +16 -16
  156. package/build/src/kanshi/report.d.ts +2 -2
  157. package/build/src/library/address.d.ts +9 -3
  158. package/build/src/library/address.js +3 -2
  159. package/build/src/library/akuma-creation.d.ts +4 -3
  160. package/build/src/library/akuma-creation.js +19 -13
  161. package/build/src/library/audit.d.ts +14 -6
  162. package/build/src/library/audit.js +13 -23
  163. package/build/src/library/catalog.d.ts +3 -1
  164. package/build/src/library/catalog.js +20 -6
  165. package/build/src/library/composition.d.ts +385 -0
  166. package/build/src/library/composition.js +28 -0
  167. package/build/src/library/configuration.js +8 -2
  168. package/build/src/library/continuation.js +66 -30
  169. package/build/src/library/contract-bind.js +10 -2
  170. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +102 -0
  171. package/build/src/library/contract-forwarding-reconciliation-result.js +92 -0
  172. package/build/src/library/contract-forwarding-result.d.ts +4464 -0
  173. package/build/src/library/contract-forwarding-result.js +521 -0
  174. package/build/src/library/contract-forwarding.d.ts +71 -0
  175. package/build/src/library/contract-forwarding.js +114 -0
  176. package/build/src/library/contract-handle.d.ts +38 -0
  177. package/build/src/library/contract-handle.js +314 -0
  178. package/build/src/library/contract-operations.d.ts +214 -69
  179. package/build/src/library/contract-operations.js +189 -118
  180. package/build/src/library/contract-types.d.ts +7 -3
  181. package/build/src/library/contract.d.ts +21 -34
  182. package/build/src/library/contract.js +29 -287
  183. package/build/src/library/fleet-result.d.ts +1580 -0
  184. package/build/src/library/fleet-result.js +98 -0
  185. package/build/src/library/fleet.d.ts +112 -54
  186. package/build/src/library/fleet.js +211 -71
  187. package/build/src/library/input.d.ts +3 -1
  188. package/build/src/library/input.js +11 -1
  189. package/build/src/library/keiyaku.d.ts +388 -20
  190. package/build/src/library/keiyaku.js +13 -21
  191. package/build/src/library/mutation.d.ts +3 -3
  192. package/build/src/library/mutation.js +5 -9
  193. package/build/src/library/nuke.d.ts +1 -1
  194. package/build/src/library/nuke.js +4 -3
  195. package/build/src/library/reconcile.d.ts +4 -0
  196. package/build/src/library/reconcile.js +2 -0
  197. package/build/src/library/refusal.d.ts +0 -9
  198. package/build/src/library/refusal.js +0 -7
  199. package/build/src/protocol/amend.js +56 -50
  200. package/build/src/protocol/attempt.d.ts +2 -0
  201. package/build/src/protocol/attempt.js +8 -1
  202. package/build/src/protocol/completion.js +7 -0
  203. package/build/src/protocol/deliver.js +6 -2
  204. package/build/src/protocol/operations.d.ts +4 -1
  205. package/build/src/protocol/operations.js +5 -2
  206. package/build/src/protocol/placement.d.ts +1 -0
  207. package/build/src/protocol/placement.js +52 -38
  208. package/build/src/protocol/read/observation.d.ts +1 -4
  209. package/build/src/protocol/read/observation.js +2 -15
  210. package/build/src/protocol/reintegrate.js +62 -58
  211. package/build/src/protocol/review.js +5 -0
  212. package/build/src/protocol/run.js +17 -13
  213. package/build/src/runtime/proc/run.d.ts +9 -0
  214. package/build/src/runtime/proc/run.js +51 -4
  215. package/build/src/runtime/proc/termination.js +26 -22
  216. package/build/src/runtime/proc/windows-launch.exe +0 -0
  217. package/build/src/settlement/holder.d.ts +2 -1
  218. package/build/src/settlement/holder.js +15 -4
  219. package/build/src/settlement/settle.js +99 -33
  220. package/build/src/task/board.d.ts +68 -27
  221. package/build/src/task/board.js +31 -1
  222. package/build/src/task/catalog.d.ts +4 -0
  223. package/build/src/task/catalog.js +23 -0
  224. package/build/src/task/compose-language.js +33 -7
  225. package/build/src/task/compose-parser.d.ts +1 -1
  226. package/build/src/task/compose-parser.js +1 -1
  227. package/build/src/task/compose.js +2 -0
  228. package/build/src/task/index.d.ts +12 -4
  229. package/build/src/task/index.js +97 -16
  230. package/build/src/task/mutation-result.d.ts +923 -0
  231. package/build/src/task/mutation-result.js +140 -0
  232. package/build/src/task/mutation.d.ts +552 -28
  233. package/build/src/task/mutation.js +304 -97
  234. package/build/src/task/operations.d.ts +1 -4
  235. package/build/src/task/operations.js +0 -6
  236. package/build/src/task/public.d.ts +2 -0
  237. package/build/src/task/public.js +1 -0
  238. package/build/src/workspace-place.d.ts +7 -2
  239. package/build/src/workspace-place.js +34 -24
  240. package/build/src/world.d.ts +1 -0
  241. package/build/src/world.js +11 -0
  242. package/package.json +8 -6
  243. package/build/src/akuma/request-execution.d.ts +0 -8
  244. package/build/src/akuma/request-execution.js +0 -98
@@ -1,4 +1,5 @@
1
1
  import { CliUsageError, isBlankInput, usageLine } from "../usage.js";
2
+ import { parseTaskNamespaceSelector } from "../../task/catalog.js";
2
3
  import { parseTaskQueryExpression, validateTaskLimit, validateTaskParent, } from "./task-query.js";
3
4
  const COMMON = { json: "boolean" };
4
5
  const TASK_COMMAND_SPECS = {
@@ -18,39 +19,39 @@ const TASK_COMMAND_SPECS = {
18
19
  note: "value",
19
20
  actor: "value",
20
21
  },
21
- usage: `task add <TITLE> [--namespace <ns>] [--priority 0..3]
22
+ usage: `task add <TITLE> [--namespace <ns>] [--priority 0..3] [--json]
22
23
  [--state open|in_progress|on_hold|done|drop]
23
24
  [--note <text>] [--actor <actor>]
24
25
  [--needs <TaskId>]... [--parent <TaskId>]
25
26
  [--supersedes <TaskId>]... [--relates <TaskId>]...
26
27
  [--body <text>]
27
- task add [--namespace <ns>] [--actor <actor>] -`,
28
+ task add [--namespace <ns>] [--actor <actor>] [--json] -`,
28
29
  purpose: "Create one Task from flags or a canonical stdin document.",
29
30
  },
30
31
  show: {
31
32
  arity: [1, Number.POSITIVE_INFINITY],
32
33
  flags: COMMON,
33
- usage: "task show <TaskId>...",
34
+ usage: "task show <TaskId>... [--json]",
34
35
  purpose: "Read one or more Tasks and their relationships.",
35
36
  },
36
37
  ls: {
37
- arity: [0, 0],
38
+ arity: [0, 1],
38
39
  flags: { ...COMMON, closed: "boolean", all: "boolean", world: "boolean", limit: "value" },
39
- usage: "task ls [--closed | --all] [--world] [--limit <n>]",
40
+ usage: "task ls [<namespace-selector>] [--closed | --all] [--world] [--limit <n>] [--json]",
40
41
  purpose: "List Tasks in the selected scope.",
41
42
  details: "--world lists every namespace in the current Task world.",
42
43
  },
43
44
  ready: {
44
45
  arity: [0, 0],
45
46
  flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" },
46
- usage: "task ready [--world] [--parent <TaskId>] [--limit <n>]",
47
+ usage: "task ready [--world] [--parent <TaskId>] [--limit <n>] [--json]",
47
48
  purpose: "List open Tasks whose every need is terminal.",
48
49
  details: "--world lists every namespace in the current Task world.",
49
50
  },
50
51
  blocked: {
51
52
  arity: [0, 0],
52
53
  flags: { ...COMMON, world: "boolean", parent: "value", limit: "value" },
53
- usage: "task blocked [--world] [--parent <TaskId>] [--limit <n>]",
54
+ usage: "task blocked [--world] [--parent <TaskId>] [--limit <n>] [--json]",
54
55
  purpose: "List Tasks blocked by dependencies.",
55
56
  details: "--world lists every namespace in the current Task world.",
56
57
  },
@@ -58,7 +59,7 @@ task add [--namespace <ns>] [--actor <actor>] -`,
58
59
  arity: [0, 0],
59
60
  flags: { ...COMMON, where: "value", world: "boolean", sort: "value", limit: "value" },
60
61
  usage: `task query [--where <expression>] [--world]
61
- [--sort priority|created|updated|id] [--limit <n>]`,
62
+ [--sort priority|created|updated|id] [--limit <n>] [--json]`,
62
63
  purpose: "Query Task facts with a typed boolean expression.",
63
64
  details: [
64
65
  "fields: state priority title id parent under needs blocks ready blocked created updated",
@@ -72,13 +73,13 @@ task add [--namespace <ns>] [--actor <actor>] -`,
72
73
  tree: {
73
74
  arity: [1, 1],
74
75
  flags: COMMON,
75
- usage: "task tree <TaskId>",
76
+ usage: "task tree <TaskId> [--json]",
76
77
  purpose: "Read one Task parent decomposition tree.",
77
78
  },
78
79
  doctor: {
79
80
  arity: [0, 0],
80
81
  flags: COMMON,
81
- usage: "task doctor",
82
+ usage: "task doctor [--json]",
82
83
  purpose: "Inspect Task authority without repairing it.",
83
84
  },
84
85
  update: {
@@ -104,45 +105,60 @@ task add [--namespace <ns>] [--actor <actor>] -`,
104
105
  [--priority 0..3] [--needs <TaskId>]... [--drop-needs <TaskId>]...
105
106
  [--parent <TaskId> | --no-parent]
106
107
  [--supersedes <TaskId>]... [--drop-supersedes <TaskId>]...
107
- [--relates <TaskId>]... [--drop-relates <TaskId>]...`,
108
+ [--relates <TaskId>]... [--drop-relates <TaskId>]... [--json]`,
108
109
  purpose: "Apply one or more patches to a Task.",
109
110
  },
110
- start: { arity: [1, 1], flags: COMMON, usage: "task start <TaskId>", purpose: "Move one open Task into progress." },
111
- stop: { arity: [1, 1], flags: COMMON, usage: "task stop <TaskId>", purpose: "Return one in-progress Task to open." },
111
+ start: {
112
+ arity: [1, Number.POSITIVE_INFINITY],
113
+ flags: COMMON,
114
+ usage: "task start <TaskId>... [--json]",
115
+ purpose: "Move one or more open Tasks into progress.",
116
+ },
117
+ stop: {
118
+ arity: [1, 1],
119
+ flags: COMMON,
120
+ usage: "task stop <TaskId> [--json]",
121
+ purpose: "Return one in-progress Task to open.",
122
+ },
112
123
  hold: {
113
124
  arity: [1, Number.POSITIVE_INFINITY],
114
125
  flags: COMMON,
115
- usage: "task hold <TaskId>...",
126
+ usage: "task hold <TaskId>... [--json]",
116
127
  purpose: "Put one or more Tasks on hold.",
117
128
  },
118
- resume: { arity: [1, 1], flags: COMMON, usage: "task resume <TaskId>", purpose: "Return one held Task to open." },
129
+ resume: {
130
+ arity: [1, 1],
131
+ flags: COMMON,
132
+ usage: "task resume <TaskId> [--json]",
133
+ purpose: "Return one held Task to open.",
134
+ },
119
135
  done: {
120
136
  arity: [1, Number.POSITIVE_INFINITY],
121
137
  flags: { ...COMMON, note: "value" },
122
- usage: "task done <TaskId>... [--note <text>]",
138
+ usage: "task done <TaskId>... [--note <text>] [--json]",
123
139
  purpose: "Mark one or more Tasks done.",
124
140
  },
125
141
  drop: {
126
142
  arity: [1, Number.POSITIVE_INFINITY],
127
143
  flags: { ...COMMON, note: "value" },
128
- usage: "task drop <TaskId>... [--note <text>]",
144
+ usage: "task drop <TaskId>... [--note <text>] [--json]",
129
145
  purpose: "Drop one or more Tasks.",
130
146
  },
131
147
  context: {
132
148
  arity: [0, 1],
133
149
  flags: COMMON,
134
- usage: "task context [<namespace>]",
150
+ usage: "task context [<namespace>] [--json]",
135
151
  purpose: "Read or replace the directory Task context.",
136
152
  },
137
153
  compose: {
138
154
  arity: [0, 0],
139
155
  stdin: "compose",
140
156
  flags: { ...COMMON, actor: "value", plan: "boolean" },
141
- usage: "task compose [--actor <actor>] [--plan] -",
157
+ usage: "task compose [--actor <actor>] [--plan] [--json] -",
142
158
  purpose: "Plan or admit one explicit Task composition.",
143
159
  details: [
144
160
  "nodes: + <Title> creates; @task/<id> modifies a pre-existing Task",
145
- "properties: as = <alias>; pri = 0..3; parent = <ref>|empty",
161
+ "properties: as = <alias>; state = open|in_progress|on_hold|done|drop; pri = 0..3; parent = <ref>|empty",
146
162
  "relations: needs|supersedes|relates with =, +=, or -=",
147
163
  "references: @task/... is pre-existing; ^alias is new in this document",
148
164
  "body: body = clears; body <<TOKEN reads exact content to TOKEN",
@@ -255,6 +271,9 @@ function validateUpdate(scanned, fail) {
255
271
  function validateTaskReadFlags(action, flags, fail) {
256
272
  if (action === "ls" && flags.closed === true && flags.all === true)
257
273
  fail("--closed and --all are mutually exclusive");
274
+ if (action === "ls" && flags.world === true) {
275
+ // An explicit selector is checked below, after positional shape is known.
276
+ }
258
277
  if (typeof flags.limit === "string") {
259
278
  try {
260
279
  validateTaskLimit(flags.limit);
@@ -291,6 +310,21 @@ function validateTaskScan(action, scanned, fail) {
291
310
  fail("task add document input owns its creation fields");
292
311
  if (action === "compose" && stdin !== "compose")
293
312
  fail("task compose requires '-' input");
313
+ if (action === "ls" && positionals.length === 1) {
314
+ const selector = positionals[0];
315
+ if (selector !== "task/" && (!selector.startsWith("task/") || !selector.endsWith("/")))
316
+ fail(`invalid Task namespace selector: ${selector}`);
317
+ if (selector !== "task/") {
318
+ try {
319
+ parseTaskNamespaceSelector(selector);
320
+ }
321
+ catch (error) {
322
+ fail(error instanceof Error ? error.message : String(error));
323
+ }
324
+ }
325
+ if (flags.world === true)
326
+ fail("--world cannot be combined with an explicit Task namespace selector");
327
+ }
294
328
  validateTaskReadFlags(action, flags, fail);
295
329
  if (action === "update")
296
330
  validateUpdate(scanned, fail);
@@ -3,6 +3,8 @@ import { isParsedAkumaCommand } from "./commands/akuma.js";
3
3
  import { invokeContractMutation } from "./commands/contract-invoke.js";
4
4
  import { assertExplicitRepoUse, CliUsageError, renderCommandUsage, } from "./parse.js";
5
5
  import { isBlankInput } from "./usage.js";
6
+ import { AKUMA_REQUESTS_ENV } from "../akuma/provider.js";
7
+ import { bodyRequestExecution, executionChannel, localExecutionContext, } from "../akuma/requests.js";
6
8
  async function readStdin() {
7
9
  const chunks = [];
8
10
  for await (const chunk of process.stdin)
@@ -56,6 +58,20 @@ async function settingsAt(root, home) {
56
58
  const { settings } = await import("../settings.js");
57
59
  return settings({ ...(root === undefined ? {} : { root }), ...(home === undefined ? {} : { home }) });
58
60
  }
61
+ function executionForEnvironment(environment) {
62
+ return environment[AKUMA_REQUESTS_ENV] === undefined
63
+ ? localExecutionContext()
64
+ : bodyRequestExecution({ directory: environment[AKUMA_REQUESTS_ENV] });
65
+ }
66
+ async function contractSettings(command, execution, world, home) {
67
+ const forwarded = executionChannel(execution).kind === "body-request" &&
68
+ (command.command === "audit" || command.command === "deliver" || command.command === "review");
69
+ if (forwarded)
70
+ return {};
71
+ const configuration = await settingsAt(world ?? undefined, home);
72
+ const { worktreeHooksFrom, SettingsError } = await import("../library/configuration.js");
73
+ return { configuration, hooks: consumeSettings(() => worktreeHooksFrom({ settings: configuration }), SettingsError) };
74
+ }
59
75
  function consumeSettings(run, ErrorType) {
60
76
  try {
61
77
  return run();
@@ -76,6 +92,10 @@ function actorFromEdge(actor, environment) {
76
92
  }
77
93
  return resolved;
78
94
  }
95
+ function taskActor(command, runtime, environment) {
96
+ return (runtime.actor ??
97
+ actorFromEdge(typeof command.flags.actor === "string" ? command.flags.actor : undefined, environment));
98
+ }
79
99
  function gitPathFromEdge(environment) {
80
100
  const value = environment.KEIYAKU_GIT_PATH;
81
101
  if (value === undefined)
@@ -103,7 +123,7 @@ async function invokeAkumaFromEdge(parsed, input) {
103
123
  }
104
124
  const { invokeAkuma } = await import("./commands/akuma-invoke.js");
105
125
  const contract = parsed.command === "call" && parsed.contract !== undefined
106
- ? (await import("./selectors.js")).contractFromInput(repo, parsed.contract).contract
126
+ ? (await import("./selectors.js")).contractFromInput(repo, parsed.contract, input.execution).contract
107
127
  : undefined;
108
128
  return await invokeAkuma(parsed, {
109
129
  path,
@@ -113,6 +133,7 @@ async function invokeAkumaFromEdge(parsed, input) {
113
133
  ...(contract === undefined ? (repo === undefined ? {} : { repo }) : { contract }),
114
134
  environment: edge.environment,
115
135
  readStdin: edge.readStdin,
136
+ execution: input.execution,
116
137
  });
117
138
  }
118
139
  catch (error) {
@@ -276,18 +297,6 @@ async function invokeContractHistory(repo, contract) {
276
297
  throw error;
277
298
  }
278
299
  }
279
- async function invokeForwardedContractMutation(parsed, repo, edge, scope, establishWorld) {
280
- const { EMPTY_WORKTREE_HOOKS } = await import("../library/configuration.js");
281
- return invokeContractMutation({
282
- parsed,
283
- repo,
284
- edge,
285
- scope,
286
- hooks: EMPTY_WORKTREE_HOOKS,
287
- establishWorld,
288
- forwarded: true,
289
- });
290
- }
291
300
  async function resolveInvocationCoordinates(invocation, runtime) {
292
301
  const environment = runtime.environment ?? process.env, gitPath = gitPathFromEdge(environment);
293
302
  const { resolveCliCoordinates } = await import("./coordinates.js");
@@ -302,6 +311,7 @@ async function resolveInvocationCoordinates(invocation, runtime) {
302
311
  // eslint-disable-next-line complexity -- command dispatch keeps the CLI's existing boundary in one place.
303
312
  async function invokeParsed(invocation, runtime) {
304
313
  const environment = runtime.environment ?? process.env;
314
+ const execution = executionForEnvironment(environment);
305
315
  const coordinates = await resolveInvocationCoordinates(invocation, runtime);
306
316
  const { cwd, cwdSource, repo, world, candidateWorld, establishWorld, taskContext } = coordinates;
307
317
  const edge = { environment, readStdin: runtime.readStdin ?? readStdin };
@@ -313,8 +323,7 @@ async function invokeParsed(invocation, runtime) {
313
323
  if (parsed.command === "nuke")
314
324
  return await (await import("./commands/nuke.js")).invokeNuke(parsed, world);
315
325
  if (parsed.command === "task") {
316
- const actor = runtime.actor ??
317
- actorFromEdge(typeof parsed.flags.actor === "string" ? parsed.flags.actor : undefined, edge.environment);
326
+ const actor = taskActor(parsed, runtime, edge.environment);
318
327
  return await (await import("./commands/task-invoke.js")).invokeTaskFromEdge({
319
328
  parsed,
320
329
  world,
@@ -323,6 +332,7 @@ async function invokeParsed(invocation, runtime) {
323
332
  establish: coordinates.establishWorld,
324
333
  readStdin: edge.readStdin,
325
334
  actor,
335
+ execution,
326
336
  });
327
337
  }
328
338
  if (parsed.command === "history" && "contract" in parsed)
@@ -337,6 +347,7 @@ async function invokeParsed(invocation, runtime) {
337
347
  ...(repo === undefined ? {} : { repo }),
338
348
  ...(home === undefined ? {} : { home }),
339
349
  edge,
350
+ execution,
340
351
  });
341
352
  }
342
353
  if (parsed.command === "ls")
@@ -348,13 +359,7 @@ async function invokeParsed(invocation, runtime) {
348
359
  if (parsed.command === "region")
349
360
  return invokeRegion(parsed, world, repo);
350
361
  const scope = cwd;
351
- if ((parsed.command === "deliver" || parsed.command === "review") &&
352
- (await import("../akuma/requests.js")).injectedBodyRequests() !== null) {
353
- return invokeForwardedContractMutation(parsed, repo, edge, scope, establishWorld);
354
- }
355
- const configuration = await settingsAt(world ?? undefined, home);
356
- const { worktreeHooksFrom, SettingsError } = await import("../library/configuration.js");
357
- const hooks = consumeSettings(() => worktreeHooksFrom({ settings: configuration }), SettingsError);
362
+ const { configuration, hooks } = await contractSettings(parsed, execution, world, home);
358
363
  if (parsed.command === "show") {
359
364
  const selected = await selectContract(repo, parsed.contract, scope);
360
365
  return { kind: "guidance", contract: selected.id, guidance: await selected.contract.guidance() };
@@ -364,17 +369,26 @@ async function invokeParsed(invocation, runtime) {
364
369
  return {
365
370
  kind: "observation",
366
371
  command: "reconcile",
367
- report: await repo.reconcile({ hooks, retryHooks: parsed.retryHooks }),
372
+ report: await repo.reconcile({ ...(hooks === undefined ? {} : { hooks }), retryHooks: parsed.retryHooks }),
368
373
  };
369
374
  }
370
375
  const { contract } = await selectContract(repo, parsed.contract, scope);
371
376
  return {
372
377
  kind: "observation",
373
378
  command: "reconcile",
374
- ...(await contract.reconcile({ hooks, retryHooks: parsed.retryHooks })),
379
+ ...(await contract.reconcile({ ...(hooks === undefined ? {} : { hooks }), retryHooks: parsed.retryHooks })),
375
380
  };
376
381
  }
377
- return invokeContractMutation({ parsed, repo, edge, scope, configuration, hooks, establishWorld });
382
+ return invokeContractMutation({
383
+ parsed,
384
+ repo,
385
+ edge,
386
+ scope,
387
+ ...(configuration === undefined ? {} : { configuration }),
388
+ ...(hooks === undefined ? {} : { hooks }),
389
+ establishWorld,
390
+ execution,
391
+ });
378
392
  }
379
393
  function withResolvedTaskActor(command, runtime) {
380
394
  if (command.command !== "task" || (command.action !== "add" && command.action !== "compose"))
@@ -3,7 +3,8 @@ export async function main(argv = process.argv.slice(2)) {
3
3
  try {
4
4
  const parsed = parseArgv(argv);
5
5
  if ("help" in parsed) {
6
- const help = renderHelp(parsed.help);
6
+ const columns = process.stdout.isTTY === true && Number.isInteger(process.stdout.columns) ? process.stdout.columns : undefined;
7
+ const help = renderHelp(parsed.help, columns);
7
8
  process.stdout.write(help.endsWith("\n") ? help : `${help}\n`);
8
9
  return 0;
9
10
  }
@@ -5,9 +5,9 @@ import { type ContractCommand as Command, type ParsedAbandon, type ParsedAmend,
5
5
  export { CliUsageError } from "./usage.js";
6
6
  export { renderContractHelp } from "./commands/contract.js";
7
7
  export type { Command };
8
- export declare function renderRootHelp(): string;
8
+ export declare function renderRootHelp(columns?: number): string;
9
9
  export declare function renderCommandUsage(command: ParsedCommand): string;
10
- export declare function renderHelp(coordinate: CliHelpCoordinate): string;
10
+ export declare function renderHelp(coordinate: CliHelpCoordinate, columns?: number): string;
11
11
  export type ParsedCommand = ParsedBind | ParsedAmend | ParsedDeliver | ParsedReview | ParsedArc | ParsedAbandon | ParsedStatus | ParsedShow | ParsedLs | ParsedAudit | ParsedReconcile | ParsedNuke | ParsedSettings | ParsedRegion | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
12
12
  export type CliHelpCoordinate = Readonly<{
13
13
  kind: "root";
@@ -1,27 +1,53 @@
1
1
  import { isTaskAction, parseTaskCommand, renderTaskHelp, renderTaskUsage, } from "./commands/task.js";
2
2
  import { isAkumaAction, parseAkumaCommand, renderAkumaHelp, renderAkumaRootRows, renderAkumaUsage, } from "./commands/akuma.js";
3
- import { INSTALL_USAGE, parseInstallCommand, renderInstallHelp, } from "./commands/install.js";
3
+ import { INSTALL_ROOT_PURPOSE, parseInstallCommand, renderInstallHelp, } from "./commands/install.js";
4
4
  import { CONTRACT_COMMAND_SPECS, parseContractCommand, renderContractHelp as renderContractHelpForOwner, renderContractUsage, } from "./commands/contract.js";
5
+ import { renderTextBlock } from "./render/terminal.js";
5
6
  import { CliUsageError, isBlankInput } from "./usage.js";
6
7
  export { CliUsageError } from "./usage.js";
7
8
  export { renderContractHelp } from "./commands/contract.js";
8
- const ROOT_USAGE = "usage: keiyaku [-C <path>] [--repo <path>] <command> [<contract>|@<contract>] [--flag ...] [-]";
9
- export function renderRootHelp() {
10
- return [
9
+ const ROOT_USAGE = [
10
+ "usage: keiyaku <command> [options]",
11
+ " keiyaku <command> --help shows that command's complete usage",
12
+ ].join("\n");
13
+ export function renderRootHelp(columns) {
14
+ return renderHelpText([
15
+ "keiyaku — Contract, Task, and Akuma control for one repository",
16
+ "",
11
17
  ROOT_USAGE,
12
18
  "",
13
- "global options:",
14
- " -C, --cwd <path> Set the invocation working directory.",
15
- " --repo <path> Select the Git repository coordinate.",
19
+ "Contract — standing acceptance",
20
+ ...Object.entries(CONTRACT_COMMAND_SPECS)
21
+ .filter(([command]) => command !== "settings")
22
+ .map(([command, spec]) => ` ${command.padEnd(10)} ${spec.purpose}`),
23
+ "",
24
+ "Task — plan memory",
25
+ " task Task coordination; see `keiyaku task --help`.",
16
26
  "",
17
- "commands:",
18
- ...Object.values(CONTRACT_COMMAND_SPECS).flatMap((spec) => [` ${spec.usage}`, ` ${spec.purpose}`]),
19
- ` ${INSTALL_USAGE}`,
20
- " Install the Keiyaku skills into an agent harness.",
21
- " task ...",
22
- " Task coordination; see `keiyaku task --help`.",
27
+ "Akuma — invoke capability",
23
28
  ...renderAkumaRootRows(),
24
- ].join("\n");
29
+ "",
30
+ "Workspace",
31
+ ` install ${INSTALL_ROOT_PURPOSE}`,
32
+ ` settings ${CONTRACT_COMMAND_SPECS.settings.purpose}`,
33
+ "",
34
+ "Global options:",
35
+ " -C, --cwd <path> Set the invocation working directory.",
36
+ " --repo <path> Select the Git repository coordinate.",
37
+ ].join("\n"), columns);
38
+ }
39
+ function renderHelpText(help, columns) {
40
+ if (columns === undefined || !Number.isFinite(columns) || columns <= 0)
41
+ return help;
42
+ return help
43
+ .split("\n")
44
+ .flatMap((line) => {
45
+ if (line.trim().length === 0)
46
+ return [line];
47
+ const indent = line.match(/^\s*/u)?.[0] ?? "";
48
+ return renderTextBlock(line.slice(indent.length), indent, columns);
49
+ })
50
+ .join("\n");
25
51
  }
26
52
  function contractUsage(command) {
27
53
  return renderContractUsage(command);
@@ -35,19 +61,22 @@ export function renderCommandUsage(command) {
35
61
  return renderAkumaUsage(command.command);
36
62
  return contractUsage(command.command);
37
63
  }
38
- export function renderHelp(coordinate) {
39
- switch (coordinate.kind) {
40
- case "root":
41
- return renderRootHelp();
42
- case "contract":
43
- return renderContractHelpForOwner(coordinate.command);
44
- case "task":
45
- return renderTaskHelp(coordinate.action);
46
- case "install":
47
- return renderInstallHelp();
48
- case "akuma":
49
- return renderAkumaHelp(coordinate.action);
50
- }
64
+ export function renderHelp(coordinate, columns) {
65
+ const help = (() => {
66
+ switch (coordinate.kind) {
67
+ case "root":
68
+ return renderRootHelp();
69
+ case "contract":
70
+ return renderContractHelpForOwner(coordinate.command);
71
+ case "task":
72
+ return renderTaskHelp(coordinate.action);
73
+ case "install":
74
+ return renderInstallHelp();
75
+ case "akuma":
76
+ return renderAkumaHelp(coordinate.action);
77
+ }
78
+ })();
79
+ return renderHelpText(help, columns);
51
80
  }
52
81
  export function commandRepoPolicy(command) {
53
82
  switch (command.command) {
@@ -1,3 +1,4 @@
1
+ import type { KillEvidence } from "../../akuma/index.js";
1
2
  import type { AkumaObservation, AkumaObservationStage, CreatedTaskObservation, DispatchAssociation } from "../../index.js";
2
3
  import type { AkumaInvocationResult } from "../commands/akuma-invoke.js";
3
4
  import type { ParsedCommand } from "../parse.js";
@@ -15,6 +16,8 @@ type SnapshotCoreOptions = Readonly<{
15
16
  facts?: readonly string[];
16
17
  }>;
17
18
  export declare function snapshotText(view: SnapshotView, context: TextRenderContext, options?: SnapshotCoreOptions): string;
19
+ export declare function killObservationText(id: string, evidence: KillEvidence, observation: AkumaObservationStage, context: TextRenderContext, alias?: string): string;
20
+ export declare function killResultText(id: string, evidence: KillEvidence, alias?: string): string;
18
21
  export declare function mutationObservationStageText(id: string, observation: AkumaObservationStage, context: TextRenderContext, options?: SnapshotCoreOptions & Readonly<{
19
22
  showLife?: boolean;
20
23
  }>): string;
@@ -1,4 +1,4 @@
1
- import { defaultWaitComplete } from "../../akuma/index.js";
1
+ import { parseAkumaStatus } from "../../akuma/akuma.js";
2
2
  import { toolRepr } from "./akuma-tool.js";
3
3
  import { displayColumns, renderBoundedTextBlock, safeText, truncateMiddleDisplayText, } from "./terminal.js";
4
4
  export const DEFAULT_CONTEXT = { columns: 80, color: false };
@@ -37,11 +37,6 @@ function lifeLabel(life) {
37
37
  return "× killed";
38
38
  return `? ${life}`;
39
39
  }
40
- function pendingWithoutLiveBody(status) {
41
- if (status.life === "running")
42
- return 0;
43
- return status.timeline.entries.reduce((count, entry) => count + (entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending" ? 1 : 0), 0);
44
- }
45
40
  function clock(at) {
46
41
  const date = new Date(at);
47
42
  return Number.isFinite(date.getTime())
@@ -58,16 +53,20 @@ function label(row) {
58
53
  if (row.kind === "call")
59
54
  return "call";
60
55
  if (row.kind === "tell")
61
- return "tell";
56
+ return row.state === "told" ? "told" : "tell";
62
57
  if (row.kind === "outcome")
63
58
  return row.outcome.kind === "answered" ? "say" : "error";
64
59
  if (row.kind === "turn")
65
60
  return "call";
61
+ if (row.kind !== "tool")
62
+ return row.kind;
66
63
  return toolRepr(row).label;
67
64
  }
68
65
  function mark(row) {
69
66
  if (row.kind === "outcome")
70
67
  return row.outcome.kind === "answered" ? "✓" : "!";
68
+ if (row.kind === "tell" && row.state === "told")
69
+ return "✓";
71
70
  if (row.kind === "tell" && row.state === "pending")
72
71
  return "⧗";
73
72
  if (row.kind === "tool") {
@@ -96,6 +95,8 @@ function rowText(row) {
96
95
  : { text: row.outcome.diagnostic, lines: 2 };
97
96
  if (row.kind === "turn")
98
97
  return { text: "", lines: 1 };
98
+ if (row.kind !== "tool")
99
+ return { text: "", lines: 1 };
99
100
  const repr = toolRepr(row);
100
101
  return {
101
102
  text: repr.text,
@@ -261,15 +262,9 @@ function snapshotCore(view, context, options) {
261
262
  ...contractFacts(view.contract),
262
263
  ...(options.facts ?? []),
263
264
  ];
264
- const pending = pendingWithoutLiveBody(view.status);
265
265
  return {
266
266
  activity,
267
- lines: [
268
- ...snapshotHeading(view.status.id, options.alias, view.contract),
269
- ...facts,
270
- ...activity,
271
- ...(pending === 0 ? [] : [`pending ${pending} tells · no live body`]),
272
- ],
267
+ lines: [...snapshotHeading(view.status.id, options.alias, view.contract), ...facts, ...activity],
273
268
  };
274
269
  }
275
270
  export function snapshotText(view, context, options = {}) {
@@ -288,13 +283,35 @@ function mutationSnapshotText(view, context, options = {}) {
288
283
  const core = snapshotCore(view, context, options);
289
284
  return [...core.lines, ...(options.showLife === false ? [] : ["", lifeLabel(view.status.life)])].join("\n");
290
285
  }
286
+ function killResultLabel(evidence) {
287
+ if (evidence === "killed")
288
+ return "✓ killed";
289
+ if (evidence === "already-killed")
290
+ return "✓ already killed";
291
+ if (evidence === "already-stopped")
292
+ return "✓ already stopped";
293
+ return `! not killed · ${evidence}`;
294
+ }
295
+ function latestKillActivity(snapshot, context) {
296
+ const rows = snapshot.entries.flatMap((entry) => (entry.kind === "row" ? [entry.row] : []));
297
+ const latest = rows.reduce((selected, row) => (selected === undefined || row.sequence > selected.sequence ? row : selected), undefined);
298
+ return latest === undefined ? [] : groupedRows([latest], context);
299
+ }
300
+ export function killObservationText(id, evidence, observation, context, alias) {
301
+ const heading = snapshotHeading(id, alias, observation.kind === "observed" ? observation.contract : undefined);
302
+ const activity = observation.kind === "observed" ? latestKillActivity(observation.status.timeline, context) : [];
303
+ return [...heading, ...activity, "", killResultLabel(evidence)].join("\n");
304
+ }
305
+ export function killResultText(id, evidence, alias) {
306
+ return [...snapshotHeading(id, alias, undefined), "", killResultLabel(evidence)].join("\n");
307
+ }
291
308
  export function mutationObservationStageText(id, observation, context, options = {}) {
292
309
  if (observation.kind === "unobserved")
293
310
  return unobservedText(id, observation.diagnostic);
294
311
  return mutationSnapshotText(observation, context, options);
295
312
  }
296
313
  export function statusAnswer(view) {
297
- if (!defaultWaitComplete(view.status))
314
+ if (!waitComplete(view.status))
298
315
  return undefined;
299
316
  if (view.status.life !== "asleep")
300
317
  return undefined;
@@ -305,6 +322,10 @@ export function statusAnswer(view) {
305
322
  return undefined;
306
323
  return timeline.outcome.outcome.answer;
307
324
  }
325
+ function waitComplete(status) {
326
+ return (status.life !== "running" &&
327
+ !status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
328
+ }
308
329
  function answerCallFailed(result) {
309
330
  return result.dispatch.kind === "failed" || result.alias.kind === "failed" || result.readonly?.enforcement === "none";
310
331
  }
@@ -312,7 +333,7 @@ export function akumaRawAnswer(result) {
312
333
  if (result.action === "call") {
313
334
  if (answerCallFailed(result.result) || result.result.observation.kind !== "observed")
314
335
  return undefined;
315
- return statusAnswer({ status: result.result.observation.status });
336
+ return statusAnswer({ status: parseAkumaStatus(result.result.observation.status) });
316
337
  }
317
338
  if (result.action === "wait" && result.result.observations.length === 1)
318
339
  return statusAnswer(result.result.observations[0]);
@@ -326,7 +347,7 @@ export function akumaRawAnswer(result) {
326
347
  export function waitText(result, context) {
327
348
  const alias = result.alias;
328
349
  const total = result.result.observations.length + result.result.unobserved.length;
329
- const done = result.result.observations.filter((observation) => defaultWaitComplete(observation.status)).length;
350
+ const done = result.result.observations.filter((observation) => waitComplete(observation.status)).length;
330
351
  const blocks = [
331
352
  ...result.result.observations.map((observation) => {
332
353
  const answer = statusAnswer(observation);
@@ -358,16 +379,11 @@ export function historyText(command, result, context) {
358
379
  }
359
380
  export function tellText(result, context) {
360
381
  const wake = result.result.tell.wake;
361
- const facts = wake.kind === "failed"
362
- ? [
363
- `! wake failed · ${safeText(wake.diagnostic)}${wake.child === undefined ? "" : ` · log ${wake.child.log.path} ${wake.child.log.from}..${wake.child.log.to}`}`,
364
- ]
365
- : wake.kind === "pursuing"
366
- ? []
367
- : [`wake ${wake.kind}`];
368
- return mutationObservationStageText(result.result.akuma, result.result.observation, context, {
369
- ...(result.alias === undefined ? {} : { alias: result.alias }),
370
- facts,
371
- showLife: false,
372
- });
382
+ const target = identity(result.result.akuma, result.alias);
383
+ const row = groupedRows([result.result.tell.row], context).join("\n");
384
+ if (wake.kind === "failed") {
385
+ const child = "child" in wake ? wake.child : undefined;
386
+ return `${target}\n${SNAPSHOT_RULER}\n${row}\n! tell delivery failed · ${safeText(wake.diagnostic)}${child === undefined ? "" : ` · log ${child.log.path} ${child.log.from}..${child.log.to}`}`;
387
+ }
388
+ return `${target}\n${SNAPSHOT_RULER}\n${row}`;
373
389
  }
@@ -1,5 +1,9 @@
1
1
  import type { ActivityRow, SnapshotRow } from "../../akuma/index.js";
2
- type ToolRow = Extract<ActivityRow | SnapshotRow, {
2
+ import type { AkumaObservation } from "../../index.js";
3
+ type FleetTimelineRow = Extract<AkumaObservation["status"]["timeline"]["entries"][number], {
4
+ kind: "row";
5
+ }>["row"];
6
+ type ToolRow = Extract<ActivityRow | SnapshotRow | FleetTimelineRow, {
3
7
  kind: "tool";
4
8
  }>;
5
9
  export type ToolRepr = Readonly<{