@astrosheep/keiyaku 4.5.11 → 4.5.13

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 (272) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +135 -377
  2. package/build/integrations/pi/keiyaku.ts +11 -116
  3. package/build/src/akuma/akuma-errors.d.ts +1 -0
  4. package/build/src/akuma/akuma-errors.js +1 -0
  5. package/build/src/akuma/akuma-handle.d.ts +1 -0
  6. package/build/src/akuma/akuma-handle.js +6 -7
  7. package/build/src/akuma/akuma-product.d.ts +6 -8
  8. package/build/src/akuma/akuma-product.js +141 -57
  9. package/build/src/akuma/akuma.d.ts +5 -7
  10. package/build/src/akuma/akuma.js +1 -22
  11. package/build/src/akuma/archetype.d.ts +6 -5
  12. package/build/src/akuma/archetype.js +137 -38
  13. package/build/src/akuma/body.d.ts +5 -5
  14. package/build/src/akuma/body.js +223 -63
  15. package/build/src/akuma/call-input.d.ts +4 -0
  16. package/build/src/akuma/call-input.js +21 -0
  17. package/build/src/akuma/call-request.d.ts +5 -8
  18. package/build/src/akuma/call-request.js +28 -73
  19. package/build/src/akuma/fleet-execution.d.ts +26 -0
  20. package/build/src/akuma/fleet-execution.js +109 -0
  21. package/build/src/{library/fleet-result.d.ts → akuma/fleet-observation.d.ts} +13 -57
  22. package/build/src/{library/fleet-result.js → akuma/fleet-observation.js} +4 -25
  23. package/build/src/akuma/fleet-request.d.ts +122 -0
  24. package/build/src/akuma/fleet-request.js +168 -0
  25. package/build/src/akuma/heart/facts.d.ts +23 -0
  26. package/build/src/akuma/heart/facts.js +7 -0
  27. package/build/src/akuma/heart/index.d.ts +43 -4
  28. package/build/src/akuma/heart/index.js +107 -7
  29. package/build/src/akuma/heart/request-authority.d.ts +2 -0
  30. package/build/src/akuma/heart/request-authority.js +28 -3
  31. package/build/src/akuma/heart/request-rows.d.ts +2 -0
  32. package/build/src/akuma/heart/request-rows.js +24 -5
  33. package/build/src/akuma/heart/rows.d.ts +4 -1
  34. package/build/src/akuma/heart/rows.js +46 -19
  35. package/build/src/akuma/heart/schema.d.ts +1 -1
  36. package/build/src/akuma/heart/schema.js +28 -6
  37. package/build/src/akuma/heart/storage.d.ts +1 -1
  38. package/build/src/akuma/heart/tells.d.ts +29 -0
  39. package/build/src/akuma/heart/tells.js +136 -5
  40. package/build/src/akuma/heart/timeline.js +9 -3
  41. package/build/src/akuma/projection-read.js +36 -3
  42. package/build/src/akuma/projection.js +3 -4
  43. package/build/src/akuma/provider.d.ts +4 -0
  44. package/build/src/akuma/provider.js +56 -3
  45. package/build/src/akuma/providers/claude/index.js +3 -0
  46. package/build/src/akuma/providers/codex-app-server/index.js +14 -12
  47. package/build/src/akuma/providers/pi/index.js +7 -1
  48. package/build/src/akuma/publication.js +65 -49
  49. package/build/src/akuma/request-lifecycle.d.ts +5 -4
  50. package/build/src/akuma/request-lifecycle.js +29 -16
  51. package/build/src/akuma/request-rendezvous.d.ts +15 -12
  52. package/build/src/akuma/request-rendezvous.js +80 -51
  53. package/build/src/akuma/request-serve.d.ts +1 -2
  54. package/build/src/akuma/request-serve.js +94 -39
  55. package/build/src/akuma/request-wire.d.ts +57 -26
  56. package/build/src/akuma/request-wire.js +64 -25
  57. package/build/src/akuma/turn-drive.d.ts +5 -4
  58. package/build/src/akuma/turn-drive.js +27 -11
  59. package/build/src/akuma-body.d.ts +4 -6
  60. package/build/src/akuma-body.js +19 -17
  61. package/build/src/bounded-list.d.ts +8 -0
  62. package/build/src/bounded-list.js +14 -0
  63. package/build/src/cli/accepted.d.ts +1 -1
  64. package/build/src/cli/accepted.js +1 -0
  65. package/build/src/cli/commands/akuma-invoke.js +1 -25
  66. package/build/src/cli/commands/contract-help.d.ts +5 -2
  67. package/build/src/cli/commands/contract-help.js +62 -12
  68. package/build/src/cli/commands/contract-invoke.d.ts +5 -0
  69. package/build/src/cli/commands/contract-invoke.js +26 -1
  70. package/build/src/cli/commands/contract.js +50 -18
  71. package/build/src/cli/commands/task-invoke.js +10 -2
  72. package/build/src/cli/commands/task-query.js +3 -4
  73. package/build/src/cli/coordinates.d.ts +13 -0
  74. package/build/src/cli/coordinates.js +38 -24
  75. package/build/src/cli/draft.d.ts +1 -1
  76. package/build/src/cli/invoke.js +14 -1
  77. package/build/src/cli/render/akuma-activity.d.ts +0 -1
  78. package/build/src/cli/render/akuma-activity.js +5 -38
  79. package/build/src/cli/render/akuma.js +4 -1
  80. package/build/src/cli/render/audit.js +4 -1
  81. package/build/src/cli/render/catalog.js +13 -39
  82. package/build/src/cli/render/contract.js +4 -14
  83. package/build/src/cli/render/kanshi-akuma.js +3 -8
  84. package/build/src/cli/render/kanshi.js +8 -34
  85. package/build/src/cli/render/nuke.js +7 -3
  86. package/build/src/cli/render/receipt.d.ts +1 -0
  87. package/build/src/cli/render/receipt.js +8 -0
  88. package/build/src/cli/render/refusal.js +4 -3
  89. package/build/src/cli/render/task.js +4 -37
  90. package/build/src/cli/render/terminal.d.ts +2 -6
  91. package/build/src/cli/render/terminal.js +4 -9
  92. package/build/src/cli/result.d.ts +2 -1
  93. package/build/src/contract-guidance.js +13 -3
  94. package/build/src/contract-worktree.d.ts +1 -0
  95. package/build/src/contract-worktree.js +26 -2
  96. package/build/src/core/facts/codec.d.ts +2 -1
  97. package/build/src/core/facts/codec.js +3 -0
  98. package/build/src/core/facts/gate.d.ts +2 -1
  99. package/build/src/core/facts/gate.js +63 -0
  100. package/build/src/core/verbs/abandon.d.ts +2 -1
  101. package/build/src/core/verbs/abandon.js +16 -0
  102. package/build/src/core/verbs/amend.d.ts +2 -1
  103. package/build/src/core/verbs/amend.js +20 -0
  104. package/build/src/core/verbs/arc.d.ts +2 -1
  105. package/build/src/core/verbs/arc.js +16 -0
  106. package/build/src/core/verbs/attestation.d.ts +2 -1
  107. package/build/src/core/verbs/attestation.js +16 -0
  108. package/build/src/core/verbs/bind.d.ts +2 -1
  109. package/build/src/core/verbs/bind.js +16 -0
  110. package/build/src/core/verbs/deliver.d.ts +2 -1
  111. package/build/src/core/verbs/deliver.js +16 -0
  112. package/build/src/core/verbs/placement.d.ts +2 -1
  113. package/build/src/core/verbs/placement.js +58 -1
  114. package/build/src/dispatch/association.d.ts +13 -0
  115. package/build/src/dispatch/association.js +20 -0
  116. package/build/src/dispatch/index.d.ts +6 -0
  117. package/build/src/dispatch/index.js +27 -3
  118. package/build/src/git/hooks.d.ts +9 -1
  119. package/build/src/git/hooks.js +79 -1
  120. package/build/src/git/nuke.d.ts +2 -1
  121. package/build/src/git/nuke.js +6 -11
  122. package/build/src/git/private-state-seat.d.ts +26 -1
  123. package/build/src/git/private-state-seat.js +78 -13
  124. package/build/src/git/process.d.ts +2 -0
  125. package/build/src/git/reconcile.d.ts +1 -2
  126. package/build/src/git/reconcile.js +0 -6
  127. package/build/src/git/repository.d.ts +0 -2
  128. package/build/src/git/repository.js +27 -25
  129. package/build/src/git/result-codec.d.ts +29 -0
  130. package/build/src/git/result-codec.js +306 -0
  131. package/build/src/git/target-placement.js +2 -8
  132. package/build/src/git/workspace.d.ts +2 -0
  133. package/build/src/git/workspace.js +4 -0
  134. package/build/src/index.d.ts +1 -0
  135. package/build/src/kanshi/fleet.js +1 -1
  136. package/build/src/kanshi/read.js +55 -28
  137. package/build/src/kanshi/report.d.ts +4 -3
  138. package/build/src/kanshi/select.js +14 -1
  139. package/build/src/library/address.d.ts +1 -0
  140. package/build/src/library/address.js +4 -7
  141. package/build/src/library/akuma-creation.d.ts +5 -3
  142. package/build/src/library/akuma-creation.js +90 -33
  143. package/build/src/library/audit.js +2 -1
  144. package/build/src/library/catalog.d.ts +10 -2
  145. package/build/src/library/catalog.js +65 -25
  146. package/build/src/library/composition.d.ts +1 -0
  147. package/build/src/library/composition.js +1 -0
  148. package/build/src/library/configuration.d.ts +4 -21
  149. package/build/src/library/configuration.js +2 -158
  150. package/build/src/library/continuation.d.ts +20 -1
  151. package/build/src/library/continuation.js +36 -0
  152. package/build/src/library/contract-bind.d.ts +1 -0
  153. package/build/src/library/contract-bind.js +16 -5
  154. package/build/src/library/contract-forwarding.d.ts +2 -2
  155. package/build/src/library/contract-forwarding.js +18 -4
  156. package/build/src/library/contract-handle.js +4 -3
  157. package/build/src/library/contract-operations.d.ts +5 -9
  158. package/build/src/library/contract-operations.js +34 -47
  159. package/build/src/library/contract.d.ts +11 -2
  160. package/build/src/library/contract.js +21 -1
  161. package/build/src/library/delivery.d.ts +4 -1
  162. package/build/src/library/delivery.js +47 -0
  163. package/build/src/library/fleet.d.ts +4 -136
  164. package/build/src/library/fleet.js +31 -315
  165. package/build/src/library/keiyaku.d.ts +7 -3
  166. package/build/src/library/keiyaku.js +1 -0
  167. package/build/src/library/mutation.d.ts +431 -3
  168. package/build/src/library/mutation.js +192 -19
  169. package/build/src/library/nuke.d.ts +7 -1
  170. package/build/src/library/nuke.js +18 -4
  171. package/build/src/library/reconcile.d.ts +14 -0
  172. package/build/src/library/reconcile.js +22 -8
  173. package/build/src/library/refusal.d.ts +9 -1
  174. package/build/src/library/refusal.js +76 -0
  175. package/build/src/library/region.d.ts +0 -8
  176. package/build/src/library/region.js +1 -29
  177. package/build/src/library/result-codec.d.ts +2 -0
  178. package/build/src/library/result-codec.js +12 -0
  179. package/build/src/markdown/lex.js +9 -2
  180. package/build/src/markdown/types.d.ts +2 -1
  181. package/build/src/markdown/types.js +3 -1
  182. package/build/src/plugin/akuma-signals.d.ts +12 -0
  183. package/build/src/plugin/akuma-signals.js +14 -0
  184. package/build/src/plugin/public.d.ts +51 -0
  185. package/build/src/plugin/public.js +1 -0
  186. package/build/src/plugin/runtime.d.ts +14 -0
  187. package/build/src/plugin/runtime.js +357 -0
  188. package/build/src/protocol/amend.js +3 -3
  189. package/build/src/protocol/attempt.d.ts +2 -1
  190. package/build/src/protocol/attempt.js +1 -1
  191. package/build/src/protocol/audit.d.ts +1 -1
  192. package/build/src/protocol/audit.js +1 -1
  193. package/build/src/protocol/bind.d.ts +3 -1
  194. package/build/src/protocol/bind.js +26 -0
  195. package/build/src/protocol/completion.js +0 -1
  196. package/build/src/protocol/deliver.d.ts +1 -1
  197. package/build/src/protocol/deliver.js +136 -57
  198. package/build/src/protocol/intent.d.ts +0 -1
  199. package/build/src/protocol/intent.js +0 -1
  200. package/build/src/protocol/operations.d.ts +9 -2
  201. package/build/src/protocol/operations.js +16 -1
  202. package/build/src/protocol/outcome.d.ts +3 -0
  203. package/build/src/protocol/outcome.js +17 -1
  204. package/build/src/protocol/placement.js +10 -3
  205. package/build/src/protocol/read/status.d.ts +8 -0
  206. package/build/src/protocol/read/status.js +49 -0
  207. package/build/src/protocol/reintegrate.js +10 -3
  208. package/build/src/protocol/result-codec.d.ts +22 -0
  209. package/build/src/protocol/result-codec.js +442 -0
  210. package/build/src/protocol/review.d.ts +1 -1
  211. package/build/src/protocol/review.js +81 -46
  212. package/build/src/protocol/run.d.ts +22 -2
  213. package/build/src/protocol/run.js +119 -29
  214. package/build/src/runtime/proc/lifecycle.js +1 -1
  215. package/build/src/runtime/proc/line-rpc.d.ts +7 -1
  216. package/build/src/runtime/proc/line-rpc.js +49 -9
  217. package/build/src/runtime/proc/run.d.ts +0 -1
  218. package/build/src/runtime/proc/run.js +1 -11
  219. package/build/src/runtime/proc/termination.d.ts +1 -0
  220. package/build/src/runtime/proc/termination.js +63 -18
  221. package/build/src/runtime/proc/windows-launch.exe +0 -0
  222. package/build/src/settings.d.ts +10 -0
  223. package/build/src/settings.js +88 -2
  224. package/build/src/settlement/result-codec.d.ts +2 -0
  225. package/build/src/settlement/result-codec.js +56 -0
  226. package/build/src/settlement/settle.d.ts +5 -12
  227. package/build/src/settlement/settle.js +60 -55
  228. package/build/src/task/board.d.ts +3 -0
  229. package/build/src/task/board.js +22 -4
  230. package/build/src/task/catalog.d.ts +13 -2
  231. package/build/src/task/catalog.js +59 -5
  232. package/build/src/task/compose.d.ts +4 -2
  233. package/build/src/task/compose.js +56 -30
  234. package/build/src/task/created-observation.d.ts +39 -0
  235. package/build/src/task/created-observation.js +26 -0
  236. package/build/src/task/identity.d.ts +6 -0
  237. package/build/src/task/identity.js +48 -7
  238. package/build/src/task/index.d.ts +4 -3
  239. package/build/src/task/index.js +19 -16
  240. package/build/src/task/input.d.ts +3 -1
  241. package/build/src/task/input.js +7 -4
  242. package/build/src/task/lifecycle-operations.d.ts +6 -0
  243. package/build/src/task/lifecycle-operations.js +116 -0
  244. package/build/src/task/mutation-result.d.ts +762 -20
  245. package/build/src/task/mutation-result.js +34 -9
  246. package/build/src/task/mutation.d.ts +4 -9
  247. package/build/src/task/mutation.js +17 -52
  248. package/build/src/task/operation-types.d.ts +114 -0
  249. package/build/src/task/operation-types.js +1 -0
  250. package/build/src/task/operations.d.ts +6 -113
  251. package/build/src/task/operations.js +75 -117
  252. package/build/src/task/query.d.ts +8 -11
  253. package/build/src/task/query.js +7 -14
  254. package/build/src/task/store.d.ts +11 -1
  255. package/build/src/task/store.js +169 -55
  256. package/build/src/task/view.d.ts +4 -0
  257. package/build/src/task/view.js +7 -0
  258. package/build/src/verification/declaration.d.ts +1 -0
  259. package/build/src/verification/declaration.js +18 -1
  260. package/build/src/verification/execution.d.ts +0 -1
  261. package/build/src/verification/execution.js +5 -5
  262. package/build/src/world.d.ts +0 -2
  263. package/build/src/world.js +3 -7
  264. package/package.json +17 -5
  265. package/build/src/cli/square-edge.d.ts +0 -7
  266. package/build/src/cli/square-edge.js +0 -159
  267. package/build/src/git/ref-migration.d.ts +0 -22
  268. package/build/src/git/ref-migration.js +0 -55
  269. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +0 -102
  270. package/build/src/library/contract-forwarding-reconciliation-result.js +0 -92
  271. package/build/src/library/contract-forwarding-result.d.ts +0 -4270
  272. package/build/src/library/contract-forwarding-result.js +0 -521
