@astrosheep/keiyaku 4.1.0 → 4.1.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 (278) hide show
  1. package/README.md +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
  5. package/build/src/akuma/akuma-errors.d.ts +6 -0
  6. package/build/src/akuma/akuma-errors.js +9 -0
  7. package/build/src/akuma/akuma-handle.d.ts +39 -0
  8. package/build/src/akuma/akuma-handle.js +263 -0
  9. package/build/src/akuma/akuma-observe.d.ts +19 -0
  10. package/build/src/akuma/akuma-observe.js +74 -0
  11. package/build/src/akuma/akuma-product-symbols.d.ts +1 -0
  12. package/build/src/akuma/akuma-product-symbols.js +1 -0
  13. package/build/src/akuma/akuma-product.d.ts +18 -0
  14. package/build/src/akuma/akuma-product.js +154 -0
  15. package/build/src/akuma/akuma.d.ts +37 -81
  16. package/build/src/akuma/akuma.js +39 -447
  17. package/build/src/akuma/allowed.d.ts +1 -0
  18. package/build/src/akuma/allowed.js +6 -0
  19. package/build/src/akuma/archetype.js +8 -5
  20. package/build/src/akuma/body-supervisor.d.ts +26 -0
  21. package/build/src/akuma/body-supervisor.js +89 -0
  22. package/build/src/akuma/body.d.ts +45 -4
  23. package/build/src/akuma/body.js +145 -35
  24. package/build/src/akuma/coordinate.js +17 -7
  25. package/build/src/akuma/heart/facts.js +1 -1
  26. package/build/src/akuma/heart/index.d.ts +1 -1
  27. package/build/src/akuma/heart/index.js +2 -4
  28. package/build/src/akuma/heart/request-authority.js +4 -4
  29. package/build/src/akuma/heart/request-rows.js +27 -16
  30. package/build/src/akuma/heart/rows.js +79 -41
  31. package/build/src/akuma/heart/soul.js +1 -1
  32. package/build/src/akuma/heart/storage.d.ts +1 -0
  33. package/build/src/akuma/heart/storage.js +76 -11
  34. package/build/src/akuma/heart/tells.js +35 -18
  35. package/build/src/akuma/heart/timeline.js +19 -11
  36. package/build/src/akuma/identity.d.ts +1 -0
  37. package/build/src/akuma/identity.js +1 -0
  38. package/build/src/akuma/index.d.ts +3 -3
  39. package/build/src/akuma/index.js +1 -1
  40. package/build/src/akuma/nuke.js +106 -14
  41. package/build/src/akuma/projection-read.d.ts +17 -0
  42. package/build/src/akuma/projection-read.js +135 -0
  43. package/build/src/akuma/projection.d.ts +1 -16
  44. package/build/src/akuma/projection.js +77 -154
  45. package/build/src/akuma/provider-recipe.js +11 -5
  46. package/build/src/akuma/provider.js +105 -62
  47. package/build/src/akuma/providers/acp/config.js +5 -6
  48. package/build/src/akuma/providers/acp/core.js +17 -10
  49. package/build/src/akuma/providers/acp/events.js +38 -29
  50. package/build/src/akuma/providers/acp/index.js +13 -9
  51. package/build/src/akuma/providers/claude/events.js +8 -12
  52. package/build/src/akuma/providers/claude/index.d.ts +1 -0
  53. package/build/src/akuma/providers/claude/index.js +55 -26
  54. package/build/src/akuma/providers/claude/input.js +6 -2
  55. package/build/src/akuma/providers/codex-app-server/events.js +61 -36
  56. package/build/src/akuma/providers/codex-app-server/index.js +25 -13
  57. package/build/src/akuma/providers/grok-build/index.js +22 -25
  58. package/build/src/akuma/providers/index.js +2 -18
  59. package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
  60. package/build/src/akuma/providers/opencode-sdk/index.js +26 -17
  61. package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
  62. package/build/src/akuma/providers/pi/events.js +26 -19
  63. package/build/src/akuma/providers/pi/index.js +58 -40
  64. package/build/src/akuma/publication.js +9 -9
  65. package/build/src/akuma/request-execution.d.ts +6 -0
  66. package/build/src/akuma/request-execution.js +86 -0
  67. package/build/src/akuma/request-serve.d.ts +12 -1
  68. package/build/src/akuma/request-serve.js +19 -122
  69. package/build/src/akuma/request-wire.d.ts +2 -2
  70. package/build/src/akuma/request-wire.js +75 -102
  71. package/build/src/akuma/requests.js +2 -2
  72. package/build/src/akuma/{body-turn.d.ts → turn-drive.d.ts} +2 -25
  73. package/build/src/akuma/{body-turn.js → turn-drive.js} +20 -103
  74. package/build/src/akuma-body.js +6 -5
  75. package/build/src/body/amend.d.ts +4 -1
  76. package/build/src/body/amend.js +14 -6
  77. package/build/src/body/decode.js +2 -4
  78. package/build/src/body/envelope.js +2 -4
  79. package/build/src/body/region.d.ts +1 -2
  80. package/build/src/body/region.js +2 -70
  81. package/build/src/body/render.js +17 -12
  82. package/build/src/body/shape.js +1 -7
  83. package/build/src/cli/accepted.d.ts +1 -1
  84. package/build/src/cli/accepted.js +8 -1
  85. package/build/src/cli/commands/akuma-invoke.js +18 -6
  86. package/build/src/cli/commands/akuma.d.ts +0 -6
  87. package/build/src/cli/commands/akuma.js +11 -24
  88. package/build/src/cli/commands/amend.d.ts +2 -2
  89. package/build/src/cli/commands/amend.js +2 -4
  90. package/build/src/cli/commands/bind.d.ts +4 -4
  91. package/build/src/cli/commands/bind.js +16 -6
  92. package/build/src/cli/commands/contract-invoke.d.ts +25 -0
  93. package/build/src/cli/commands/contract-invoke.js +193 -0
  94. package/build/src/cli/commands/contract.d.ts +109 -10
  95. package/build/src/cli/commands/contract.js +339 -16
  96. package/build/src/cli/commands/install.d.ts +1 -1
  97. package/build/src/cli/commands/install.js +23 -15
  98. package/build/src/cli/commands/task-invoke.js +187 -67
  99. package/build/src/cli/commands/task-query.js +48 -24
  100. package/build/src/cli/commands/task.js +150 -38
  101. package/build/src/cli/coordinates.js +2 -4
  102. package/build/src/cli/invoke.js +92 -208
  103. package/build/src/cli/main.js +4 -2
  104. package/build/src/cli/parse.d.ts +3 -90
  105. package/build/src/cli/parse.js +27 -233
  106. package/build/src/cli/render/akuma-activity.d.ts +38 -0
  107. package/build/src/cli/render/akuma-activity.js +362 -0
  108. package/build/src/cli/render/akuma-tool-command.js +6 -7
  109. package/build/src/cli/render/akuma-tool.js +10 -8
  110. package/build/src/cli/render/akuma.d.ts +1 -1
  111. package/build/src/cli/render/akuma.js +61 -353
  112. package/build/src/cli/render/audit.js +5 -15
  113. package/build/src/cli/render/board.d.ts +1 -0
  114. package/build/src/cli/render/board.js +17 -0
  115. package/build/src/cli/render/catalog.js +81 -8
  116. package/build/src/cli/render/contract-history.d.ts +2 -0
  117. package/build/src/cli/render/contract-history.js +83 -0
  118. package/build/src/cli/render/contract-observation.d.ts +10 -0
  119. package/build/src/cli/render/contract-observation.js +58 -0
  120. package/build/src/cli/render/contract.d.ts +1 -2
  121. package/build/src/cli/render/contract.js +41 -142
  122. package/build/src/cli/render/kanshi.js +239 -215
  123. package/build/src/cli/render/receipt.js +2 -9
  124. package/build/src/cli/render/refusal.js +10 -15
  125. package/build/src/cli/render/region.js +22 -6
  126. package/build/src/cli/render/settings.js +4 -4
  127. package/build/src/cli/render/task.js +34 -14
  128. package/build/src/cli/render/terminal.js +16 -5
  129. package/build/src/cli/result.d.ts +3 -3
  130. package/build/src/cli/runtime.d.ts +6 -1
  131. package/build/src/cli/runtime.js +84 -63
  132. package/build/src/cli/selectors.js +2 -4
  133. package/build/src/cli/usage.js +6 -5
  134. package/build/src/contract-worktree.d.ts +1 -23
  135. package/build/src/contract-worktree.js +79 -155
  136. package/build/src/coordination/durable-file.js +7 -3
  137. package/build/src/coordination/sqlite-transaction-lock.js +29 -12
  138. package/build/src/core/facts/codec.js +7 -3
  139. package/build/src/core/facts/types.d.ts +1 -1
  140. package/build/src/core/subject.js +16 -9
  141. package/build/src/core/verbs/abandon.d.ts +1 -1
  142. package/build/src/core/verbs/abandon.js +1 -1
  143. package/build/src/core/verbs/amend.d.ts +1 -1
  144. package/build/src/core/verbs/amend.js +7 -7
  145. package/build/src/core/verbs/attestation.js +4 -1
  146. package/build/src/core/verbs/bind.d.ts +1 -1
  147. package/build/src/core/verbs/bind.js +1 -1
  148. package/build/src/core/verbs/placement.d.ts +1 -1
  149. package/build/src/core/verbs/placement.js +10 -8
  150. package/build/src/dispatch/index.js +8 -6
  151. package/build/src/duration.js +5 -1
  152. package/build/src/git/admission.js +5 -3
  153. package/build/src/git/hooks.d.ts +8 -0
  154. package/build/src/git/hooks.js +63 -14
  155. package/build/src/git/identity.js +1 -4
  156. package/build/src/git/integration.d.ts +2 -3
  157. package/build/src/git/integration.js +32 -39
  158. package/build/src/git/nuke.d.ts +1 -1
  159. package/build/src/git/nuke.js +110 -57
  160. package/build/src/git/observe.d.ts +13 -1
  161. package/build/src/git/observe.js +51 -44
  162. package/build/src/git/process.js +4 -2
  163. package/build/src/git/read-observation.js +10 -8
  164. package/build/src/git/reconcile.d.ts +22 -2
  165. package/build/src/git/reconcile.js +38 -274
  166. package/build/src/git/repository.d.ts +2 -0
  167. package/build/src/git/repository.js +13 -22
  168. package/build/src/git/scratch.d.ts +8 -5
  169. package/build/src/git/scratch.js +29 -2
  170. package/build/src/git/target-placement.d.ts +9 -10
  171. package/build/src/git/target-placement.js +59 -62
  172. package/build/src/git/tender.js +13 -46
  173. package/build/src/git/terminal-reconcile.d.ts +21 -0
  174. package/build/src/git/terminal-reconcile.js +278 -0
  175. package/build/src/git/terminal-seal.js +15 -12
  176. package/build/src/git/tree.js +5 -2
  177. package/build/src/git/workspace.d.ts +24 -2
  178. package/build/src/git/workspace.js +120 -16
  179. package/build/src/identity/coordinates.js +3 -1
  180. package/build/src/identity/selector.js +6 -3
  181. package/build/src/kanshi/fleet.d.ts +6 -0
  182. package/build/src/kanshi/fleet.js +27 -0
  183. package/build/src/kanshi/index.d.ts +1 -1
  184. package/build/src/kanshi/read.js +60 -48
  185. package/build/src/kanshi/report.d.ts +11 -23
  186. package/build/src/kanshi/select.js +25 -24
  187. package/build/src/library/address.d.ts +2 -1
  188. package/build/src/library/address.js +7 -8
  189. package/build/src/library/akuma-creation.js +20 -12
  190. package/build/src/library/audit.d.ts +0 -1
  191. package/build/src/library/audit.js +1 -2
  192. package/build/src/library/bind.d.ts +53 -5
  193. package/build/src/library/bind.js +98 -22
  194. package/build/src/library/catalog.d.ts +1 -0
  195. package/build/src/library/catalog.js +6 -3
  196. package/build/src/library/configuration.js +3 -1
  197. package/build/src/library/continuation.d.ts +15 -4
  198. package/build/src/library/continuation.js +24 -16
  199. package/build/src/library/contract-bind.d.ts +26 -0
  200. package/build/src/library/contract-bind.js +106 -0
  201. package/build/src/library/contract-operations.d.ts +77 -0
  202. package/build/src/library/contract-operations.js +130 -0
  203. package/build/src/library/contract-types.d.ts +95 -0
  204. package/build/src/library/contract-types.js +1 -0
  205. package/build/src/library/contract.d.ts +19 -154
  206. package/build/src/library/contract.js +46 -261
  207. package/build/src/library/fleet.d.ts +1 -1
  208. package/build/src/library/fleet.js +19 -11
  209. package/build/src/library/input.d.ts +2 -0
  210. package/build/src/library/input.js +14 -0
  211. package/build/src/library/keiyaku.d.ts +8 -7
  212. package/build/src/library/keiyaku.js +3 -3
  213. package/build/src/library/nuke.js +14 -5
  214. package/build/src/library/reconcile.d.ts +9 -4
  215. package/build/src/library/reconcile.js +30 -24
  216. package/build/src/library/refusal.d.ts +13 -5
  217. package/build/src/library/refusal.js +7 -0
  218. package/build/src/library/region.d.ts +8 -7
  219. package/build/src/library/region.js +31 -11
  220. package/build/src/library/repo.js +2 -2
  221. package/build/src/markdown/lex.js +9 -2
  222. package/build/src/markdown/parse.js +11 -7
  223. package/build/src/markdown/query.js +4 -2
  224. package/build/src/protocol/amend.js +3 -1
  225. package/build/src/protocol/attempt.d.ts +7 -3
  226. package/build/src/protocol/attempt.js +9 -5
  227. package/build/src/protocol/audit.d.ts +1 -1
  228. package/build/src/protocol/audit.js +4 -14
  229. package/build/src/protocol/bind.d.ts +19 -6
  230. package/build/src/protocol/bind.js +28 -13
  231. package/build/src/protocol/completion.d.ts +0 -1
  232. package/build/src/protocol/completion.js +1 -3
  233. package/build/src/protocol/deliver.d.ts +1 -3
  234. package/build/src/protocol/deliver.js +15 -39
  235. package/build/src/protocol/intent.d.ts +1 -0
  236. package/build/src/protocol/intent.js +9 -7
  237. package/build/src/protocol/operations.d.ts +3 -7
  238. package/build/src/protocol/operations.js +5 -3
  239. package/build/src/protocol/placement.d.ts +0 -1
  240. package/build/src/protocol/placement.js +6 -6
  241. package/build/src/protocol/read/observation.d.ts +11 -0
  242. package/build/src/protocol/read/observation.js +37 -0
  243. package/build/src/protocol/read/status.d.ts +23 -12
  244. package/build/src/protocol/read/status.js +90 -72
  245. package/build/src/protocol/reconcile.d.ts +1 -0
  246. package/build/src/protocol/reconcile.js +2 -3
  247. package/build/src/protocol/reintegrate.js +1 -1
  248. package/build/src/protocol/review.d.ts +0 -1
  249. package/build/src/protocol/review.js +15 -22
  250. package/build/src/protocol/run.d.ts +1 -0
  251. package/build/src/protocol/run.js +4 -5
  252. package/build/src/runtime/proc/launch.d.ts +33 -0
  253. package/build/src/runtime/proc/launch.js +98 -0
  254. package/build/src/runtime/proc/line-rpc.js +9 -3
  255. package/build/src/runtime/proc/run.d.ts +12 -6
  256. package/build/src/runtime/proc/run.js +78 -21
  257. package/build/src/runtime/proc/stdio.js +7 -10
  258. package/build/src/settings.js +6 -2
  259. package/build/src/settlement/holder.js +13 -10
  260. package/build/src/settlement/settle.js +39 -6
  261. package/build/src/task/board.js +12 -6
  262. package/build/src/task/compose.js +85 -22
  263. package/build/src/task/context.js +21 -8
  264. package/build/src/task/document.js +46 -10
  265. package/build/src/task/identity.js +5 -2
  266. package/build/src/task/index.d.ts +0 -1
  267. package/build/src/task/index.js +119 -34
  268. package/build/src/task/input.js +29 -7
  269. package/build/src/task/mutation.js +61 -19
  270. package/build/src/task/operations.d.ts +6 -1
  271. package/build/src/task/operations.js +83 -29
  272. package/build/src/task/query.js +55 -26
  273. package/build/src/task/store.d.ts +3 -1
  274. package/build/src/task/store.js +81 -17
  275. package/build/src/verification/execution.js +14 -11
  276. package/build/src/workspace-place.js +19 -7
  277. package/build/src/world.js +16 -6
  278. package/package.json +8 -3
