@astrosheep/keiyaku 4.6.7 → 4.6.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 (336) hide show
  1. package/README.md +46 -16
  2. package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
  3. package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
  4. package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
  5. package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
  6. package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
  7. package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
  8. package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
  9. package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
  10. package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
  11. package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
  12. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
  13. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
  14. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
  15. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
  16. package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
  17. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
  18. package/build/plugins/opencode/index.js +1 -1
  19. package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
  20. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
  21. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
  22. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
  23. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
  24. package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
  25. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
  26. package/build/plugins/pi/keiyaku.ts +0 -5
  27. package/build/skills/keiyaku/SKILL.md +5 -6
  28. package/build/skills/keiyaku-akuma/SKILL.md +1 -1
  29. package/build/skills/keiyaku-akuma/references/automation.md +8 -8
  30. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  31. package/build/skills/keiyaku-bind/SKILL.md +9 -9
  32. package/build/skills/keiyaku-debt/SKILL.md +91 -0
  33. package/build/skills/keiyaku-workflow/SKILL.md +2 -2
  34. package/build/src/akuma/akuma-call.d.ts +2 -0
  35. package/build/src/akuma/akuma-call.js +8 -2
  36. package/build/src/akuma/akuma-instance.d.ts +14 -1
  37. package/build/src/akuma/akuma-instance.js +37 -7
  38. package/build/src/akuma/akuma-observe.d.ts +33 -8
  39. package/build/src/akuma/akuma-observe.js +89 -63
  40. package/build/src/akuma/akuma-owner.d.ts +14 -2
  41. package/build/src/akuma/akuma-owner.js +49 -35
  42. package/build/src/akuma/akuma-selection-execution.js +9 -1
  43. package/build/src/akuma/akuma-stream.d.ts +22 -0
  44. package/build/src/akuma/akuma-stream.js +116 -0
  45. package/build/src/akuma/akuma-wait.d.ts +1 -40
  46. package/build/src/akuma/akuma-wait.js +23 -84
  47. package/build/src/akuma/akuma.d.ts +52 -16
  48. package/build/src/akuma/akuma.js +10 -10
  49. package/build/src/akuma/allowed.d.ts +7 -12
  50. package/build/src/akuma/allowed.js +13 -4
  51. package/build/src/akuma/archetype.d.ts +7 -15
  52. package/build/src/akuma/archetype.js +36 -35
  53. package/build/src/akuma/body-supervisor.d.ts +5 -5
  54. package/build/src/akuma/body-supervisor.js +22 -20
  55. package/build/src/akuma/body.d.ts +5 -3
  56. package/build/src/akuma/body.js +57 -8
  57. package/build/src/akuma/call-request.d.ts +30 -32
  58. package/build/src/akuma/call-request.js +10 -3
  59. package/build/src/akuma/caller.d.ts +39 -0
  60. package/build/src/akuma/caller.js +36 -0
  61. package/build/src/akuma/dispatch-association.d.ts +0 -1
  62. package/build/src/akuma/dispatch-association.js +0 -3
  63. package/build/src/akuma/heart/activity-schema.d.ts +12 -0
  64. package/build/src/akuma/heart/activity-schema.js +6 -0
  65. package/build/src/akuma/heart/facts.d.ts +16 -12
  66. package/build/src/akuma/heart/facts.js +8 -0
  67. package/build/src/akuma/heart/index.d.ts +61 -9
  68. package/build/src/akuma/heart/index.js +89 -24
  69. package/build/src/akuma/heart/rows.d.ts +3 -3
  70. package/build/src/akuma/heart/rows.js +5 -3
  71. package/build/src/akuma/heart/soul.d.ts +10 -1
  72. package/build/src/akuma/heart/soul.js +34 -24
  73. package/build/src/akuma/heart/storage.d.ts +20 -0
  74. package/build/src/akuma/heart/storage.js +62 -3
  75. package/build/src/akuma/heart/timeline.d.ts +7 -0
  76. package/build/src/akuma/heart/timeline.js +10 -0
  77. package/build/src/akuma/identity.d.ts +0 -1
  78. package/build/src/akuma/identity.js +2 -5
  79. package/build/src/akuma/index.d.ts +6 -2
  80. package/build/src/akuma/index.js +1 -0
  81. package/build/src/akuma/nuke.js +6 -28
  82. package/build/src/akuma/projection.d.ts +25 -11
  83. package/build/src/akuma/projection.js +24 -7
  84. package/build/src/akuma/provider-recipe.d.ts +18 -6
  85. package/build/src/akuma/provider-recipe.js +24 -1
  86. package/build/src/akuma/provider.d.ts +31 -10
  87. package/build/src/akuma/provider.js +105 -14
  88. package/build/src/akuma/providers/acp/events.js +29 -19
  89. package/build/src/akuma/providers/acp/index.js +2 -3
  90. package/build/src/akuma/providers/claude/events.js +110 -69
  91. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  92. package/build/src/akuma/providers/claude/index.js +4 -8
  93. package/build/src/akuma/providers/codex-app-server/events.js +17 -2
  94. package/build/src/akuma/providers/codex-app-server/index.js +17 -11
  95. package/build/src/akuma/providers/decode.d.ts +33 -0
  96. package/build/src/akuma/providers/decode.js +65 -0
  97. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  98. package/build/src/akuma/providers/execution-environment.js +3 -0
  99. package/build/src/akuma/providers/grok-build/index.js +16 -48
  100. package/build/src/akuma/providers/index.js +2 -0
  101. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  102. package/build/src/akuma/providers/lifecycle.js +10 -0
  103. package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
  104. package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
  105. package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
  106. package/build/src/akuma/providers/opencode-sdk/events.js +146 -296
  107. package/build/src/akuma/providers/opencode-sdk/index.js +270 -431
  108. package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
  109. package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
  110. package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
  111. package/build/src/akuma/providers/opencode-sdk/session.js +75 -84
  112. package/build/src/akuma/providers/paseo/events.d.ts +33 -0
  113. package/build/src/akuma/providers/paseo/events.js +204 -0
  114. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  115. package/build/src/akuma/providers/paseo/index.js +357 -0
  116. package/build/src/akuma/providers/pi/events.d.ts +2 -0
  117. package/build/src/akuma/providers/pi/events.js +36 -38
  118. package/build/src/akuma/providers/pi/index.js +21 -35
  119. package/build/src/akuma/publication.d.ts +2 -0
  120. package/build/src/akuma/publication.js +5 -0
  121. package/build/src/akuma/request-lifecycle.d.ts +4 -2
  122. package/build/src/akuma/request-lifecycle.js +27 -12
  123. package/build/src/akuma/request-rendezvous.js +38 -55
  124. package/build/src/akuma/request-serve.d.ts +1 -1
  125. package/build/src/akuma/request-serve.js +77 -113
  126. package/build/src/akuma/requests.d.ts +3 -1
  127. package/build/src/akuma/requests.js +32 -0
  128. package/build/src/akuma/selection-observation.d.ts +129 -53
  129. package/build/src/akuma/selection-observation.js +3 -9
  130. package/build/src/akuma/turn-drive.d.ts +3 -0
  131. package/build/src/akuma/turn-drive.js +28 -10
  132. package/build/src/akuma-body.js +12 -22
  133. package/build/src/cli/akuma-caller.d.ts +3 -0
  134. package/build/src/cli/akuma-caller.js +31 -0
  135. package/build/src/cli/commands/akuma-grammar.js +10 -16
  136. package/build/src/cli/commands/akuma.js +25 -55
  137. package/build/src/cli/commands/contract-grammar.d.ts +9 -7
  138. package/build/src/cli/commands/contract-grammar.js +40 -47
  139. package/build/src/cli/commands/contract-help.d.ts +17 -7
  140. package/build/src/cli/commands/contract-help.js +50 -11
  141. package/build/src/cli/commands/contract.js +34 -63
  142. package/build/src/cli/commands/debt-grammar.d.ts +19 -0
  143. package/build/src/cli/commands/debt-grammar.js +323 -0
  144. package/build/src/cli/commands/debt-query.d.ts +5 -0
  145. package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
  146. package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
  147. package/build/src/cli/commands/{task.js → debt.js} +87 -164
  148. package/build/src/cli/coordinates.d.ts +1 -1
  149. package/build/src/cli/coordinates.js +1 -1
  150. package/build/src/cli/parse.d.ts +5 -5
  151. package/build/src/cli/parse.js +17 -16
  152. package/build/src/cli/render/akuma-activity.d.ts +11 -83
  153. package/build/src/cli/render/akuma-activity.js +20 -382
  154. package/build/src/cli/render/catalog.d.ts +4 -7
  155. package/build/src/cli/render/catalog.js +5 -5
  156. package/build/src/cli/render/contract-history.js +3 -6
  157. package/build/src/cli/render/contract.js +17 -52
  158. package/build/src/cli/render/debt.d.ts +28 -0
  159. package/build/src/cli/render/{task.js → debt.js} +55 -133
  160. package/build/src/cli/render/kanshi.js +28 -28
  161. package/build/src/cli/render/marks.d.ts +5 -5
  162. package/build/src/cli/render/marks.js +4 -10
  163. package/build/src/cli/render/nuke.js +1 -1
  164. package/build/src/cli/render/receipt.js +3 -10
  165. package/build/src/cli/runtime.d.ts +1 -1
  166. package/build/src/cli/runtime.js +14 -20
  167. package/build/src/cli/scan.d.ts +1 -1
  168. package/build/src/cli/selectors.d.ts +3 -6
  169. package/build/src/cli/selectors.js +22 -53
  170. package/build/src/cli/usage.d.ts +1 -1
  171. package/build/src/cli/usage.js +4 -4
  172. package/build/src/contract-worktree.js +3 -3
  173. package/build/src/debt/board.d.ts +160 -0
  174. package/build/src/{task → debt}/board.js +89 -89
  175. package/build/src/debt/catalog.d.ts +11 -0
  176. package/build/src/debt/catalog.js +59 -0
  177. package/build/src/{task → debt}/context.d.ts +1 -1
  178. package/build/src/{task → debt}/context.js +1 -1
  179. package/build/src/{task → debt}/created-observation.d.ts +6 -10
  180. package/build/src/{task → debt}/created-observation.js +7 -7
  181. package/build/src/debt/document.d.ts +37 -0
  182. package/build/src/{task → debt}/document.js +37 -37
  183. package/build/src/debt/identity.d.ts +21 -0
  184. package/build/src/{task → debt}/identity.js +35 -35
  185. package/build/src/debt/index.d.ts +111 -0
  186. package/build/src/debt/index.js +203 -0
  187. package/build/src/{task → debt}/input.d.ts +8 -8
  188. package/build/src/{task → debt}/input.js +21 -21
  189. package/build/src/debt/lifecycle-operations.d.ts +6 -0
  190. package/build/src/{task → debt}/lifecycle-operations.js +27 -31
  191. package/build/src/debt/mutation-result.d.ts +981 -0
  192. package/build/src/debt/mutation-result.js +109 -0
  193. package/build/src/debt/mutation.d.ts +424 -0
  194. package/build/src/debt/mutation.js +223 -0
  195. package/build/src/debt/operation-types.d.ts +71 -0
  196. package/build/src/debt/operations.d.ts +28 -0
  197. package/build/src/{task → debt}/operations.js +59 -60
  198. package/build/src/debt/query.d.ts +76 -0
  199. package/build/src/{task → debt}/query.js +55 -55
  200. package/build/src/{task → debt}/store.d.ts +13 -13
  201. package/build/src/{task → debt}/store.js +58 -49
  202. package/build/src/debt/view.d.ts +4 -0
  203. package/build/src/debt/view.js +7 -0
  204. package/build/src/dispatch/index.d.ts +3 -3
  205. package/build/src/dispatch/index.js +1 -2
  206. package/build/src/git/observe.d.ts +6 -2
  207. package/build/src/git/observe.js +6 -2
  208. package/build/src/identity/coordinates.d.ts +1 -1
  209. package/build/src/index.d.ts +17 -17
  210. package/build/src/index.js +11 -11
  211. package/build/src/kanshi/index.d.ts +2 -2
  212. package/build/src/kanshi/read.js +54 -39
  213. package/build/src/kanshi/report.d.ts +7 -7
  214. package/build/src/kanshi/select.js +4 -4
  215. package/build/src/library/address.js +2 -4
  216. package/build/src/library/akuma-creation.d.ts +5 -1
  217. package/build/src/library/akuma-creation.js +27 -47
  218. package/build/src/library/akumas.d.ts +7 -7
  219. package/build/src/library/akumas.js +13 -9
  220. package/build/src/library/bind.d.ts +17 -17
  221. package/build/src/library/bind.js +16 -12
  222. package/build/src/library/contract-address.d.ts +9 -0
  223. package/build/src/library/contract-address.js +71 -0
  224. package/build/src/library/contract-composition.d.ts +4 -7
  225. package/build/src/library/contract-composition.js +6 -18
  226. package/build/src/library/contract-creation.d.ts +3 -5
  227. package/build/src/library/contract-creation.js +24 -22
  228. package/build/src/library/contract-execution.js +21 -26
  229. package/build/src/library/contract-outcomes.d.ts +2 -14
  230. package/build/src/library/contract-outcomes.js +2 -13
  231. package/build/src/library/contract-types.d.ts +38 -4
  232. package/build/src/library/delivery.d.ts +0 -2
  233. package/build/src/library/delivery.js +2 -5
  234. package/build/src/library/input.d.ts +2 -2
  235. package/build/src/library/input.js +5 -5
  236. package/build/src/library/invocation.js +2 -2
  237. package/build/src/library/keiyaku.d.ts +0 -5
  238. package/build/src/library/keiyaku.js +6 -12
  239. package/build/src/library/nuke.js +3 -3
  240. package/build/src/library/outcome.d.ts +626 -625
  241. package/build/src/library/outcome.js +13 -3
  242. package/build/src/library/reconcile.js +8 -16
  243. package/build/src/library/refusal.d.ts +2 -2
  244. package/build/src/library/repo.d.ts +3 -2
  245. package/build/src/library/repo.js +10 -5
  246. package/build/src/library/selection.d.ts +5 -8
  247. package/build/src/library/selection.js +22 -73
  248. package/build/src/plugin/akuma-signals.d.ts +2 -0
  249. package/build/src/plugin/akuma-signals.js +4 -0
  250. package/build/src/plugin/public.d.ts +32 -2
  251. package/build/src/plugin/runtime.js +5 -3
  252. package/build/src/protocol/amend.js +3 -2
  253. package/build/src/protocol/attempt.js +3 -8
  254. package/build/src/protocol/bind.d.ts +2 -2
  255. package/build/src/protocol/bind.js +1 -1
  256. package/build/src/protocol/deliver.js +3 -3
  257. package/build/src/protocol/operations.d.ts +1 -3
  258. package/build/src/protocol/operations.js +0 -8
  259. package/build/src/protocol/outcome.d.ts +1 -2
  260. package/build/src/protocol/outcome.js +1 -13
  261. package/build/src/protocol/placement.js +3 -10
  262. package/build/src/protocol/read/status.js +31 -70
  263. package/build/src/protocol/reintegrate.js +3 -10
  264. package/build/src/protocol/review.js +3 -3
  265. package/build/src/protocol/run.d.ts +5 -1
  266. package/build/src/protocol/run.js +3 -3
  267. package/build/src/runtime/proc/windows-launch.exe +0 -0
  268. package/build/src/settlement/fence.d.ts +3 -3
  269. package/build/src/settlement/fence.js +4 -4
  270. package/build/src/settlement/holder.d.ts +16 -16
  271. package/build/src/settlement/holder.js +69 -63
  272. package/build/src/settlement/settle.d.ts +5 -5
  273. package/build/src/settlement/settle.js +53 -53
  274. package/package.json +19 -9
  275. package/plugins/paseo/plugin/index.server.ts +17 -0
  276. package/plugins/paseo/plugin/paseo-plugin.json +4 -0
  277. package/plugins/paseo/plugin/server/attach.ts +52 -0
  278. package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
  279. package/plugins/paseo/plugin/server/message.ts +60 -0
  280. package/plugins/paseo/plugin/server/mirror.ts +193 -0
  281. package/plugins/paseo/plugin/server/model.ts +14 -0
  282. package/plugins/paseo/plugin/server/provider.ts +276 -0
  283. package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
  284. package/plugins/paseo/plugin/server/sdk.ts +289 -0
  285. package/plugins/paseo/plugin/server/stop.ts +26 -0
  286. package/plugins/paseo/plugin/server/transport.ts +35 -0
  287. package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
  288. package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
  289. package/plugins/paseo/plugin/tsconfig.json +6 -0
  290. package/plugins/pi/keiyaku.ts +57 -0
  291. package/skills/keiyaku/SKILL.md +43 -0
  292. package/skills/keiyaku-akuma/SKILL.md +130 -0
  293. package/skills/keiyaku-akuma/references/automation.md +269 -0
  294. package/skills/keiyaku-babysit/SKILL.md +65 -0
  295. package/skills/keiyaku-bind/SKILL.md +216 -0
  296. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  297. package/skills/keiyaku-debt/SKILL.md +91 -0
  298. package/skills/keiyaku-workflow/SKILL.md +129 -0
  299. package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
  300. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
  301. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
  302. package/build/skills/keiyaku-task/SKILL.md +0 -104
  303. package/build/src/cli/commands/amend.d.ts +0 -12
  304. package/build/src/cli/commands/amend.js +0 -10
  305. package/build/src/cli/commands/bind.d.ts +0 -11
  306. package/build/src/cli/commands/bind.js +0 -23
  307. package/build/src/cli/commands/task-grammar.d.ts +0 -19
  308. package/build/src/cli/commands/task-grammar.js +0 -384
  309. package/build/src/cli/commands/task-query.d.ts +0 -5
  310. package/build/src/cli/render/task.d.ts +0 -41
  311. package/build/src/dispatch/association.d.ts +0 -1
  312. package/build/src/dispatch/association.js +0 -1
  313. package/build/src/task/board.d.ts +0 -168
  314. package/build/src/task/catalog.d.ts +0 -11
  315. package/build/src/task/catalog.js +0 -59
  316. package/build/src/task/compose-language.d.ts +0 -57
  317. package/build/src/task/compose-language.js +0 -364
  318. package/build/src/task/compose-parser.d.ts +0 -32
  319. package/build/src/task/compose-parser.js +0 -180
  320. package/build/src/task/compose.d.ts +0 -16
  321. package/build/src/task/compose.js +0 -189
  322. package/build/src/task/document.d.ts +0 -39
  323. package/build/src/task/identity.d.ts +0 -21
  324. package/build/src/task/index.d.ts +0 -138
  325. package/build/src/task/index.js +0 -269
  326. package/build/src/task/lifecycle-operations.d.ts +0 -6
  327. package/build/src/task/mutation-result.d.ts +0 -1726
  328. package/build/src/task/mutation-result.js +0 -198
  329. package/build/src/task/mutation.d.ts +0 -590
  330. package/build/src/task/mutation.js +0 -262
  331. package/build/src/task/operation-types.d.ts +0 -71
  332. package/build/src/task/operations.d.ts +0 -28
  333. package/build/src/task/query.d.ts +0 -76
  334. package/build/src/task/view.d.ts +0 -4
  335. package/build/src/task/view.js +0 -7
  336. /package/build/src/{task → debt}/operation-types.js +0 -0