@@ -1,7 +1,17 @@
1
1
  import { join } from "node:path";
2
+ import { randomBytes } from "node:crypto";
3
+ import { contractSegment } from "../core/facts/types.js";
2
4
  import { identityCoordinate, identitySegments } from "../identity/coordinates.js";
3
5
  import { normalizeIdentityStem } from "../identity/normalize.js";
4
6
  const STEM_CODE_POINTS = 32;
7
+ const TASK_FILENAME_BYTES = 255;
8
+ const TASK_EXTENSION_BYTES = Buffer.byteLength(".md");
9
+ const TASK_LOCK_EXTENSION_BYTES = Buffer.byteLength(".sqlite");
10
+ const GENERATED_SUFFIX = "-0000";
11
+ export const TASK_LOCK_ID_BYTES = TASK_FILENAME_BYTES - TASK_LOCK_EXTENSION_BYTES;
12
+ export const TASK_LOCAL_ID_BYTES = TASK_FILENAME_BYTES - TASK_EXTENSION_BYTES - TASK_LOCK_EXTENSION_BYTES - Buffer.byteLength(GENERATED_SUFFIX);
13
+ const GENERATED_STEM_BYTES = TASK_LOCAL_ID_BYTES - Buffer.byteLength(GENERATED_SUFFIX);
14
+ const WINDOWS_RESERVED = /^(?:con|prn|aux|nul|clock\$|com[1-9]|lpt[1-9])(?:\..*)?$/iu;
5
15
  export function isTaskSegment(value) {
6
16
  return (value.length > 0 &&
7
17
  value !== "." &&
@@ -26,8 +36,19 @@ export function formatTaskId(coordinate) {
26
36
  throw new TypeError("task coordinate contains a noncanonical segment");
27
37
  return identityCoordinate({ family: "task", segments: [...coordinate.namespace, coordinate.localId] });
28
38
  }
39
+ export function canonicalTaskId(value) {
40
+ const id = formatTaskId(parseTaskId(value));
41
+ if (id !== value)
42
+ throw new TypeError("task ID is not canonical");
43
+ return id;
44
+ }
45
+ export function contractNamespace(id) {
46
+ return ["kei", contractSegment(id)];
47
+ }
29
48
  export function taskAuthorityPath(tasksDirectory, coordinate) {
30
- return join(tasksDirectory, ...coordinate.namespace, `${coordinate.localId}.md`);
49
+ if (![...coordinate.namespace, coordinate.localId].every(isTaskSegment))
50
+ throw new TypeError("task coordinate contains a noncanonical segment");
51
+ return join(tasksDirectory, ...coordinate.namespace.map((segment) => physicalTaskSegment(segment)), `${physicalTaskSegment(coordinate.localId)}.md`);
31
52
  }
32
53
  export function deriveLocalStem(title) {
33
54
  const stem = normalizeIdentityStem({ source: title });
@@ -43,17 +64,37 @@ export function deriveLocalStem(title) {
43
64
  fitted += `-${word}`;
44
65
  count = candidate;
45
66
  }
46
- return fitted;
67
+ return fitPhysicalStem(fitted);
47
68
  }
48
69
  export function allocateLocalId(stem, occupied) {
49
- if (!occupied.has(stem))
50
- return stem;
51
- for (let suffix = 2; Number.isSafeInteger(suffix); suffix += 1) {
52
- const candidate = `${stem}-${suffix}`;
70
+ const seed = randomBytes(2).readUInt16BE(0);
71
+ for (let offset = 0; offset <= 0xffff; offset += 1) {
72
+ const suffix = ((seed + offset) & 0xffff).toString(16).padStart(4, "0");
73
+ const candidate = `${fitPhysicalStem(stem, suffix)}-${suffix}`;
53
74
  if (!occupied.has(candidate))
54
75
  return candidate;
55
76
  }
56
- throw new Error("task identity collision ordinal exceeded the safe integer range");
77
+ throw new Error("task identity hexadecimal suffix space exhausted");
78
+ }
79
+ function fitPhysicalStem(stem, suffix) {
80
+ const maxBytes = suffix === undefined ? GENERATED_STEM_BYTES : TASK_LOCAL_ID_BYTES - Buffer.byteLength(`-${suffix}`);
81
+ let result = "";
82
+ for (const segment of new Intl.Segmenter("und", { granularity: "grapheme" }).segment(stem)) {
83
+ if (Buffer.byteLength(result + segment.segment) > maxBytes)
84
+ break;
85
+ result += segment.segment;
86
+ }
87
+ result = result.replace(/-+$/u, "");
88
+ if (result.length === 0)
89
+ throw new TypeError("task title cannot fit the physical filename budget");
90
+ return result;
91
+ }
92
+ export function physicalTaskSegment(segment, maxBytes = TASK_LOCAL_ID_BYTES) {
93
+ if (Buffer.byteLength(segment) <= maxBytes && !WINDOWS_RESERVED.test(segment))
94
+ return segment;
95
+ if (Buffer.byteLength(segment) > maxBytes)
96
+ throw new TypeError("task identity cannot fit the physical filename budget");
97
+ throw new TypeError("task identity contains a Windows-reserved physical segment");
57
98
  }
58
99
  export function sameNamespace(left, right) {
59
100
  return left.length === right.length && left.every((segment, index) => segment === right[index]);
@@ -5,7 +5,7 @@ import { type BlockedTaskRow, type TaskDetailFacts, type TaskDoctorIssue, type T
5
5
  import { type TaskCompositionAlias, type TaskCompositionBodyPreview, type TaskCompositionResult } from "./compose.js";
6
6
  import { TaskAuthorityCorruptionError, type TaskPriority, type TaskState } from "./document.js";
7
7
  import type { TaskId } from "./identity.js";
8
- import { type AddTaskDocumentInput, type AddTaskInput, type TaskBatchResult, type TaskCompositionDiagnostic, type TaskMutationResult, type TaskOutcome, type TaskRefusal, type TaskRetry, type TaskUpdateResult, type TaskView, type UpdateTaskInput } from "./operations.js";
8
+ import { type AddTaskDocumentInput, type AddTaskInput, type TaskBatchResult, type TaskCleanupFailure, type TaskCompositionDiagnostic, type TaskMutationResult, type TaskOutcome, type TaskRefusal, type TaskRetry, type TaskUpdateResult, type TaskView, type UpdateTaskInput } from "./operations.js";
9
9
  import { TASK_RELATION_PREDICATE_FIELDS, type TaskPage, type TaskQueryExpression, type TaskQueryPredicate, type TaskQueryRow, type TaskQuerySort, type TaskRelationPredicateField } from "./query.js";
10
10
  export type TaskDetail = Omit<TaskDetailFacts, "task"> & Readonly<{
11
11
  task: TaskView;
@@ -23,9 +23,11 @@ export type TaskDoctorReport = Readonly<{
23
23
  issues: readonly TaskDoctorIssue[];
24
24
  }>;
25
25
  export type TaskDecompositionTree = TaskOutcome<TaskTreeNode>;
26
- export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCompositionDiagnostic, TaskCompositionAlias, TaskCompositionBodyPreview, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRef, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskTreeNode, TaskUpdateResult, TaskView, UpdateTaskInput, TaskPage, TaskQueryExpression, TaskQueryPredicate, TaskQueryRow, TaskQuerySort, TaskRelationPredicateField, };
26
+ export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCleanupFailure, TaskCompositionDiagnostic, TaskCompositionAlias, TaskCompositionBodyPreview, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRef, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskTreeNode, TaskUpdateResult, TaskView, UpdateTaskInput, TaskPage, TaskQueryExpression, TaskQueryPredicate, TaskQueryRow, TaskQuerySort, TaskRelationPredicateField, };
27
27
  export type { LibraryExecution } from "../akuma/requests.js";
28
28
  export { TaskAuthorityCorruptionError, TASK_RELATION_PREDICATE_FIELDS };
29
+ export { observeRecentTaskStatus, type RecentTaskStatusRow } from "./catalog.js";
30
+ export { taskRowViewLimit } from "./input.js";
29
31
  declare class TaskHandle {
30
32
  readonly id: TaskId;
31
33
  private readonly world;
@@ -108,7 +110,6 @@ declare class TasksHandle {
108
110
  }>): Promise<TaskCompositionResult>;
109
111
  }
110
112
  export type Tasks = TasksHandle;
111
- export declare function tasksForExecution(world: WorldRoot, execution: ExecutionContext): Tasks;
112
113
  type TasksOfInput = Readonly<{
113
114
  execution?: LibraryExecution;
114
115
  }>;
@@ -1,13 +1,15 @@
1
1
  import { executionChannel, libraryExecution, localExecutionContext, } from "../akuma/requests.js";
2
2
  import { requestForwardedTask } from "./mutation.js";
3
- import { buildTree, createTaskRelations, diagnoseBoard, projectDetailFacts, } from "./board.js";
3
+ import { buildTree, createTaskRelations, diagnoseBoard, } from "./board.js";
4
4
  import { composeTasks, } from "./compose.js";
5
5
  import { TaskAuthorityCorruptionError } from "./document.js";
6
- import { addTask, addTaskDocument, batchTasks, blockedTasks, lifecycleTask, listTasks, queryTasks, readyTasks, taskView, updateTask, } from "./operations.js";
6
+ import { addTask, addTaskDocument, batchTasks, blockedTasks, lifecycleTask, listTasks, queryTasks, readTaskDetail, readyTasks, taskView, updateTask, } from "./operations.js";
7
7
  import { readBoard } from "./store.js";
8
- import { actor, addInput, closed, limit, namespace, record, signal, sort, taskId as id, taskIds, text, updateInput, } from "./input.js";
9
- import { normalizeTaskQuery, TASK_RELATION_PREDICATE_FIELDS, DEFAULT_TASK_LIMIT, } from "./query.js";
8
+ import { actor, addInput, closed, namespace, record, signal, sort, taskRowViewLimit, taskId as id, taskIds, text, updateInput, } from "./input.js";
9
+ import { normalizeTaskQuery, TASK_RELATION_PREDICATE_FIELDS, } from "./query.js";
10
10
  export { TaskAuthorityCorruptionError, TASK_RELATION_PREDICATE_FIELDS };
11
+ export { observeRecentTaskStatus } from "./catalog.js";
12
+ export { taskRowViewLimit } from "./input.js";
11
13
  function forwardTask(directory, world, request, signal) {
12
14
  return requestForwardedTask({
13
15
  directory,
@@ -26,8 +28,7 @@ class TaskHandle {
26
28
  this.execution = execution;
27
29
  }
28
30
  async read() {
29
- const board = (await readBoard(this.world)).board;
30
- const facts = projectDetailFacts(board, this.id, createTaskRelations(board));
31
+ const facts = await readTaskDetail(this.world, this.id);
31
32
  return facts === null ? null : { ...facts, task: taskView(facts.task) };
32
33
  }
33
34
  async tree() {
@@ -140,7 +141,8 @@ class TasksHandle {
140
141
  throw new TypeError("selection must be active, closed, or all");
141
142
  if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
142
143
  throw new TypeError("scope must be namespace or world");
143
- return listTasks(this.world, namespace(v.namespace), v.selection ?? "active", v.scope, limit(v.limit) ?? DEFAULT_TASK_LIMIT);
144
+ const selectedLimit = taskRowViewLimit(v.limit);
145
+ return listTasks(this.world, namespace(v.namespace), v.selection ?? "active", v.scope, selectedLimit);
144
146
  }
145
147
  async ready(input = {}) {
146
148
  const v = record(input, "ready input");
@@ -148,7 +150,8 @@ class TasksHandle {
148
150
  if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
149
151
  throw new TypeError("scope must be namespace or world");
150
152
  const parent = v.parent === undefined ? undefined : id(v.parent);
151
- return readyTasks(this.world, namespace(v.namespace), v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT);
153
+ const selectedLimit = taskRowViewLimit(v.limit);
154
+ return readyTasks(this.world, namespace(v.namespace), v.scope, parent, selectedLimit);
152
155
  }
153
156
  async blocked(input = {}) {
154
157
  const v = record(input, "blocked input");
@@ -156,7 +159,8 @@ class TasksHandle {
156
159
  if (v.scope !== undefined && v.scope !== "namespace" && v.scope !== "world")
157
160
  throw new TypeError("scope must be namespace or world");
158
161
  const parent = v.parent === undefined ? undefined : id(v.parent);
159
- return blockedTasks(this.world, namespace(v.namespace), v.scope, parent, limit(v.limit) ?? DEFAULT_TASK_LIMIT);
162
+ const selectedLimit = taskRowViewLimit(v.limit);
163
+ return blockedTasks(this.world, namespace(v.namespace), v.scope, parent, selectedLimit);
160
164
  }
161
165
  async query(input = {}) {
162
166
  const v = record(input, "query input");
@@ -173,13 +177,14 @@ class TasksHandle {
173
177
  }
174
178
  : normalizeTaskQuery(v.where);
175
179
  const selected = namespace(v.namespace);
180
+ const selectedLimit = taskRowViewLimit(v.limit);
176
181
  return queryTasks({
177
182
  world: this.world,
178
183
  ...(selected === undefined ? {} : { namespace: selected }),
179
184
  expression,
180
185
  ...(v.scope === undefined ? {} : { scope: v.scope }),
181
186
  sort: sort(v.sort) ?? "priority",
182
- limit: limit(v.limit) ?? DEFAULT_TASK_LIMIT,
187
+ limit: selectedLimit,
183
188
  });
184
189
  }
185
190
  async doctor() {
@@ -239,11 +244,6 @@ class TasksHandle {
239
244
  return composeTasks(local);
240
245
  }
241
246
  }
242
- export function tasksForExecution(world, execution) {
243
- if (typeof world !== "string")
244
- throw new TypeError("Tasks.of world must be a WorldRoot");
245
- return new TasksHandle(world, execution);
246
- }
247
247
  function tasksOfExecution(input) {
248
248
  if (input === undefined)
249
249
  return localExecutionContext();
@@ -253,6 +253,9 @@ function tasksOfExecution(input) {
253
253
  }
254
254
  export const Tasks = Object.freeze({
255
255
  of(world, input) {
256
- return tasksForExecution(world, tasksOfExecution(input));
256
+ const execution = tasksOfExecution(input);
257
+ if (typeof world !== "string")
258
+ throw new TypeError("Tasks.of world must be a WorldRoot");
259
+ return new TasksHandle(world, execution);
257
260
  },
258
261
  });
@@ -1,7 +1,7 @@
1
1
  import { type TaskPriority, type TaskState } from "./document.js";
2
2
  import { type TaskId } from "./identity.js";
3
3
  import type { AddTaskInput, UpdateTaskInput } from "./operations.js";
4
- import { type TaskQuerySort } from "./query.js";
4
+ import type { TaskQuerySort } from "./query.js";
5
5
  export declare function record(value: unknown, label: string): Record<string, unknown>;
6
6
  export declare function closed(value: Record<string, unknown>, allowed: readonly string[], label: string): void;
7
7
  export declare function taskId(value: unknown): TaskId;
@@ -12,6 +12,8 @@ export declare function text(value: unknown, label: string): string | undefined;
12
12
  export declare function actor(value: unknown): string | undefined;
13
13
  export declare function priority(value: unknown): TaskPriority | undefined;
14
14
  export declare function limit(value: unknown): number | undefined;
15
+ /** Validates and supplies the shared bounded-list limit for Task row views. */
16
+ export declare function taskRowViewLimit(value: unknown): number;
15
17
  export declare function sort(value: unknown): TaskQuerySort | undefined;
16
18
  export declare function state(value: unknown): TaskState | undefined;
17
19
  export declare function addInput(input: unknown): AddTaskInput;
@@ -1,5 +1,5 @@
1
1
  import { isTaskSegment, parseTaskId } from "./identity.js";
2
- import { isValidTaskLimit, MAX_TASK_LIMIT } from "./query.js";
2
+ import { boundedListLimit } from "../bounded-list.js";
3
3
  export function record(value, label) {
4
4
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
5
5
  throw new TypeError(`${label} must be an object`);
@@ -74,11 +74,14 @@ export function priority(value) {
74
74
  export function limit(value) {
75
75
  if (value === undefined)
76
76
  return undefined;
77
- if (typeof value !== "number" || !isValidTaskLimit(value)) {
78
- throw new TypeError(`limit must be an integer from 1 to ${MAX_TASK_LIMIT}`);
79
- }
77
+ if (typeof value !== "number")
78
+ throw new TypeError("limit must be a number");
80
79
  return value;
81
80
  }
81
+ /** Validates and supplies the shared bounded-list limit for Task row views. */
82
+ export function taskRowViewLimit(value) {
83
+ return boundedListLimit(value);
84
+ }
82
85
  export function sort(value) {
83
86
  if (value === undefined)
84
87
  return undefined;
@@ -0,0 +1,6 @@
1
+ import { type SettledTaskResult, type TaskBatchResult, type TaskLifecycleVerb, type TaskMutationResult } from "./operation-types.js";
2
+ import type { TaskId } from "./identity.js";
3
+ import type { WorldRoot } from "../world.js";
4
+ export declare function lifecycleTask(world: WorldRoot, id: TaskId, verb: TaskLifecycleVerb, signal?: AbortSignal, note?: string): Promise<TaskMutationResult>;
5
+ export declare function batchTasks(world: WorldRoot, verb: "start" | "done" | "drop" | "hold", ids: readonly TaskId[], signal?: AbortSignal, note?: string): Promise<TaskBatchResult>;
6
+ export declare function settleTask(world: WorldRoot, id: TaskId): Promise<SettledTaskResult>;
@@ -0,0 +1,116 @@
1
+ import { serializeTaskDocument } from "./document.js";
2
+ import { authorityBytesMatch, readBoard, replaceAuthority, withTaskLocks } from "./store.js";
3
+ import { advanceTaskTimestamp, taskView } from "./view.js";
4
+ const TRANSITIONS = {
5
+ start: { open: "in_progress" },
6
+ stop: { in_progress: "open" },
7
+ hold: { open: "on_hold", in_progress: "on_hold" },
8
+ resume: { on_hold: "open" },
9
+ done: { open: "done", in_progress: "done", on_hold: "done" },
10
+ drop: { open: "drop", in_progress: "drop", on_hold: "drop" },
11
+ };
12
+ function currentTaskBoard(board, bytes) {
13
+ return { board, bytes: new Map(bytes) };
14
+ }
15
+ function retry(reason) {
16
+ return { kind: "retry", reason };
17
+ }
18
+ async function transitionLifecycle(world, id, verb, currentBoard, options = {}) {
19
+ const { note, freshness = "none" } = options;
20
+ const current = currentBoard.board.tasks.get(id);
21
+ if (current === undefined) {
22
+ return freshness === "batch" && !(await authorityBytesMatch(world, id, null))
23
+ ? retry("concurrent-modification")
24
+ : { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
25
+ }
26
+ const state = TRANSITIONS[verb][current.state];
27
+ if (state === undefined) {
28
+ return freshness === "batch" && !(await authorityBytesMatch(world, id, currentBoard.bytes.get(id)))
29
+ ? retry("concurrent-modification")
30
+ : { kind: "refused", refusal: { kind: "invalid-lifecycle-transition", taskId: id, state: current.state, verb } };
31
+ }
32
+ const at = new Date().toISOString();
33
+ const next = {
34
+ ...current,
35
+ state,
36
+ ...(note === undefined ? {} : { note }),
37
+ updatedAt: advanceTaskTimestamp(current.updatedAt, at),
38
+ };
39
+ const bytes = serializeTaskDocument(next);
40
+ if ((await replaceAuthority({
41
+ world,
42
+ id,
43
+ expected: currentBoard.bytes.get(id),
44
+ next: bytes,
45
+ })) !== "replaced") {
46
+ return retry("concurrent-modification");
47
+ }
48
+ currentBoard.board = {
49
+ tasks: new Map(currentBoard.board.tasks).set(id, next),
50
+ };
51
+ currentBoard.bytes.set(id, bytes);
52
+ return { kind: "accepted", value: taskView(next) };
53
+ }
54
+ async function lifecycleFromCurrentBoard(world, id, verb, currentBoard, options = {}) {
55
+ const { signal, note } = options;
56
+ const result = await withTaskLocks({ world, allocation: false, ids: [id], ...(signal === undefined ? {} : { signal }) }, async () => transitionLifecycle(world, id, verb, currentBoard, {
57
+ freshness: "batch",
58
+ ...(note === undefined ? {} : { note }),
59
+ }));
60
+ return result === "busy" ? retry("busy") : result;
61
+ }
62
+ export async function lifecycleTask(world, id, verb, signal, note) {
63
+ const result = await withTaskLocks({ world, allocation: false, ids: [id], ...(signal === undefined ? {} : { signal }) }, async () => {
64
+ const snapshot = await readBoard(world);
65
+ const options = note === undefined ? {} : { note };
66
+ return transitionLifecycle(world, id, verb, currentTaskBoard(snapshot.board, snapshot.bytes), options);
67
+ });
68
+ return result === "busy" ? retry("busy") : result;
69
+ }
70
+ export async function batchTasks(world, verb, ids, signal, note) {
71
+ signal?.throwIfAborted();
72
+ const snapshot = await readBoard(world);
73
+ const currentBoard = currentTaskBoard(snapshot.board, snapshot.bytes);
74
+ const items = [];
75
+ for (const id of ids) {
76
+ signal?.throwIfAborted();
77
+ items.push({
78
+ id,
79
+ outcome: await lifecycleFromCurrentBoard(world, id, verb, currentBoard, {
80
+ ...(signal === undefined ? {} : { signal }),
81
+ ...(note === undefined ? {} : { note }),
82
+ }),
83
+ });
84
+ }
85
+ return { items };
86
+ }
87
+ export async function settleTask(world, id) {
88
+ const result = await withTaskLocks({ world, allocation: false, ids: [id] }, async () => {
89
+ const snapshot = await readBoard(world), current = snapshot.board.tasks.get(id);
90
+ if (current === undefined)
91
+ return { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
92
+ if (current.state === "done")
93
+ return { kind: "unchanged" };
94
+ if (current.state === "drop") {
95
+ return {
96
+ kind: "refused",
97
+ refusal: { kind: "invalid-lifecycle-transition", taskId: id, state: current.state, verb: "done" },
98
+ };
99
+ }
100
+ const next = {
101
+ ...current,
102
+ state: "done",
103
+ updatedAt: advanceTaskTimestamp(current.updatedAt, new Date().toISOString()),
104
+ };
105
+ const replaced = await replaceAuthority({
106
+ world,
107
+ id,
108
+ expected: snapshot.bytes.get(id),
109
+ next: serializeTaskDocument(next),
110
+ });
111
+ return replaced === "replaced"
112
+ ? { kind: "changed", task: taskView(next), action: "done" }
113
+ : { kind: "retry", reason: "concurrent-modification" };
114
+ });
115
+ return result === "busy" ? { kind: "retry", reason: "busy" } : result;
116
+ }