@@ -1,10 +1,25 @@
1
1
  import { isMap, parseDocument, stringify } from "yaml";
2
2
  import { formatTaskId, parseTaskId } from "./identity.js";
3
3
  export class TaskAuthorityCorruptionError extends Error {
4
- constructor(message, options) { super(message, options); this.name = "TaskAuthorityCorruptionError"; }
4
+ constructor(message, options) {
5
+ super(message, options);
6
+ this.name = "TaskAuthorityCorruptionError";
7
+ }
5
8
  }
6
9
  const STATES = new Set(["open", "in_progress", "on_hold", "done", "drop"]);
7
- const REQUIRED_STORED_KEYS = ["id", "title", "state", "priority", "needs", "parent", "supersedes", "relates", "note", "createdAt", "updatedAt"];
10
+ const REQUIRED_STORED_KEYS = [
11
+ "id",
12
+ "title",
13
+ "state",
14
+ "priority",
15
+ "needs",
16
+ "parent",
17
+ "supersedes",
18
+ "relates",
19
+ "note",
20
+ "createdAt",
21
+ "updatedAt",
22
+ ];
8
23
  const STORED_KEYS = [...REQUIRED_STORED_KEYS, "createdBy"];
9
24
  const CREATION_KEYS = ["title", "state", "priority", "needs", "parent", "supersedes", "relates", "note"];