@@ -1,364 +0,0 @@
1
- import { occupiedLocalIds } from "./board.js";
2
- import { serializeTaskDocument } from "./document.js";
3
- import { allocateLocalId, deriveLocalStem, formatTaskId, parseTaskId } from "./identity.js";
4
- import { parseTaskComposition } from "./compose-parser.js";
5
- import { advanceTaskTimestamp } from "./operations.js";
6
- export function taskCompositionNamespaceHeader(markdown) {
7
- const parsed = parseTaskComposition(markdown);
8
- return {
9
- specified: parsed.namespaceSpecified,
10
- ...(parsed.namespace === undefined ? {} : { namespace: parsed.namespace }),
11
- };
12
- }
13
- function diagnostic(line, reason, token) {
14
- return { line, reason, token };
15
- }
16
- function createdTask(id, title, at, actor) {
17
- return {
18
- id,
19
- title,
20
- state: "open",
21
- priority: 2,
22
- needs: [],
23
- parent: null,
24
- supersedes: [],
25
- relates: [],
26
- note: "",
27
- ...(actor === undefined ? {} : { createdBy: actor }),
28
- createdAt: at,
29
- updatedAt: at,
30
- body: "",
31
- };
32
- }
33
- function aliasFor(node) {
34
- return node.assignments.find((item) => item.field === "as");
35
- }
36
- function allocateNodes(input, diagnostics) {
37
- const ids = occupiedLocalIds(input.board, input.namespace);
38
- const allocations = new Map();
39
- for (const node of input.parsed.nodes) {
40
- if (node.kind !== "new")
41
- continue;
42
- try {
43
- const localId = allocateLocalId(deriveLocalStem(node.title), ids);
44
- ids.add(localId);
45
- const id = formatTaskId({ namespace: input.namespace, localId });
46
- allocations.set(node.index, createdTask(id, node.title, input.at, input.actor));
47
- }
48
- catch (error) {
49
- diagnostics.push(diagnostic(node.line, error instanceof Error ? error.message : String(error), node.title));
50
- }
51
- }
52
- return allocations;
53
- }
54
- function collectAliases(nodes, allocations, diagnostics) {
55
- const aliases = new Map();
56
- for (const node of nodes) {
57
- const declarations = node.assignments.filter((item) => item.field === "as");
58
- for (const duplicate of declarations.slice(1)) {
59
- diagnostics.push(diagnostic(duplicate.line, "alias is assigned more than once", duplicate.token));
60
- }
61
- const declaration = declarations[0];
62
- if (declaration === undefined)
63
- continue;
64
- if (node.kind !== "new") {
65
- diagnostics.push(diagnostic(declaration.line, "only a new task may declare an alias", declaration.token));
66
- continue;
67
- }
68
- if (declaration.operator !== "=" || !/^[^\s,]+$/u.test(declaration.value)) {
69
- diagnostics.push(diagnostic(declaration.line, "alias must be a nonempty token without whitespace or comma", declaration.token));
70
- continue;
71
- }
72
- if (aliases.has(declaration.value)) {
73
- diagnostics.push(diagnostic(declaration.line, "alias must be unique in the composition", declaration.value));
74
- continue;
75
- }
76
- const allocated = allocations.get(node.index);
77
- if (allocated !== undefined)
78
- aliases.set(declaration.value, allocated.id);
79
- }
80
- return aliases;
81
- }
82
- function isTaskState(value) {
83
- return value === "open" || value === "in_progress" || value === "on_hold" || value === "done" || value === "drop";
84
- }
85
- function applyStateAssignment(node, current, assignment, scalar, diagnostics) {
86
- if (node.kind !== "new") {
87
- diagnostics.push(diagnostic(assignment.line, "only a new task may declare an initial state", assignment.token));
88
- return current;
89
- }
90
- if (scalar.has(assignment.field)) {
91
- diagnostics.push(diagnostic(assignment.line, "state is assigned more than once", assignment.token));
92
- return current;
93
- }
94
- scalar.add(assignment.field);
95
- if (assignment.operator !== "=" || !isTaskState(assignment.value)) {
96
- diagnostics.push(diagnostic(assignment.line, "state must use = with a valid persisted state", assignment.token));
97
- return current;
98
- }
99
- return { ...current, state: assignment.value };
100
- }
101
- function markScalarAssignment(assignment, scalar, diagnostics) {
102
- if (assignment.field !== "pri" && assignment.field !== "parent")
103
- return;
104
- if (scalar.has(assignment.field)) {
105
- diagnostics.push(diagnostic(assignment.line, `${assignment.field} is assigned more than once`, assignment.token));
106
- }
107
- scalar.add(assignment.field);
108
- }
109
- function resolveReference(raw, line, board, aliases, diagnostics) {
110
- if (raw.startsWith("^")) {
111
- const alias = raw.slice(1);
112
- const resolved = aliases.get(alias);
113
- if (resolved === undefined)
114
- diagnostics.push(diagnostic(line, "new-task alias is not declared", raw));
115
- return resolved;
116
- }
117
- if (!raw.startsWith("@task/")) {
118
- diagnostics.push(diagnostic(line, "reference must be @task/... or ^alias", raw));
119
- return undefined;
120
- }
121
- try {
122
- const id = raw.slice(1);
123
- parseTaskId(id);
124
- if (!board.tasks.has(id))
125
- diagnostics.push(diagnostic(line, "@ reference must name a pre-existing task", raw));
126
- return board.tasks.has(id) ? id : undefined;
127
- }
128
- catch (error) {
129
- diagnostics.push(diagnostic(line, error instanceof Error ? error.message : String(error), raw));
130
- return undefined;
131
- }
132
- }
133
- function referenceList(assignment, board, aliases, diagnostics) {
134
- if (assignment.value === "")
135
- return [];
136
- const raw = assignment.value.split(",").map((item) => item.trim());
137
- if (raw.some((item) => item.length === 0)) {
138
- diagnostics.push(diagnostic(assignment.line, "reference list contains an empty item", assignment.token));
139
- return undefined;
140
- }
141
- const resolved = raw.map((item) => resolveReference(item, assignment.line, board, aliases, diagnostics));
142
- if (resolved.some((item) => item === undefined))
143
- return undefined;
144
- const ids = resolved;
145
- if (new Set(ids).size !== ids.length) {
146
- diagnostics.push(diagnostic(assignment.line, "reference list contains a duplicate", assignment.token));
147
- return undefined;
148
- }
149
- return ids;
150
- }
151
- function patchRelation(current, assignment, values, diagnostics) {
152
- if (assignment.operator === "=")
153
- return values;
154
- if (assignment.operator === "+=")
155
- return [...current, ...values.filter((id) => !current.includes(id))];
156
- const missing = values.filter((id) => !current.includes(id));
157
- for (const id of missing)
158
- diagnostics.push(diagnostic(assignment.line, "cannot remove an absent relation", `@${id}`));
159
- return missing.length === 0 ? current.filter((id) => !values.includes(id)) : current;
160
- }
161
- function applyAssignments(node, base, board, aliases, diagnostics) {
162
- let next = base;
163
- const scalar = new Set();
164
- for (const assignment of node.assignments) {
165
- if (assignment.field === "as")
166
- continue;
167
- if (assignment.field === "state") {
168
- next = applyStateAssignment(node, next, assignment, scalar, diagnostics);
169
- continue;
170
- }
171
- markScalarAssignment(assignment, scalar, diagnostics);
172
- if (assignment.field === "pri") {
173
- if (assignment.operator !== "=" || !/^[0-3]$/u.test(assignment.value)) {
174
- diagnostics.push(diagnostic(assignment.line, "pri must use = with a value from 0 through 3", assignment.token));
175
- }
176
- else
177
- next = { ...next, priority: Number(assignment.value) };
178
- continue;
179
- }
180
- if (assignment.field === "parent") {
181
- if (assignment.operator !== "=") {
182
- diagnostics.push(diagnostic(assignment.line, "parent accepts only =", assignment.token));
183
- }
184
- else if (assignment.value === "")
185
- next = { ...next, parent: null };
186
- else {
187
- const id = resolveReference(assignment.value.trim(), assignment.line, board, aliases, diagnostics);
188
- if (id !== undefined)
189
- next = { ...next, parent: id };
190
- }
191
- continue;
192
- }
193
- const values = referenceList(assignment, board, aliases, diagnostics);
194
- if (values === undefined)
195
- continue;
196
- if (assignment.operator !== "=" && values.length === 0) {
197
- diagnostics.push(diagnostic(assignment.line, `${assignment.operator} requires at least one reference`, assignment.token));
198
- continue;
199
- }
200
- next = { ...next, [assignment.field]: patchRelation(next[assignment.field], assignment, values, diagnostics) };
201
- }
202
- if (node.body !== undefined)
203
- next = { ...next, body: node.body.value };
204
- for (const field of ["needs", "supersedes", "relates"]) {
205
- if (next[field].includes(next.id))
206
- diagnostics.push(diagnostic(node.line, `${field} cannot reference the task itself`, next.id));
207
- }
208
- if (next.parent === next.id)
209
- diagnostics.push(diagnostic(node.line, "parent cannot reference the task itself", next.id));
210
- return next;
211
- }
212
- function relationTargets(document, relation) {
213
- return relation === "needs" ? document.needs : document.parent === null ? [] : [document.parent];
214
- }
215
- function pathExists(board, start, goal, relation) {
216
- const seen = new Set();
217
- const pending = [start];
218
- while (pending.length > 0) {
219
- const id = pending.pop();
220
- if (id === goal)
221
- return true;
222
- if (seen.has(id))
223
- continue;
224
- seen.add(id);
225
- const task = board.tasks.get(id);
226
- if (task !== undefined)
227
- pending.push(...relationTargets(task, relation));
228
- }
229
- return false;
230
- }
231
- function diagnoseIntroducedCycles(after, tasks, diagnostics) {
232
- for (const task of tasks) {
233
- for (const relation of ["needs", "parent"]) {
234
- const old = task.before === null ? [] : relationTargets(task.before, relation);
235
- for (const target of relationTargets(task.after, relation)) {
236
- if (!old.includes(target) && pathExists(after, target, task.after.id, relation)) {
237
- diagnostics.push(diagnostic(task.line, `${relation} edge creates a cycle`, `${task.after.id} -> ${target}`));
238
- }
239
- }
240
- }
241
- }
242
- }
243
- function changed(task) {
244
- return (task.before === null ||
245
- !Buffer.from(serializeTaskDocument(task.before)).equals(Buffer.from(serializeTaskDocument(task.after))));
246
- }
247
- function stableAdmissionOrder(tasks, diagnostics) {
248
- const candidates = tasks.filter(changed);
249
- const byId = new Map(candidates.map((task) => [task.after.id, task]));
250
- const dependencies = new Map(candidates.map((task) => [task.after.id, new Set()]));
251
- for (const task of candidates) {
252
- const targets = [...task.after.needs, ...(task.after.parent === null ? [] : [task.after.parent])];
253
- for (const target of targets) {
254
- const plannedTarget = byId.get(target);
255
- if (plannedTarget?.before === null)
256
- dependencies.get(task.after.id).add(target);
257
- }
258
- }
259
- const remaining = new Set(candidates.map((task) => task.after.id));
260
- const ordered = [];
261
- while (remaining.size > 0) {
262
- const ready = candidates.find((task) => remaining.has(task.after.id) && [...dependencies.get(task.after.id)].every((id) => !remaining.has(id)));
263
- if (ready === undefined) {
264
- const first = candidates.find((task) => remaining.has(task.after.id));
265
- diagnostics.push(diagnostic(first.line, "needs and parent references create an admission cycle", first.after.id));
266
- return [];
267
- }
268
- remaining.delete(ready.after.id);
269
- ordered.push(ready);
270
- }
271
- return ordered;
272
- }
273
- function bodyPreview(node, title) {
274
- if (node.body?.kind !== "replace")
275
- return null;
276
- const lines = node.body.value.split(/\r\n|\n|\r/u);
277
- return {
278
- position: node.index + 1,
279
- title,
280
- bytes: Buffer.byteLength(node.body.value),
281
- firstLine: lines[0] ?? "",
282
- lastLine: lines.at(-1) ?? "",
283
- };
284
- }
285
- function planPresentation(ordered, tasks, parsed, aliases) {
286
- const aliasBindings = [...aliases].map(([alias, taskId]) => ({ alias, taskId }));
287
- const admissions = ordered.map((task) => task.kind === "new"
288
- ? {
289
- position: task.index + 1,
290
- kind: "new",
291
- ...(task.alias === undefined ? {} : { alias: task.alias }),
292
- title: task.after.title,
293
- taskId: task.after.id,
294
- }
295
- : { position: task.index + 1, kind: "existing", taskId: task.after.id, title: task.after.title });
296
- const bodies = parsed.nodes.flatMap((node) => {
297
- const task = tasks.find((candidate) => candidate.index === node.index);
298
- if (task === undefined)
299
- return [];
300
- const preview = bodyPreview(node, task.after.title);
301
- return preview === null ? [] : [preview];
302
- });
303
- return { aliases: aliasBindings, admissions, bodies };
304
- }
305
- export function planTaskComposition(input) {
306
- const parsed = parseTaskComposition(input.markdown);
307
- const diagnostics = [...parsed.diagnostics];
308
- const namespace = parsed.namespace ?? input.namespace;
309
- const allocationInput = {
310
- parsed,
311
- board: input.board,
312
- namespace,
313
- at: input.at,
314
- ...(input.actor === undefined ? {} : { actor: input.actor }),
315
- };
316
- const allocations = allocateNodes(allocationInput, diagnostics);
317
- const aliases = collectAliases(parsed.nodes, allocations, diagnostics);
318
- const addressed = new Set();
319
- const tasks = [];
320
- for (const node of parsed.nodes) {
321
- const before = node.kind === "new" ? null : (input.board.tasks.get(node.id) ?? null);
322
- const base = node.kind === "new" ? allocations.get(node.index) : before;
323
- if (base === null || base === undefined) {
324
- diagnostics.push(diagnostic(node.line, "existing task does not exist before composition", `@${node.id}`));
325
- continue;
326
- }
327
- if (addressed.has(base.id)) {
328
- diagnostics.push(diagnostic(node.line, "task is addressed more than once", base.id));
329
- continue;
330
- }
331
- addressed.add(base.id);
332
- let after = applyAssignments(node, base, input.board, aliases, diagnostics);
333
- if (before !== null && changed({ index: node.index, line: node.line, kind: node.kind, before, after })) {
334
- after = { ...after, updatedAt: advanceTaskTimestamp(before.updatedAt, input.at) };
335
- }
336
- tasks.push({
337
- index: node.index,
338
- line: node.line,
339
- kind: node.kind,
340
- ...(aliasFor(node) === undefined ? {} : { alias: aliasFor(node).value }),
341
- before,
342
- after,
343
- });
344
- }
345
- const post = new Map(input.board.tasks);
346
- for (const task of tasks)
347
- post.set(task.after.id, task.after);
348
- diagnoseIntroducedCycles({ tasks: post }, tasks, diagnostics);
349
- const ordered = stableAdmissionOrder(tasks, diagnostics);
350
- if (diagnostics.length > 0)
351
- return { kind: "refused", diagnostics };
352
- const presentation = planPresentation(ordered, tasks, parsed, aliases);
353
- return {
354
- kind: "planned",
355
- plan: {
356
- namespace,
357
- aliases: presentation.aliases,
358
- admissionOrder: ordered.map((task) => task.after.id),
359
- admissions: presentation.admissions,
360
- bodies: presentation.bodies,
361
- tasks: ordered,
362
- },
363
- };
364
- }
@@ -1,32 +0,0 @@
1
- import { type TaskId } from "./identity.js";
2
- import type { TaskCompositionDiagnostic } from "./operations.js";
3
- export type RelationField = "needs" | "supersedes" | "relates";
4
- export type Assignment = Readonly<{
5
- field: "as" | "state" | "parent" | "pri" | RelationField;
6
- operator: "=" | "+=" | "-=";
7
- value: string;
8
- line: number;
9
- token: string;
10
- }>;
11
- export type BodyAssignment = Readonly<{
12
- kind: "clear" | "replace";
13
- value: string;
14
- line: number;
15
- token: string;
16
- }>;
17
- export type ParsedNode = Readonly<{
18
- index: number;
19
- line: number;
20
- kind: "new" | "existing";
21
- title?: string;
22
- id?: TaskId;
23
- assignments: readonly Assignment[];
24
- body?: BodyAssignment;
25
- }>;
26
- export type ParsedComposition = Readonly<{
27
- namespace?: readonly string[];
28
- namespaceSpecified: boolean;
29
- nodes: readonly ParsedNode[];
30
- diagnostics: readonly TaskCompositionDiagnostic[];
31
- }>;
32
- export declare function parseTaskComposition(source: string): ParsedComposition;
@@ -1,180 +0,0 @@
1
- import { parseTaskId } from "./identity.js";
2
- function diagnostic(line, reason, token) {
3
- return { line, reason, token };
4
- }
5
- function sourceLines(source) {
6
- const lines = [];
7
- let start = 0;
8
- let number = 1;
9
- while (start < source.length) {
10
- let cursor = start;
11
- while (cursor < source.length && source[cursor] !== "\n" && source[cursor] !== "\r")
12
- cursor += 1;
13
- let end = cursor;
14
- if (source[cursor] === "\r" && source[cursor + 1] === "\n")
15
- end += 2;
16
- else if (cursor < source.length)
17
- end += 1;
18
- lines.push({ number, start, end, text: source.slice(start, cursor) });
19
- start = end;
20
- number += 1;
21
- }
22
- if (source.length === 0 || source.endsWith("\n") || source.endsWith("\r")) {
23
- lines.push({ number, start: source.length, end: source.length, text: "" });
24
- }
25
- return lines;
26
- }
27
- function withoutFenceSeparator(value) {
28
- if (value.endsWith("\r\n"))
29
- return value.slice(0, -2);
30
- if (value.endsWith("\n") || value.endsWith("\r"))
31
- return value.slice(0, -1);
32
- return value;
33
- }
34
- function parseNamespace(value) {
35
- if (value === "/")
36
- return [];
37
- if (value === "")
38
- throw new Error("empty compose namespace; use ns=/ for root");
39
- return parseTaskId(`task/${value}/placeholder`).namespace;
40
- }
41
- function parseAssignment(text, line) {
42
- const matched = /^(as|state|parent|pri|needs|supersedes|relates)\s*(=|\+=|-=)\s*(.*)$/u.exec(text);
43
- if (matched === null)
44
- return null;
45
- return {
46
- field: matched[1],
47
- operator: matched[2],
48
- value: matched[3],
49
- line,
50
- token: text,
51
- };
52
- }
53
- function parseNode(text, line, index) {
54
- if (text.startsWith("+ ")) {
55
- const title = text.slice(2);
56
- return title.trim().length === 0
57
- ? diagnostic(line, "new task title must be nonblank", text)
58
- : { index, line, kind: "new", title, assignments: [] };
59
- }
60
- if (!text.startsWith("@task/"))
61
- return diagnostic(line, "node must begin with + or @task/", text);
62
- try {
63
- const id = text.slice(1);
64
- parseTaskId(id);
65
- return { index, line, kind: "existing", id, assignments: [] };
66
- }
67
- catch (error) {
68
- return diagnostic(line, error instanceof Error ? error.message : String(error), text);
69
- }
70
- }
71
- function withAssignment(node, assignment) {
72
- return { ...node, assignments: [...node.assignments, assignment] };
73
- }
74
- function withBody(node, body) {
75
- return { ...node, body };
76
- }
77
- function replaceNode(nodes, node) {
78
- nodes[node.index] = node;
79
- }
80
- function parseBodyAssignment(input, diagnostics) {
81
- const fence = /^body\s+<<(.+)$/u.exec(input.text);
82
- if (fence !== null) {
83
- const token = fence[1];
84
- if (!/^[A-Z][A-Z0-9_]{2,31}$/u.test(token)) {
85
- diagnostics.push(diagnostic(input.line.number, "body token must match [A-Z][A-Z0-9_]* with length 3..32", token));
86
- return { handled: true };
87
- }
88
- const close = input.lines.findIndex((candidate, candidateIndex) => candidateIndex > input.index && candidate.text === token);
89
- if (close < 0) {
90
- diagnostics.push(diagnostic(input.line.number, "body fence is not closed", token));
91
- return { handled: true, stop: true };
92
- }
93
- const body = withoutFenceSeparator(input.source.slice(input.line.end, input.lines[close].start));
94
- if (input.current.body !== undefined) {
95
- diagnostics.push(diagnostic(input.line.number, "body is assigned more than once", input.text));
96
- return { handled: true, close };
97
- }
98
- return {
99
- handled: true,
100
- node: withBody(input.current, { kind: "replace", value: body, line: input.line.number, token }),
101
- close,
102
- };
103
- }
104
- if (!/^body\s*=\s*$/u.test(input.text))
105
- return { handled: false };
106
- if (input.current.body !== undefined) {
107
- diagnostics.push(diagnostic(input.line.number, "body is assigned more than once", input.text));
108
- return { handled: true };
109
- }
110
- return {
111
- handled: true,
112
- node: withBody(input.current, { kind: "clear", value: "", line: input.line.number, token: input.text }),
113
- };
114
- }
115
- export function parseTaskComposition(source) {
116
- const lines = sourceLines(source);
117
- const diagnostics = [];
118
- const nodes = [];
119
- let namespace;
120
- let current;
121
- let sawNode = false;
122
- let sawNamespace = false;
123
- for (let index = 0; index < lines.length; index += 1) {
124
- const line = lines[index];
125
- const text = line.text.trimStart();
126
- if (text.trim().length === 0)
127
- continue;
128
- if (text.startsWith("ns=")) {
129
- if (sawNode || sawNamespace)
130
- diagnostics.push(diagnostic(line.number, "namespace must be the first nonblank line", text));
131
- else {
132
- try {
133
- namespace = parseNamespace(text.slice(3));
134
- }
135
- catch (error) {
136
- diagnostics.push(diagnostic(line.number, error instanceof Error ? error.message : String(error), text));
137
- }
138
- }
139
- sawNamespace = true;
140
- continue;
141
- }
142
- if (text.startsWith("+ ") || text.startsWith("@task/")) {
143
- const parsed = parseNode(text, line.number, nodes.length);
144
- if ("reason" in parsed) {
145
- diagnostics.push(parsed);
146
- current = undefined;
147
- }
148
- else {
149
- nodes.push(parsed);
150
- current = parsed;
151
- }
152
- sawNode = true;
153
- continue;
154
- }
155
- if (current === undefined) {
156
- diagnostics.push(diagnostic(line.number, "property must follow a task node", text));
157
- continue;
158
- }
159
- const body = parseBodyAssignment({ text, line, index, lines, source, current }, diagnostics);
160
- if (body.handled) {
161
- if (body.node !== undefined) {
162
- current = body.node;
163
- replaceNode(nodes, current);
164
- }
165
- if (body.close !== undefined)
166
- index = body.close;
167
- if (body.stop === true)
168
- break;
169
- continue;
170
- }
171
- const assignment = parseAssignment(text, line.number);
172
- if (assignment === null)
173
- diagnostics.push(diagnostic(line.number, "unknown compose property", text));
174
- else {
175
- current = withAssignment(current, assignment);
176
- replaceNode(nodes, current);
177
- }
178
- }
179
- return { ...(namespace === undefined ? {} : { namespace }), namespaceSpecified: sawNamespace, nodes, diagnostics };
180
- }
@@ -1,16 +0,0 @@
1
- import type { WorldRoot } from "../world.js";
2
- import type { TaskCompositionResult } from "./mutation-result.js";
3
- import { type AcceptedComposition } from "./compose-language.js";
4
- export type { TaskCompositionAdmission, TaskCompositionBodyPreview, TaskCompositionPlanAlias, TaskCompositionPlanOrder, } from "./compose-language.js";
5
- export type { TaskCompositionAlias } from "./compose-language.js";
6
- export type TaskDocumentChange = Readonly<AcceptedComposition["documentChanges"][number]>;
7
- export type TaskCompositionFacts = Readonly<Pick<AcceptedComposition, "aliases" | "admissionOrder" | "admissions">>;
8
- export type { TaskCompositionResult } from "./mutation-result.js";
9
- export declare function composeTasks(input: Readonly<{
10
- world: WorldRoot;
11
- markdown: string;
12
- signal?: AbortSignal;
13
- actor?: string;
14
- defaultNamespace?: readonly string[];
15
- planOnly?: boolean;
16
- }>): Promise<TaskCompositionResult>;