10
25
  function frontMatter(markdown, fail) {
@@ -92,7 +107,9 @@ function fields(value, body, fail) {
92
107
  };
93
108
  }
94
109
  export function parseTaskDocument(bytes, expected) {
95
- const fail = (message, cause) => { throw new TaskAuthorityCorruptionError(message, cause === undefined ? {} : { cause }); };
110
+ const fail = (message, cause) => {
111
+ throw new TaskAuthorityCorruptionError(message, cause === undefined ? {} : { cause });
112
+ };
96
113
  const { value, body } = frontMatter(Buffer.from(bytes).toString("utf8"), fail);
97
114
  closed(value, STORED_KEYS, REQUIRED_STORED_KEYS, fail);
98
115
  const id = taskId(value.id, "id", fail);
@@ -102,27 +119,46 @@ export function parseTaskDocument(bytes, expected) {
102
119
  if (Date.parse(updatedAt) < Date.parse(createdAt))
103
120
  fail("updatedAt must not precede createdAt");
104
121
  return {
105
- id, state: state(value.state, fail), createdAt, updatedAt, ...fields(value, body, fail),
122
+ id,
123
+ state: state(value.state, fail),
124
+ createdAt,
125
+ updatedAt,
126
+ ...fields(value, body, fail),
106
127
  ...(Object.hasOwn(value, "createdBy") ? { createdBy: createdBy(value.createdBy, fail) } : {}),
107
128
  };
108
129
  }
109
130
  export function parseTaskCreationDocument(markdown) {
110
- const fail = (message) => { throw new TypeError(message); };
131
+ const fail = (message) => {
132
+ throw new TypeError(message);
133
+ };
111
134
  const { value, body } = frontMatter(markdown, fail);
112
135
  closed(value, CREATION_KEYS, ["title"], fail);
113
136
  const complete = {
114
- state: "open", priority: 2, needs: [], parent: null, supersedes: [], relates: [], note: "",
137
+ state: "open",
138
+ priority: 2,
139
+ needs: [],
140
+ parent: null,
141
+ supersedes: [],
142
+ relates: [],
143
+ note: "",
115
144
  ...value,
116
145
  };
117
146
  return { state: state(complete.state, fail), ...fields(complete, body, fail) };
118
147
  }
119
148
  export function serializeTaskDocument(document) {
120
149
  const value = {
121
- id: document.id, title: document.title, state: document.state, priority: document.priority,
122
- needs: [...document.needs], parent: document.parent, supersedes: [...document.supersedes],
123
- relates: [...document.relates], note: document.note,
150
+ id: document.id,
151
+ title: document.title,
152
+ state: document.state,
153
+ priority: document.priority,
154
+ needs: [...document.needs],
155
+ parent: document.parent,
156
+ supersedes: [...document.supersedes],
157
+ relates: [...document.relates],
158
+ note: document.note,
124
159
  ...(document.createdBy === undefined ? {} : { createdBy: document.createdBy }),
125
- createdAt: document.createdAt, updatedAt: document.updatedAt,
160
+ createdAt: document.createdAt,
161
+ updatedAt: document.updatedAt,
126
162
  };
127
163
  return Buffer.from(`---\n${stringify(value, { lineWidth: 0 })}---\n${document.body}`);
128
164
  }
@@ -3,8 +3,11 @@ import { identityCoordinate, identitySegments } from "../identity/coordinates.js
3
3
  import { normalizeIdentityStem } from "../identity/normalize.js";
4
4
  const STEM_CODE_POINTS = 32;
5
5
  export function isTaskSegment(value) {
6
- return value.length > 0 && value !== "." && value !== ".." && !value.includes("/")
7
- && normalizeIdentityStem({ source: value }) === value;
6
+ return (value.length > 0 &&
7
+ value !== "." &&
8
+ value !== ".." &&
9
+ !value.includes("/") &&
10
+ normalizeIdentityStem({ source: value }) === value);
8
11
  }
9
12
  export function parseTaskId(value) {
10
13
  let segments;
@@ -19,7 +19,6 @@ export type TaskDoctorReport = Readonly<{
19
19
  export type TaskDecompositionTree = TaskOutcome<TaskTreeNode>;
20
20
  export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRef, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskTreeNode, TaskUpdateResult, TaskView, UpdateTaskInput, TaskPage, TaskQueryExpression, TaskQueryPredicate, TaskQueryRow, TaskQuerySort, TaskRelationPredicateField, };
21
21
  export { TaskAuthorityCorruptionError, TASK_RELATION_PREDICATE_FIELDS };
22
- export declare function observeTaskDetails(world: WorldRoot, ids: readonly TaskId[]): Promise<TaskOutcome<readonly TaskDetail[]>>;
23
22
  declare class TaskHandle {
24
23
  readonly id: TaskId;
25
24
  private readonly world;
@@ -1,17 +1,11 @@
1
1
  import { buildTree, createTaskRelations, diagnoseBoard, projectDetailFacts, } from "./board.js";
2
2
  import { composeTasks } from "./compose.js";
3
3
  import { TaskAuthorityCorruptionError } from "./document.js";
4
- import { addTask, addTaskDocument, batchTasks, blockedTasks, lifecycleTask, listTasks, queryTasks, readTaskDetails, readyTasks, taskView, updateTask, } from "./operations.js";
4
+ import { addTask, addTaskDocument, batchTasks, blockedTasks, lifecycleTask, listTasks, queryTasks, readyTasks, taskView, updateTask, } from "./operations.js";
5
5
  import { readBoard } from "./store.js";
6
6
  import { actor, addInput, closed, limit, namespace, record, signal, sort, taskId as id, taskIds, text, updateInput, } from "./input.js";
7
7
  import { normalizeTaskQuery, TASK_RELATION_PREDICATE_FIELDS, DEFAULT_TASK_LIMIT, } from "./query.js";
8
8
  export { TaskAuthorityCorruptionError, TASK_RELATION_PREDICATE_FIELDS };
9
- export async function observeTaskDetails(world, ids) {
10
- const observed = await readTaskDetails(world, ids);
11
- if (observed.kind !== "accepted")
12
- return observed;
13
- return { kind: "accepted", value: observed.value.map((facts) => ({ ...facts, task: taskView(facts.task) })) };
14
- }
15
9
  class TaskHandle {
16
10
  id;
17
11
  world;
@@ -29,21 +23,37 @@ class TaskHandle {
29
23
  throw new TypeError("tree accepts no input");
30
24
  const board = (await readBoard(this.world)).board;
31
25
  const node = buildTree(board, this.id, createTaskRelations(board));
32
- return node === null ? { kind: "refused", refusal: { kind: "task-missing", taskId: this.id } } : { kind: "accepted", value: node };
26
+ return node === null
27
+ ? { kind: "refused", refusal: { kind: "task-missing", taskId: this.id } }
28
+ : { kind: "accepted", value: node };
29
+ }
30
+ update(input) {
31
+ return updateTask(this.world, this.id, updateInput(input));
33
32
  }
34
- update(input) { return updateTask(this.world, this.id, updateInput(input)); }
35
33
  lifecycle(verb, input) {
36
34
  const value = record(input ?? {}, `${verb} input`);
37
35
  closed(value, verb === "drop" || verb === "done" ? ["note", "signal"] : ["signal"], `${verb} input`);
38
36
  const note = verb === "drop" || verb === "done" ? text(value.note, "note") : undefined;
39
37
  return lifecycleTask(this.world, this.id, verb, signal(value.signal), note);
40
38
  }
41
- start(input) { return this.lifecycle("start", input); }
42
- stop(input) { return this.lifecycle("stop", input); }
43
- hold(input) { return this.lifecycle("hold", input); }
44
- resume(input) { return this.lifecycle("resume", input); }
45
- done(input) { return this.lifecycle("done", input); }
46
- drop(input) { return this.lifecycle("drop", input); }
39
+ start(input) {
40
+ return this.lifecycle("start", input);
41
+ }
42
+ stop(input) {
43
+ return this.lifecycle("stop", input);
44
+ }
45
+ hold(input) {
46
+ return this.lifecycle("hold", input);
47
+ }
48
+ resume(input) {
49
+ return this.lifecycle("resume", input);
50
+ }
51
+ done(input) {
52
+ return this.lifecycle("done", input);
53
+ }
54
+ drop(input) {
55
+ return this.lifecycle("drop", input);
56
+ }
47
57
  }
48
58
  class TasksHandle {
49
59
  world;
@@ -52,25 +62,100 @@ class TasksHandle {
52
62
  this.world = world;
53
63
  this.root = world;
54
64
  }
55
- task(input) { const v = record(input, "task input"); closed(v, ["id"], "task input"); return new TaskHandle(id(v.id), this.world); }
56
- add(input) { return addTask(this.world, addInput(input)); }
57
- addDocument(input) { const v = record(input, "addDocument input"); closed(v, ["markdown", "namespace", "actor", "signal"], "addDocument input"); const markdown = text(v.markdown, "markdown"); if (markdown === undefined)
58
- throw new TypeError("markdown is required"); const ns = namespace(v.namespace), createdBy = actor(v.actor), abort = signal(v.signal); return addTaskDocument(this.world, { markdown, ...(ns === undefined ? {} : { namespace: ns }), ...(createdBy === undefined ? {} : { actor: createdBy }), ...(abort === undefined ? {} : { signal: abort }) }); }
59
- async list(input = {}) { const v = record(input, "list input"); closed(v, ["selection", "scope", "namespace", "limit"], "list input"); if (v.selection !== undefined && v.selection !== "active" && v.selection !== "closed" && v.selection !== "all")
60
- throw new TypeError("selection must be active, closed, or all"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
61
- throw new TypeError("scope must be namespace or world"); return listTasks(this.world, namespace(v.namespace), v.selection ?? "active", v.scope, limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
62
- async ready(input = {}) { const v = record(input, "ready input"); closed(v, ["scope", "namespace", "parent", "limit"], "ready input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
63
- throw new TypeError("scope must be namespace or world"); const parent = v.parent === undefined ? undefined : id(v.parent); return readyTasks(this.world, namespace(v.namespace), v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
64
- async blocked(input = {}) { const v = record(input, "blocked input"); closed(v, ["scope", "namespace", "parent", "limit"], "blocked input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
65
- throw new TypeError("scope must be namespace or world"); const parent = v.parent === undefined ? undefined : id(v.parent); return blockedTasks(this.world, namespace(v.namespace), v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT); }
66
- async query(input = {}) { const v = record(input, "query input"); closed(v, ["where", "scope", "namespace", "sort", "limit"], "query input"); if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
67
- throw new TypeError("scope must be namespace or world"); const expression = v.where === undefined ? { kind: "and", terms: [{ kind: "predicate", predicate: { field: "state", operator: "!=", value: "done" } }, { kind: "predicate", predicate: { field: "state", operator: "!=", value: "drop" } }] } : normalizeTaskQuery(v.where); const selected = namespace(v.namespace); return queryTasks({ world: this.world, ...(selected === undefined ? {} : { namespace: selected }), expression, ...(v.scope === undefined ? {} : { scope: v.scope }), sort: sort(v.sort) ?? "priority", limit: limit(v.limit) ?? DEFAULT_TASK_LIMIT }); }
68
- async doctor() { return { issues: diagnoseBoard((await readBoard(this.world)).board) }; }
69
- batch(input) { const v = record(input, "batch input"); closed(v, ["verb", "ids", "note", "signal"], "batch input"); const verb = v.verb; if (verb !== "done" && verb !== "drop" && verb !== "hold")
70
- throw new TypeError("batch verb is invalid"); const note = text(v.note, "note"); if (note !== undefined && verb !== "done" && verb !== "drop")
71
- throw new TypeError("batch note is valid only for done or drop"); return batchTasks(this.world, verb, taskIds(v.ids, "ids") ?? [], signal(v.signal), note); }
72
- compose(input) { const v = record(input, "compose input"); closed(v, ["markdown", "namespace", "actor", "signal"], "compose input"); const markdown = text(v.markdown, "markdown"); if (markdown === undefined)
73
- throw new TypeError("markdown is required"); const selected = namespace(v.namespace); return composeTasks(this.world, markdown, signal(v.signal), actor(v.actor), selected); }
65
+ task(input) {
66
+ const v = record(input, "task input");
67
+ closed(v, ["id"], "task input");
68
+ return new TaskHandle(id(v.id), this.world);
69
+ }
70
+ add(input) {
71
+ return addTask(this.world, addInput(input));
72
+ }
73
+ addDocument(input) {
74
+ const v = record(input, "addDocument input");
75
+ closed(v, ["markdown", "namespace", "actor", "signal"], "addDocument input");
76
+ const markdown = text(v.markdown, "markdown");
77
+ if (markdown === undefined)
78
+ throw new TypeError("markdown is required");
79
+ const ns = namespace(v.namespace), createdBy = actor(v.actor), abort = signal(v.signal);
80
+ return addTaskDocument(this.world, {
81
+ markdown,
82
+ ...(ns === undefined ? {} : { namespace: ns }),
83
+ ...(createdBy === undefined ? {} : { actor: createdBy }),
84
+ ...(abort === undefined ? {} : { signal: abort }),
85
+ });
86
+ }
87
+ async list(input = {}) {
88
+ const v = record(input, "list input");
89
+ closed(v, ["selection", "scope", "namespace", "limit"], "list input");
90
+ if (v.selection !== undefined && v.selection !== "active" && v.selection !== "closed" && v.selection !== "all")
91
+ throw new TypeError("selection must be active, closed, or all");
92
+ if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
93
+ throw new TypeError("scope must be namespace or world");
94
+ return listTasks(this.world, namespace(v.namespace), v.selection ?? "active", v.scope, limit(v.limit) ?? DEFAULT_TASK_LIMIT);
95
+ }
96
+ async ready(input = {}) {
97
+ const v = record(input, "ready input");
98
+ closed(v, ["scope", "namespace", "parent", "limit"], "ready input");
99
+ if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
100
+ throw new TypeError("scope must be namespace or world");
101
+ const parent = v.parent === undefined ? undefined : id(v.parent);
102
+ return readyTasks(this.world, namespace(v.namespace), v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT);
103
+ }
104
+ async blocked(input = {}) {
105
+ const v = record(input, "blocked input");
106
+ closed(v, ["scope", "namespace", "parent", "limit"], "blocked input");
107
+ if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
108
+ throw new TypeError("scope must be namespace or world");
109
+ const parent = v.parent === undefined ? undefined : id(v.parent);
110
+ return blockedTasks(this.world, namespace(v.namespace), v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT);
111
+ }
112
+ async query(input = {}) {
113
+ const v = record(input, "query input");
114
+ closed(v, ["where", "scope", "namespace", "sort", "limit"], "query input");
115
+ if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
116
+ throw new TypeError("scope must be namespace or world");
117
+ const expression = v.where === undefined
118
+ ? {
119
+ kind: "and",
120
+ terms: [
121
+ { kind: "predicate", predicate: { field: "state", operator: "!=", value: "done" } },
122
+ { kind: "predicate", predicate: { field: "state", operator: "!=", value: "drop" } },
123
+ ],
124
+ }
125
+ : normalizeTaskQuery(v.where);
126
+ const selected = namespace(v.namespace);
127
+ return queryTasks({
128
+ world: this.world,
129
+ ...(selected === undefined ? {} : { namespace: selected }),
130
+ expression,
131
+ ...(v.scope === undefined ? {} : { scope: v.scope }),
132
+ sort: sort(v.sort) ?? "priority",
133
+ limit: limit(v.limit) ?? DEFAULT_TASK_LIMIT,
134
+ });
135
+ }
136
+ async doctor() {
137
+ return { issues: diagnoseBoard((await readBoard(this.world)).board) };
138
+ }
139
+ batch(input) {
140
+ const v = record(input, "batch input");
141
+ closed(v, ["verb", "ids", "note", "signal"], "batch input");
142
+ const verb = v.verb;
143
+ if (verb !== "done" && verb !== "drop" && verb !== "hold")
144
+ throw new TypeError("batch verb is invalid");
145
+ const note = text(v.note, "note");
146
+ if (note !== undefined && verb !== "done" && verb !== "drop")
147
+ throw new TypeError("batch note is valid only for done or drop");
148
+ return batchTasks(this.world, verb, taskIds(v.ids, "ids") ?? [], signal(v.signal), note);
149
+ }
150
+ compose(input) {
151
+ const v = record(input, "compose input");
152
+ closed(v, ["markdown", "namespace", "actor", "signal"], "compose input");
153
+ const markdown = text(v.markdown, "markdown");
154
+ if (markdown === undefined)
155
+ throw new TypeError("markdown is required");
156
+ const selected = namespace(v.namespace);
157
+ return composeTasks(this.world, markdown, signal(v.signal), actor(v.actor), selected);
158
+ }
74
159
  }
75
160
  export const Tasks = Object.freeze({
76
161
  of(world) {
@@ -90,8 +90,7 @@ export function sort(value) {
90
90
  export function state(value) {
91
91
  if (value === undefined)
92
92
  return undefined;
93
- if (value !== "open" && value !== "in_progress" && value !== "on_hold"
94
- && value !== "done" && value !== "drop") {
93
+ if (value !== "open" && value !== "in_progress" && value !== "on_hold" && value !== "done" && value !== "drop") {
95
94
  throw new TypeError("state is invalid");
96
95
  }
97
96
  return value;
@@ -102,8 +101,18 @@ function nullableId(value) {
102
101
  export function addInput(input) {
103
102
  const value = record(input, "add input");
104
103
  closed(value, [
105
- "title", "namespace", "body", "note", "state", "priority", "needs", "parent",
106
- "supersedes", "relates", "actor", "signal",
104
+ "title",
105
+ "namespace",
106
+ "body",
107
+ "note",
108
+ "state",
109
+ "priority",
110
+ "needs",
111
+ "parent",
112
+ "supersedes",
113
+ "relates",
114
+ "actor",
115
+ "signal",
107
116
  ], "add input");
108
117
  const title = text(value.title, "title");
109
118
  if (title === undefined || title.trim() === "")
@@ -137,9 +146,22 @@ export function addInput(input) {
137
146
  export function updateInput(input) {
138
147
  const value = record(input, "update input");
139
148
  closed(value, [
140
- "title", "body", "appendBody", "note", "priority", "needs", "addNeeds", "dropNeeds",
141
- "parent", "supersedes", "addSupersedes", "dropSupersedes", "relates", "addRelates",
142
- "dropRelates", "signal",
149
+ "title",
150
+ "body",
151
+ "appendBody",
152
+ "note",
153
+ "priority",
154
+ "needs",
155
+ "addNeeds",
156
+ "dropNeeds",
157
+ "parent",
158
+ "supersedes",
159
+ "addSupersedes",
160
+ "dropSupersedes",
161
+ "relates",
162
+ "addRelates",
163
+ "dropRelates",
164
+ "signal",
143
165
  ], "update input");
144
166
  if (value.body !== undefined && value.appendBody !== undefined) {
145
167
  throw new TypeError("body and appendBody are mutually exclusive");
@@ -1,7 +1,15 @@
1
1
  import { addInput, closed, namespace, record, taskId, taskIds, text, updateInput } from "./input.js";
2
2
  export const TASK_MUTATION_ACTIONS = Object.freeze([
3
- "task.add", "task.addDocument", "task.compose", "task.done", "task.drop",
4
- "task.hold", "task.resume", "task.start", "task.stop", "task.update",
3
+ "task.add",
4
+ "task.addDocument",
5
+ "task.compose",
6
+ "task.done",
7
+ "task.drop",
8
+ "task.hold",
9
+ "task.resume",
10
+ "task.start",
11
+ "task.stop",
12
+ "task.update",
5
13
  ]);
6
14
  const TASK_MUTATION_ACTION_SET = new Set(TASK_MUTATION_ACTIONS);
7
15
  export function isTaskMutationAction(value) {
@@ -16,9 +24,7 @@ export function decodeTaskMutationRequest(action, value) {
16
24
  switch (action) {
17
25
  case "task.add": {
18
26
  const input = mutationObject(value, ["input"], "task.add request");
19
- const raw = mutationObject(input.input, [
20
- "title", "namespace", "body", "note", "state", "priority", "needs", "parent", "supersedes", "relates",
21
- ], "task.add input");
27
+ const raw = mutationObject(input.input, ["title", "namespace", "body", "note", "state", "priority", "needs", "parent", "supersedes", "relates"], "task.add input");
22
28
  const decoded = addInput(raw);
23
29
  if (decoded.namespace === undefined)
24
30
  throw new TypeError("task.add request namespace is required");
@@ -48,8 +54,21 @@ export function decodeTaskMutationRequest(action, value) {
48
54
  case "task.update": {
49
55
  const request = mutationObject(value, ["id", "input"], "task.update request");
50
56
  const raw = mutationObject(request.input, [
51
- "title", "body", "appendBody", "note", "priority", "needs", "addNeeds", "dropNeeds", "parent",
52
- "supersedes", "addSupersedes", "dropSupersedes", "relates", "addRelates", "dropRelates",
57
+ "title",
58
+ "body",
59
+ "appendBody",
60
+ "note",
61
+ "priority",
62
+ "needs",
63
+ "addNeeds",
64
+ "dropNeeds",
65
+ "parent",
66
+ "supersedes",
67
+ "addSupersedes",
68
+ "dropSupersedes",
69
+ "relates",
70
+ "addRelates",
71
+ "dropRelates",
53
72
  ], "task.update input");
54
73
  return { action, id: taskId(request.id), input: updateInput(raw) };
55
74
  }
@@ -77,17 +96,40 @@ export async function executeTaskMutation(input) {
77
96
  const { request, signal } = input;
78
97
  const withSignal = signal === undefined ? {} : { signal };
79
98
  switch (request.action) {
80
- case "task.add": return await tasks.add({ ...request.input, actor: input.requester, ...withSignal });
81
- case "task.addDocument": return await tasks.addDocument({ ...request.input, actor: input.requester, ...withSignal });
82
- case "task.compose": return await tasks.compose({ markdown: request.markdown, namespace: request.namespace, actor: input.requester, ...withSignal });
83
- case "task.update": return await tasks.task({ id: request.id }).update({ ...request.input, ...withSignal });
84
- case "task.start": return await tasks.task({ id: request.id }).start(withSignal);
85
- case "task.stop": return await tasks.task({ id: request.id }).stop(withSignal);
86
- case "task.resume": return await tasks.task({ id: request.id }).resume(withSignal);
87
- case "task.hold": return await tasks.batch({ verb: "hold", ids: request.ids, ...withSignal });
88
- case "task.done": return await tasks.batch({ verb: "done", ids: request.ids, ...withSignal,
89
- ...(request.note === undefined ? {} : { note: request.note }) });
90
- case "task.drop": return await tasks.batch({ verb: "drop", ids: request.ids, ...withSignal,
91
- ...(request.note === undefined ? {} : { note: request.note }) });
99
+ case "task.add":
100
+ return await tasks.add({ ...request.input, actor: input.requester, ...withSignal });
101
+ case "task.addDocument":
102
+ return await tasks.addDocument({ ...request.input, actor: input.requester, ...withSignal });
103
+ case "task.compose":
104
+ return await tasks.compose({
105
+ markdown: request.markdown,
106
+ namespace: request.namespace,
107
+ actor: input.requester,
108
+ ...withSignal,
109
+ });
110
+ case "task.update":
111
+ return await tasks.task({ id: request.id }).update({ ...request.input, ...withSignal });
112
+ case "task.start":
113
+ return await tasks.task({ id: request.id }).start(withSignal);
114
+ case "task.stop":
115
+ return await tasks.task({ id: request.id }).stop(withSignal);
116
+ case "task.resume":
117
+ return await tasks.task({ id: request.id }).resume(withSignal);
118
+ case "task.hold":
119
+ return await tasks.batch({ verb: "hold", ids: request.ids, ...withSignal });
120
+ case "task.done":
121
+ return await tasks.batch({
122
+ verb: "done",
123
+ ids: request.ids,
124
+ ...withSignal,
125
+ ...(request.note === undefined ? {} : { note: request.note }),
126
+ });
127
+ case "task.drop":
128
+ return await tasks.batch({
129
+ verb: "drop",
130
+ ids: request.ids,
131
+ ...withSignal,
132
+ ...(request.note === undefined ? {} : { note: request.note }),
133
+ });
92
134
  }
93
135
  }
@@ -6,7 +6,9 @@ import { type TaskPage, type TaskQueryExpression, type TaskQueryRow, type TaskQu
6
6
  export type TaskView = Readonly<TaskDocument & {
7
7
  namespace: readonly string[];
8
8
  }>;
9
- export declare function nukeTask(world: WorldRoot): Promise<void>;
9
+ export declare function nukeTask(world: WorldRoot, options?: Readonly<{
10
+ timeoutMs?: number;
11
+ }>): Promise<void>;
10
12
  export type TaskRefusal = Readonly<{
11
13
  kind: "task-missing";
12
14
  taskId: TaskId;
@@ -116,6 +118,9 @@ export declare function batchTasks(world: WorldRoot, verb: "done" | "drop" | "ho
116
118
  export declare function settleTask(world: WorldRoot, id: TaskId): Promise<SettledTaskResult>;
117
119
  export declare function listTasks(world: WorldRoot, namespace: readonly string[] | undefined, selection: "active" | "closed" | "all", scope?: "namespace" | "world", limit?: number): Promise<TaskOutcome<TaskPage<TaskRow>>>;
118
120
  export declare function readTaskDetails(world: WorldRoot, ids: readonly TaskId[]): Promise<TaskOutcome<readonly TaskDetailFacts[]>>;
121
+ export declare function observeTaskDetails(world: WorldRoot, ids: readonly TaskId[]): Promise<TaskOutcome<readonly (Omit<TaskDetailFacts, "task"> & Readonly<{
122
+ task: TaskView;
123
+ }>)[]>>;
119
124
  export declare function readyTasks(world: WorldRoot, namespace: readonly string[] | undefined, scope?: "namespace" | "world", parent?: TaskId, limit?: number): Promise<TaskOutcome<TaskPage<TaskRow>>>;
120
125
  export declare function blockedTasks(world: WorldRoot, namespace: readonly string[] | undefined, scope?: "namespace" | "world", parent?: TaskId, limit?: number): Promise<TaskOutcome<TaskPage<BlockedTaskRow>>>;
121
126
  export declare function queryTasks(input: Readonly<{