@astrosheep/keiyaku 4.6.8 → 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 (253) hide show
  1. package/README.md +40 -14
  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/skills/keiyaku/SKILL.md +5 -6
  27. package/build/skills/keiyaku-akuma/SKILL.md +1 -1
  28. package/build/skills/keiyaku-akuma/references/automation.md +8 -8
  29. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  30. package/build/skills/keiyaku-bind/SKILL.md +9 -9
  31. package/build/skills/keiyaku-debt/SKILL.md +91 -0
  32. package/build/skills/keiyaku-workflow/SKILL.md +2 -2
  33. package/build/src/akuma/akuma-instance.d.ts +2 -0
  34. package/build/src/akuma/akuma-instance.js +10 -0
  35. package/build/src/akuma/akuma-observe.d.ts +33 -8
  36. package/build/src/akuma/akuma-observe.js +88 -64
  37. package/build/src/akuma/akuma-owner.d.ts +11 -2
  38. package/build/src/akuma/akuma-owner.js +45 -35
  39. package/build/src/akuma/akuma-selection-execution.js +9 -1
  40. package/build/src/akuma/akuma-stream.d.ts +22 -0
  41. package/build/src/akuma/akuma-stream.js +116 -0
  42. package/build/src/akuma/akuma-wait.d.ts +1 -40
  43. package/build/src/akuma/akuma-wait.js +23 -84
  44. package/build/src/akuma/akuma.d.ts +17 -11
  45. package/build/src/akuma/akuma.js +2 -0
  46. package/build/src/akuma/allowed.d.ts +7 -12
  47. package/build/src/akuma/allowed.js +13 -4
  48. package/build/src/akuma/body-supervisor.d.ts +5 -5
  49. package/build/src/akuma/body-supervisor.js +22 -20
  50. package/build/src/akuma/body.js +28 -1
  51. package/build/src/akuma/call-request.d.ts +12 -22
  52. package/build/src/akuma/heart/activity-schema.d.ts +12 -0
  53. package/build/src/akuma/heart/activity-schema.js +6 -0
  54. package/build/src/akuma/heart/index.d.ts +59 -2
  55. package/build/src/akuma/heart/index.js +87 -8
  56. package/build/src/akuma/heart/rows.js +5 -3
  57. package/build/src/akuma/heart/soul.d.ts +9 -0
  58. package/build/src/akuma/heart/soul.js +29 -0
  59. package/build/src/akuma/heart/storage.d.ts +15 -0
  60. package/build/src/akuma/heart/storage.js +55 -0
  61. package/build/src/akuma/heart/timeline.d.ts +7 -0
  62. package/build/src/akuma/heart/timeline.js +10 -0
  63. package/build/src/akuma/index.d.ts +1 -0
  64. package/build/src/akuma/projection.d.ts +25 -0
  65. package/build/src/akuma/projection.js +24 -7
  66. package/build/src/akuma/provider-recipe.d.ts +11 -0
  67. package/build/src/akuma/provider-recipe.js +23 -0
  68. package/build/src/akuma/provider.d.ts +25 -0
  69. package/build/src/akuma/provider.js +99 -7
  70. package/build/src/akuma/providers/acp/events.js +25 -2
  71. package/build/src/akuma/providers/claude/events.js +76 -10
  72. package/build/src/akuma/providers/claude/index.js +2 -5
  73. package/build/src/akuma/providers/codex-app-server/events.js +17 -2
  74. package/build/src/akuma/providers/codex-app-server/index.js +15 -9
  75. package/build/src/akuma/providers/decode.d.ts +8 -0
  76. package/build/src/akuma/providers/decode.js +21 -0
  77. package/build/src/akuma/providers/grok-build/index.js +10 -26
  78. package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
  79. package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
  80. package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
  81. package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
  82. package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
  83. package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
  84. package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
  85. package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
  86. package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
  87. package/build/src/akuma/providers/paseo/events.d.ts +8 -0
  88. package/build/src/akuma/providers/paseo/events.js +58 -11
  89. package/build/src/akuma/providers/paseo/index.js +11 -7
  90. package/build/src/akuma/providers/pi/events.d.ts +2 -0
  91. package/build/src/akuma/providers/pi/events.js +32 -24
  92. package/build/src/akuma/providers/pi/index.js +21 -35
  93. package/build/src/akuma/request-lifecycle.d.ts +1 -2
  94. package/build/src/akuma/request-lifecycle.js +2 -8
  95. package/build/src/akuma/request-rendezvous.js +38 -55
  96. package/build/src/akuma/request-serve.d.ts +1 -1
  97. package/build/src/akuma/request-serve.js +77 -113
  98. package/build/src/akuma/selection-observation.d.ts +57 -51
  99. package/build/src/akuma/selection-observation.js +3 -3
  100. package/build/src/akuma/turn-drive.d.ts +3 -0
  101. package/build/src/akuma/turn-drive.js +26 -5
  102. package/build/src/akuma-body.js +12 -22
  103. package/build/src/cli/akuma-caller.js +10 -0
  104. package/build/src/cli/commands/akuma-grammar.js +3 -4
  105. package/build/src/cli/commands/akuma.js +13 -51
  106. package/build/src/cli/commands/contract-grammar.d.ts +7 -6
  107. package/build/src/cli/commands/contract-grammar.js +27 -32
  108. package/build/src/cli/commands/contract-help.d.ts +16 -7
  109. package/build/src/cli/commands/contract-help.js +20 -11
  110. package/build/src/cli/commands/contract.js +11 -11
  111. package/build/src/cli/commands/debt-grammar.d.ts +19 -0
  112. package/build/src/cli/commands/debt-grammar.js +323 -0
  113. package/build/src/cli/commands/debt-query.d.ts +5 -0
  114. package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
  115. package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
  116. package/build/src/cli/commands/{task.js → debt.js} +83 -143
  117. package/build/src/cli/coordinates.d.ts +1 -1
  118. package/build/src/cli/coordinates.js +1 -1
  119. package/build/src/cli/parse.d.ts +4 -4
  120. package/build/src/cli/parse.js +17 -16
  121. package/build/src/cli/render/akuma-activity.d.ts +11 -83
  122. package/build/src/cli/render/akuma-activity.js +20 -382
  123. package/build/src/cli/render/catalog.d.ts +2 -2
  124. package/build/src/cli/render/catalog.js +5 -5
  125. package/build/src/cli/render/contract.js +2 -2
  126. package/build/src/cli/render/debt.d.ts +28 -0
  127. package/build/src/cli/render/{task.js → debt.js} +51 -112
  128. package/build/src/cli/render/kanshi.js +28 -28
  129. package/build/src/cli/render/marks.d.ts +5 -5
  130. package/build/src/cli/render/marks.js +4 -10
  131. package/build/src/cli/render/nuke.js +1 -1
  132. package/build/src/cli/runtime.js +3 -3
  133. package/build/src/cli/scan.d.ts +1 -1
  134. package/build/src/cli/usage.d.ts +1 -1
  135. package/build/src/cli/usage.js +4 -4
  136. package/build/src/contract-worktree.js +3 -3
  137. package/build/src/debt/board.d.ts +160 -0
  138. package/build/src/{task → debt}/board.js +89 -89
  139. package/build/src/debt/catalog.d.ts +11 -0
  140. package/build/src/debt/catalog.js +59 -0
  141. package/build/src/{task → debt}/context.d.ts +1 -1
  142. package/build/src/{task → debt}/context.js +1 -1
  143. package/build/src/{task → debt}/created-observation.d.ts +6 -10
  144. package/build/src/{task → debt}/created-observation.js +7 -7
  145. package/build/src/debt/document.d.ts +37 -0
  146. package/build/src/{task → debt}/document.js +37 -37
  147. package/build/src/debt/identity.d.ts +21 -0
  148. package/build/src/{task → debt}/identity.js +35 -35
  149. package/build/src/debt/index.d.ts +111 -0
  150. package/build/src/debt/index.js +203 -0
  151. package/build/src/{task → debt}/input.d.ts +8 -8
  152. package/build/src/{task → debt}/input.js +21 -21
  153. package/build/src/debt/lifecycle-operations.d.ts +6 -0
  154. package/build/src/{task → debt}/lifecycle-operations.js +27 -31
  155. package/build/src/debt/mutation-result.d.ts +981 -0
  156. package/build/src/debt/mutation-result.js +109 -0
  157. package/build/src/debt/mutation.d.ts +424 -0
  158. package/build/src/debt/mutation.js +223 -0
  159. package/build/src/debt/operation-types.d.ts +71 -0
  160. package/build/src/debt/operations.d.ts +28 -0
  161. package/build/src/{task → debt}/operations.js +59 -60
  162. package/build/src/debt/query.d.ts +76 -0
  163. package/build/src/{task → debt}/query.js +55 -55
  164. package/build/src/{task → debt}/store.d.ts +13 -13
  165. package/build/src/{task → debt}/store.js +58 -49
  166. package/build/src/debt/view.d.ts +4 -0
  167. package/build/src/debt/view.js +7 -0
  168. package/build/src/identity/coordinates.d.ts +1 -1
  169. package/build/src/index.d.ts +13 -13
  170. package/build/src/index.js +9 -9
  171. package/build/src/kanshi/index.d.ts +1 -1
  172. package/build/src/kanshi/read.js +33 -33
  173. package/build/src/kanshi/report.d.ts +7 -7
  174. package/build/src/kanshi/select.js +4 -4
  175. package/build/src/library/akumas.d.ts +2 -3
  176. package/build/src/library/bind.d.ts +3 -3
  177. package/build/src/library/bind.js +5 -5
  178. package/build/src/library/contract-creation.js +5 -5
  179. package/build/src/library/contract-execution.js +4 -4
  180. package/build/src/library/contract-types.d.ts +2 -2
  181. package/build/src/library/input.d.ts +2 -2
  182. package/build/src/library/input.js +5 -5
  183. package/build/src/library/invocation.js +2 -2
  184. package/build/src/library/nuke.js +3 -3
  185. package/build/src/library/outcome.d.ts +126 -126
  186. package/build/src/library/outcome.js +3 -3
  187. package/build/src/library/selection.d.ts +1 -4
  188. package/build/src/library/selection.js +11 -62
  189. package/build/src/plugin/public.d.ts +5 -0
  190. package/build/src/plugin/runtime.js +3 -1
  191. package/build/src/runtime/proc/windows-launch.exe +0 -0
  192. package/build/src/settlement/fence.d.ts +3 -3
  193. package/build/src/settlement/fence.js +4 -4
  194. package/build/src/settlement/holder.d.ts +16 -16
  195. package/build/src/settlement/holder.js +69 -63
  196. package/build/src/settlement/settle.d.ts +5 -5
  197. package/build/src/settlement/settle.js +53 -53
  198. package/package.json +12 -6
  199. package/plugins/paseo/plugin/index.server.ts +17 -0
  200. package/plugins/paseo/plugin/paseo-plugin.json +4 -0
  201. package/plugins/paseo/plugin/server/attach.ts +52 -0
  202. package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
  203. package/plugins/paseo/plugin/server/message.ts +60 -0
  204. package/plugins/paseo/plugin/server/mirror.ts +193 -0
  205. package/plugins/paseo/plugin/server/model.ts +14 -0
  206. package/plugins/paseo/plugin/server/provider.ts +276 -0
  207. package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
  208. package/plugins/paseo/plugin/server/sdk.ts +289 -0
  209. package/plugins/paseo/plugin/server/stop.ts +26 -0
  210. package/plugins/paseo/plugin/server/transport.ts +35 -0
  211. package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
  212. package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
  213. package/plugins/paseo/plugin/tsconfig.json +6 -0
  214. package/skills/keiyaku/SKILL.md +5 -6
  215. package/skills/keiyaku-akuma/SKILL.md +1 -1
  216. package/skills/keiyaku-akuma/references/automation.md +8 -8
  217. package/skills/keiyaku-babysit/SKILL.md +1 -1
  218. package/skills/keiyaku-bind/SKILL.md +9 -9
  219. package/skills/keiyaku-debt/SKILL.md +91 -0
  220. package/skills/keiyaku-workflow/SKILL.md +2 -2
  221. package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
  222. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
  223. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
  224. package/build/skills/keiyaku-task/SKILL.md +0 -104
  225. package/build/src/cli/commands/task-grammar.d.ts +0 -19
  226. package/build/src/cli/commands/task-grammar.js +0 -384
  227. package/build/src/cli/commands/task-query.d.ts +0 -5
  228. package/build/src/cli/render/task.d.ts +0 -39
  229. package/build/src/task/board.d.ts +0 -168
  230. package/build/src/task/catalog.d.ts +0 -11
  231. package/build/src/task/catalog.js +0 -59
  232. package/build/src/task/compose-language.d.ts +0 -57
  233. package/build/src/task/compose-language.js +0 -364
  234. package/build/src/task/compose-parser.d.ts +0 -32
  235. package/build/src/task/compose-parser.js +0 -180
  236. package/build/src/task/compose.d.ts +0 -16
  237. package/build/src/task/compose.js +0 -189
  238. package/build/src/task/document.d.ts +0 -39
  239. package/build/src/task/identity.d.ts +0 -21
  240. package/build/src/task/index.d.ts +0 -138
  241. package/build/src/task/index.js +0 -269
  242. package/build/src/task/lifecycle-operations.d.ts +0 -6
  243. package/build/src/task/mutation-result.d.ts +0 -1726
  244. package/build/src/task/mutation-result.js +0 -198
  245. package/build/src/task/mutation.d.ts +0 -590
  246. package/build/src/task/mutation.js +0 -262
  247. package/build/src/task/operation-types.d.ts +0 -71
  248. package/build/src/task/operations.d.ts +0 -28
  249. package/build/src/task/query.d.ts +0 -76
  250. package/build/src/task/view.d.ts +0 -4
  251. package/build/src/task/view.js +0 -7
  252. package/skills/keiyaku-task/SKILL.md +0 -104
  253. /package/build/src/{task → debt}/operation-types.js +0 -0
@@ -0,0 +1,223 @@
1
+ import { World } from "../world.js";
2
+ import { requestBodyCommand } from "../akuma/request-rendezvous.js";
3
+ import { eraseRequestCommand, } from "../akuma/request-wire.js";
4
+ import { debtIdsSchema, debtNamespaceSchema } from "./identity.js";
5
+ import { debtNonblankTextSchema, debtStateSchema, debtPrioritySchema } from "./document.js";
6
+ import { debtBatchResultSchema, debtMutationIdSchema, debtMutationResultSchema, debtUpdateResultSchema, } from "./mutation-result.js";
7
+ import { z } from "zod";
8
+ export const DEBT_MUTATION_ACTIONS = Object.freeze([
9
+ "debt.add",
10
+ "debt.addDocument",
11
+ "debt.done",
12
+ "debt.drop",
13
+ "debt.update",
14
+ ]);
15
+ const debtMutationActionSchema = z.enum(DEBT_MUTATION_ACTIONS);
16
+ const nonemptyDebtIdsSchema = debtIdsSchema.unwrap().min(1).readonly();
17
+ const addInputSchema = z
18
+ .object({
19
+ title: debtNonblankTextSchema,
20
+ namespace: debtNamespaceSchema,
21
+ body: z.string().optional(),
22
+ note: z.string().optional(),
23
+ state: debtStateSchema.optional(),
24
+ priority: debtPrioritySchema.optional(),
25
+ needs: debtIdsSchema.optional(),
26
+ parent: debtMutationIdSchema.nullable().optional(),
27
+ supersedes: debtIdsSchema.optional(),
28
+ relates: debtIdsSchema.optional(),
29
+ })
30
+ .strict();
31
+ const updateInputSchema = z
32
+ .object({
33
+ title: debtNonblankTextSchema.optional(),
34
+ body: z.string().optional(),
35
+ appendBody: z.string().optional(),
36
+ note: z.string().optional(),
37
+ priority: debtPrioritySchema.optional(),
38
+ needs: debtIdsSchema.optional(),
39
+ addNeeds: debtIdsSchema.optional(),
40
+ dropNeeds: debtIdsSchema.optional(),
41
+ parent: debtMutationIdSchema.nullable().optional(),
42
+ supersedes: debtIdsSchema.optional(),
43
+ addSupersedes: debtIdsSchema.optional(),
44
+ dropSupersedes: debtIdsSchema.optional(),
45
+ relates: debtIdsSchema.optional(),
46
+ addRelates: debtIdsSchema.optional(),
47
+ dropRelates: debtIdsSchema.optional(),
48
+ })
49
+ .strict()
50
+ .superRefine((input, context) => {
51
+ if (input.body !== undefined && input.appendBody !== undefined)
52
+ context.addIssue({ code: "custom", message: "body and appendBody are mutually exclusive" });
53
+ if (Object.values(input).every((value) => value === undefined))
54
+ context.addIssue({ code: "custom", message: "update requires at least one field change" });
55
+ });
56
+ const addRequestSchema = z
57
+ .object({ input: addInputSchema })
58
+ .strict()
59
+ .transform(({ input }) => ({ action: "debt.add", input }));
60
+ const addDocumentRequestSchema = z
61
+ .object({ input: z.object({ markdown: z.string(), namespace: debtNamespaceSchema }).strict() })
62
+ .strict()
63
+ .transform(({ input }) => ({ action: "debt.addDocument", input }));
64
+ const updateRequestSchema = z
65
+ .object({ id: debtMutationIdSchema, input: updateInputSchema })
66
+ .strict()
67
+ .transform((request) => ({ action: "debt.update", ...request }));
68
+ const terminalRequestSchema = (action) => z.union([
69
+ z
70
+ .object({ id: debtMutationIdSchema, note: z.string().optional() })
71
+ .strict()
72
+ .transform(({ id, note }) => ({ action, id, ...(note === undefined ? {} : { note }) })),
73
+ z
74
+ .object({ ids: nonemptyDebtIdsSchema, note: z.string().optional() })
75
+ .strict()
76
+ .transform(({ ids, note }) => ({ action, ids, ...(note === undefined ? {} : { note }) })),
77
+ ]);
78
+ const debtRequestSchemas = {
79
+ "debt.add": addRequestSchema,
80
+ "debt.addDocument": addDocumentRequestSchema,
81
+ "debt.done": terminalRequestSchema("debt.done"),
82
+ "debt.drop": terminalRequestSchema("debt.drop"),
83
+ "debt.update": updateRequestSchema,
84
+ };
85
+ const worldPathSchema = z.string().min(1);
86
+ const debtBodyRequestSchema = z
87
+ .object({ world: worldPathSchema, request: z.union(Object.values(debtRequestSchemas)) })
88
+ .strict();
89
+ const debtMutationServiceSchema = z.object({ action: debtMutationActionSchema }).strict();
90
+ export const forwardedDebtReferenceSchema = z
91
+ .object({ kind: z.literal("served-reference"), action: debtMutationActionSchema })
92
+ .strict();
93
+ function decodeDebtBodyRequest(action, value) {
94
+ const parsed = debtBodyRequestSchema.extend({ request: debtRequestSchemas[action] }).safeParse(value);
95
+ return parsed.success ? parsed.data : null;
96
+ }
97
+ function decodeDebtService(action, value) {
98
+ const parsed = debtMutationServiceSchema.safeParse(value);
99
+ if (!parsed.success || parsed.data.action !== action)
100
+ throw new Error(`malformed stored Debt service evidence for ${action}`);
101
+ return parsed.data;
102
+ }
103
+ function decodeDebtReference(action, value) {
104
+ const parsed = forwardedDebtReferenceSchema.safeParse(value);
105
+ if (!parsed.success || parsed.data.action !== action)
106
+ throw new Error(`malformed Debt service reference for ${action}`);
107
+ return parsed.data;
108
+ }
109
+ /** Debt owns forwarded mutation payload, live result, and durable service evidence. */
110
+ export function debtMutationRequestProtocol(action, batch) {
111
+ return {
112
+ action,
113
+ encodeRequest: (input) => {
114
+ const { action: _action, ...request } = input.request;
115
+ return { world: input.world, request };
116
+ },
117
+ decodeRequest: (value) => decodeDebtBodyRequest(action, value),
118
+ encodeResult: (result) => result,
119
+ decodeResult: (result) => {
120
+ const schema = action === "debt.update"
121
+ ? debtUpdateResultSchema
122
+ : batch === undefined
123
+ ? z.union([debtMutationResultSchema, debtBatchResultSchema])
124
+ : batch
125
+ ? debtBatchResultSchema
126
+ : debtMutationResultSchema;
127
+ const parsed = schema.safeParse(result);
128
+ if (!parsed.success)
129
+ throw new Error(`transport integrity: Debt ${action} returned an invalid live result`);
130
+ return parsed.data;
131
+ },
132
+ decodeReference: (reference) => decodeDebtReference(action, reference),
133
+ isPermitted: (allowed) => allowed.includes(action),
134
+ };
135
+ }
136
+ export function debtMutationRequestCommand(action, port) {
137
+ return {
138
+ completion: "service",
139
+ protocol: debtMutationRequestProtocol(action),
140
+ encodeService: (service) => service,
141
+ decodeService: (service) => decodeDebtService(action, service),
142
+ projectService: (service) => ({ kind: "served-reference", action: service.action }),
143
+ execute: async (request, facts) => {
144
+ const world = await World.prove(request.world);
145
+ const action = request.request.action;
146
+ let result;
147
+ switch (action) {
148
+ case "debt.add":
149
+ result = await port.add({
150
+ world,
151
+ options: addDebtOptions(request.request.input, facts.requester, facts.signal),
152
+ });
153
+ break;
154
+ case "debt.addDocument":
155
+ result = await port.addDocument({
156
+ world,
157
+ document: { ...request.request.input, actor: facts.requester, signal: facts.signal },
158
+ });
159
+ break;
160
+ case "debt.update":
161
+ result = await port.update({
162
+ world,
163
+ id: request.request.id,
164
+ options: updateDebtOptions(request.request.input, facts.signal),
165
+ });
166
+ break;
167
+ case "debt.done":
168
+ case "debt.drop": {
169
+ const verb = action.slice("debt.".length);
170
+ const note = "note" in request.request ? request.request.note : undefined;
171
+ result =
172
+ "ids" in request.request
173
+ ? await port.batch({
174
+ world,
175
+ verb,
176
+ ids: request.request.ids,
177
+ ...(note === undefined ? {} : { note }),
178
+ signal: facts.signal,
179
+ })
180
+ : await port.lifecycle({
181
+ world,
182
+ verb,
183
+ id: request.request.id,
184
+ ...(note === undefined ? {} : { note }),
185
+ signal: facts.signal,
186
+ });
187
+ break;
188
+ }
189
+ }
190
+ return { kind: "served", result, service: { action } };
191
+ },
192
+ };
193
+ }
194
+ export function debtMutationRequestCommands(port) {
195
+ return Object.fromEntries(DEBT_MUTATION_ACTIONS.map((action) => [action, eraseRequestCommand(debtMutationRequestCommand(action, port))]));
196
+ }
197
+ export async function requestForwardedDebt(input) {
198
+ const response = await requestBodyCommand({
199
+ directory: input.directory,
200
+ ...(input.id === undefined ? {} : { id: input.id }),
201
+ command: debtMutationRequestProtocol(input.request.action, "ids" in input.request),
202
+ value: { world: input.world, request: input.request },
203
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
204
+ });
205
+ if (response.kind === "reference")
206
+ return response.reference;
207
+ return response.result;
208
+ }
209
+ /** Absent optional fields are omitted, never republished as an explicit undefined. */
210
+ function definedFields(fields, additions = {}) {
211
+ const selected = {};
212
+ for (const [key, value] of Object.entries({ ...fields, ...additions })) {
213
+ if (value !== undefined)
214
+ selected[key] = value;
215
+ }
216
+ return selected;
217
+ }
218
+ function addDebtOptions(input, actor, signal) {
219
+ return definedFields(input, { actor, signal });
220
+ }
221
+ function updateDebtOptions(input, signal) {
222
+ return definedFields(input, { signal });
223
+ }
@@ -0,0 +1,71 @@
1
+ import type { DebtPriority, DebtState } from "./document.js";
2
+ import type { DebtId } from "./identity.js";
3
+ import type { DebtCleanupFailure, DebtRefusal, DebtRetry, DebtView } from "./mutation-result.js";
4
+ export type { DebtView, DebtCleanupFailure, DebtRefusal, DebtRetry, DebtMutationResult, DebtUpdateResult, DebtBatchResult, } from "./mutation-result.js";
5
+ export type DebtOutcome<A> = Readonly<{
6
+ kind: "accepted";
7
+ value: A;
8
+ cleanup?: DebtCleanupFailure;
9
+ }> | Readonly<{
10
+ kind: "refused";
11
+ refusal: DebtRefusal;
12
+ }> | Readonly<{
13
+ kind: "retry";
14
+ reason: DebtRetry;
15
+ }>;
16
+ export type DebtLifecycleVerb = Extract<DebtRefusal, {
17
+ kind: "invalid-lifecycle-transition";
18
+ }>["verb"];
19
+ export type SettledDebtAction = "done";
20
+ export type SettledDebtResult = Readonly<{
21
+ kind: "changed";
22
+ debt: DebtView;
23
+ action: SettledDebtAction;
24
+ cleanup?: DebtCleanupFailure;
25
+ }> | Readonly<{
26
+ kind: "unchanged";
27
+ }> | Readonly<{
28
+ kind: "refused";
29
+ refusal: DebtRefusal;
30
+ }> | Readonly<{
31
+ kind: "retry";
32
+ reason: DebtRetry;
33
+ }>;
34
+ export type AddDebtInput = Readonly<{
35
+ title: string;
36
+ namespace?: readonly string[];
37
+ body?: string;
38
+ note?: string;
39
+ state?: DebtState;
40
+ priority?: DebtPriority;
41
+ needs?: readonly DebtId[];
42
+ parent?: DebtId | null;
43
+ supersedes?: readonly DebtId[];
44
+ relates?: readonly DebtId[];
45
+ actor?: string;
46
+ signal?: AbortSignal;
47
+ }>;
48
+ export type AddDebtDocumentInput = Readonly<{
49
+ markdown: string;
50
+ namespace?: readonly string[];
51
+ actor?: string;
52
+ signal?: AbortSignal;
53
+ }>;
54
+ export type UpdateDebtInput = Readonly<{
55
+ title?: string;
56
+ body?: string;
57
+ appendBody?: string;
58
+ note?: string;
59
+ priority?: DebtPriority;
60
+ needs?: readonly DebtId[];
61
+ addNeeds?: readonly DebtId[];
62
+ dropNeeds?: readonly DebtId[];
63
+ parent?: DebtId | null;
64
+ supersedes?: readonly DebtId[];
65
+ addSupersedes?: readonly DebtId[];
66
+ dropSupersedes?: readonly DebtId[];
67
+ relates?: readonly DebtId[];
68
+ addRelates?: readonly DebtId[];
69
+ dropRelates?: readonly DebtId[];
70
+ signal?: AbortSignal;
71
+ }>;
@@ -0,0 +1,28 @@
1
+ import { type BlockedDebtRow, type DebtBoardObservation, type DebtDetailFacts, type DebtRow } from "./board.js";
2
+ import { type DebtId } from "./identity.js";
3
+ import type { WorldRoot } from "../world.js";
4
+ import { type DebtPage, type DebtQueryExpression, type DebtQueryRow, type DebtQuerySort } from "./query.js";
5
+ export { debtView } from "./view.js";
6
+ export type { AddDebtDocumentInput, AddDebtInput, DebtCleanupFailure, SettledDebtResult, DebtBatchResult, DebtMutationResult, DebtOutcome, DebtRefusal, DebtRetry, DebtUpdateResult, DebtView, UpdateDebtInput, } from "./operation-types.js";
7
+ import type { AddDebtDocumentInput, AddDebtInput, DebtMutationResult, DebtOutcome, DebtUpdateResult, UpdateDebtInput } from "./operation-types.js";
8
+ export declare function nukeDebt(world: WorldRoot, options?: Readonly<{
9
+ timeoutMs?: number;
10
+ onRemoved?(count: number): void;
11
+ }>): Promise<number>;
12
+ export declare function addDebt(world: WorldRoot, input: AddDebtInput): Promise<DebtMutationResult>;
13
+ export declare function addDebtDocument(world: WorldRoot, input: AddDebtDocumentInput): Promise<DebtMutationResult>;
14
+ export declare function updateDebt(world: WorldRoot, id: DebtId, input: UpdateDebtInput): Promise<DebtUpdateResult>;
15
+ export { batchDebts, lifecycleDebt, settleDebt } from "./lifecycle-operations.js";
16
+ export declare function listDebts(world: WorldRoot, namespace: readonly string[] | undefined, selection: "active" | "closed" | "all", scope?: "namespace" | "world", limit?: number): Promise<DebtOutcome<DebtPage<DebtRow>>>;
17
+ export declare function readDebtDetail(world: WorldRoot, id: DebtId): Promise<DebtDetailFacts | null>;
18
+ export declare function readyDebts(world: WorldRoot, namespace: readonly string[] | undefined, scope?: "namespace" | "world", parent?: DebtId, limit?: number): Promise<DebtOutcome<DebtPage<DebtRow>>>;
19
+ export declare function blockedDebts(world: WorldRoot, namespace: readonly string[] | undefined, scope?: "namespace" | "world", parent?: DebtId, limit?: number): Promise<DebtOutcome<DebtPage<BlockedDebtRow>>>;
20
+ export declare function queryDebts(input: Readonly<{
21
+ world: WorldRoot;
22
+ namespace?: readonly string[];
23
+ expression: DebtQueryExpression;
24
+ scope?: "namespace" | "world";
25
+ sort?: DebtQuerySort;
26
+ limit?: number;
27
+ }>): Promise<DebtOutcome<DebtPage<DebtQueryRow>>>;
28
+ export declare function observeDebtBoard(world: WorldRoot): Promise<DebtBoardObservation>;
@@ -1,17 +1,17 @@
1
1
  import { SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
2
2
  import { documentDiff } from "../markdown/diff.js";
3
- import { createTaskRelations, projectOwnedDetailFacts, projectTaskBoardObservation, relationProblem, projectBlocked, projectRows, occupiedLocalIds, } from "./board.js";
4
- import { parseTaskCreationDocument, serializeTaskDocument, } from "./document.js";
5
- import { allocateLocalId, deriveLocalStem, formatTaskId } from "./identity.js";
6
- import { nukeTaskAuthority, readBoard, readTaskDocument, replaceAuthority, withTaskLocks } from "./store.js";
3
+ import { createDebtRelations, projectOwnedDetailFacts, projectDebtBoardObservation, relationProblem, projectBlocked, projectRows, occupiedLocalIds, } from "./board.js";
4
+ import { parseDebtCreationDocument, serializeDebtDocument, } from "./document.js";
5
+ import { allocateLocalId, deriveLocalStem, formatDebtId } from "./identity.js";
6
+ import { nukeDebtAuthority, readBoard, readDebtDocument, replaceAuthority, withDebtLocks } from "./store.js";
7
7
  import { boundedListLimit, projectBoundedList } from "../bounded-list.js";
8
8
  import { projectQuery, projectQueryRows, queryUnderTargets, underExpression, } from "./query.js";
9
- import { advanceTaskTimestamp, taskView } from "./view.js";
10
- export { advanceTaskTimestamp, taskView } from "./view.js";
11
- export async function nukeTask(world, options) {
12
- const result = await nukeTaskAuthority(world, options);
9
+ import { advanceDebtTimestamp, debtView } from "./view.js";
10
+ export { debtView } from "./view.js";
11
+ export async function nukeDebt(world, options) {
12
+ const result = await nukeDebtAuthority(world, options);
13
13
  if (result === "busy")
14
- throw new SqliteTransactionLockError("Task reset lock contention", "timeout");
14
+ throw new SqliteTransactionLockError("Debt reset lock contention", "timeout");
15
15
  return result;
16
16
  }
17
17
  function refused(refusal) {
@@ -23,26 +23,25 @@ function retry(reason) {
23
23
  function currentTimestamp() {
24
24
  return new Date().toISOString();
25
25
  }
26
- /** Internal Task timestamp rule shared by ordinary mutations and compose. */
27
26
  function addDocument(base, namespace, board, at, actor) {
28
27
  const localId = allocateLocalId(deriveLocalStem(base.title), occupiedLocalIds(board, namespace));
29
28
  return {
30
29
  ...base,
31
- id: formatTaskId({ namespace, localId }),
30
+ id: formatDebtId({ namespace, localId }),
32
31
  ...(actor === undefined ? {} : { createdBy: actor }),
33
32
  createdAt: at,
34
33
  updatedAt: at,
35
34
  };
36
35
  }
37
36
  function boardWith(board, document) {
38
- const tasks = new Map(board.tasks);
39
- tasks.set(document.id, document);
40
- return { tasks };
37
+ const debts = new Map(board.debts);
38
+ debts.set(document.id, document);
39
+ return { debts };
41
40
  }
42
41
  async function create(world, base, namespace, signal, actor) {
43
42
  let result;
44
43
  try {
45
- result = await withTaskLocks({ world, allocation: true, ids: [], ...(signal === undefined ? {} : { signal }) }, async () => {
44
+ result = await withDebtLocks({ world, allocation: true, ids: [], ...(signal === undefined ? {} : { signal }) }, async () => {
46
45
  const snapshot = await readBoard(world), next = addDocument(base, namespace, snapshot.board, currentTimestamp(), actor);
47
46
  const problem = relationProblem(boardWith(snapshot.board, next), null, next);
48
47
  if (problem !== null)
@@ -51,22 +50,22 @@ async function create(world, base, namespace, signal, actor) {
51
50
  world,
52
51
  id: next.id,
53
52
  expected: null,
54
- next: serializeTaskDocument(next),
53
+ next: serializeDebtDocument(next),
55
54
  });
56
55
  return replaced === "replaced"
57
- ? { kind: "accepted", value: taskView(next) }
56
+ ? { kind: "accepted", value: debtView(next) }
58
57
  : retry("concurrent-modification");
59
58
  });
60
59
  }
61
60
  catch (error) {
62
61
  if (error instanceof TypeError &&
63
- /task identity (?:cannot fit the physical filename budget|contains a Windows-reserved physical segment)/u.test(error.message))
62
+ /debt identity (?:cannot fit the physical filename budget|contains a Windows-reserved physical segment)/u.test(error.message))
64
63
  return refused({ kind: "invalid-namespace-context", path: namespace.join("/") });
65
64
  throw error;
66
65
  }
67
66
  return result === "busy" ? retry("busy") : result;
68
67
  }
69
- export async function addTask(world, input) {
68
+ export async function addDebt(world, input) {
70
69
  const namespace = input.namespace ?? [];
71
70
  return create(world, {
72
71
  title: input.title,
@@ -80,9 +79,9 @@ export async function addTask(world, input) {
80
79
  relates: input.relates ?? [],
81
80
  }, namespace, input.signal, input.actor);
82
81
  }
83
- export async function addTaskDocument(world, input) {
82
+ export async function addDebtDocument(world, input) {
84
83
  const namespace = input.namespace ?? [];
85
- return create(world, parseTaskCreationDocument(input.markdown), namespace, input.signal, input.actor);
84
+ return create(world, parseDebtCreationDocument(input.markdown), namespace, input.signal, input.actor);
86
85
  }
87
86
  function listChange(current, replacement, additions, removals) {
88
87
  const next = [...(replacement ?? current)];
@@ -92,9 +91,9 @@ function listChange(current, replacement, additions, removals) {
92
91
  return next.filter((id) => !(removals ?? []).includes(id));
93
92
  }
94
93
  function relatedOwner(board, id, target) {
95
- return board.tasks.get(target)?.relates.includes(id) ? target : null;
94
+ return board.debts.get(target)?.relates.includes(id) ? target : null;
96
95
  }
97
- function appendTaskBody(current, addition) {
96
+ function appendDebtBody(current, addition) {
98
97
  if (current.length === 0 || addition.length === 0 || current.endsWith("\n") || addition.startsWith("\n")) {
99
98
  return current + addition;
100
99
  }
@@ -105,12 +104,12 @@ function updateDocument(board, current, input) {
105
104
  if (!current.relates.includes(related)) {
106
105
  const owner = relatedOwner(board, current.id, related);
107
106
  if (owner !== null)
108
- return { kind: "relation-owned-by-other", taskId: current.id, related, declaringTask: owner };
107
+ return { kind: "relation-owned-by-other", debtId: current.id, related, declaringDebt: owner };
109
108
  }
110
109
  return {
111
110
  ...current,
112
111
  ...(input.title === undefined ? {} : { title: input.title }),
113
- body: input.body ?? (input.appendBody === undefined ? current.body : appendTaskBody(current.body, input.appendBody)),
112
+ body: input.body ?? (input.appendBody === undefined ? current.body : appendDebtBody(current.body, input.appendBody)),
114
113
  ...(input.note === undefined ? {} : { note: input.note }),
115
114
  ...(input.priority === undefined ? {} : { priority: input.priority }),
116
115
  needs: listChange(current.needs, input.needs, input.addNeeds, input.dropNeeds),
@@ -141,11 +140,11 @@ function updateFieldChanges(current, next, input) {
141
140
  }
142
141
  return changes;
143
142
  }
144
- export async function updateTask(world, id, input) {
145
- const result = await withTaskLocks({ world, allocation: false, ids: [id], ...(input.signal === undefined ? {} : { signal: input.signal }) }, async () => {
146
- const snapshot = await readBoard(world), current = snapshot.board.tasks.get(id);
143
+ export async function updateDebt(world, id, input) {
144
+ const result = await withDebtLocks({ world, allocation: false, ids: [id], ...(input.signal === undefined ? {} : { signal: input.signal }) }, async () => {
145
+ const snapshot = await readBoard(world), current = snapshot.board.debts.get(id);
147
146
  if (current === undefined)
148
- return { kind: "refused", refusal: { kind: "task-missing", taskId: id } };
147
+ return { kind: "refused", refusal: { kind: "debt-missing", debtId: id } };
149
148
  const candidate = updateDocument(snapshot.board, current, input);
150
149
  if ("kind" in candidate)
151
150
  return { kind: "refused", refusal: candidate };
@@ -154,13 +153,13 @@ export async function updateTask(world, id, input) {
154
153
  return { kind: "refused", refusal: { kind: "invalid-graph", diagnostic: problem } };
155
154
  const predecessor = snapshot.bytes.get(id);
156
155
  const before = Buffer.from(predecessor).toString("utf8");
157
- const changed = !Buffer.from(serializeTaskDocument(candidate)).equals(Buffer.from(predecessor));
156
+ const changed = !Buffer.from(serializeDebtDocument(candidate)).equals(Buffer.from(predecessor));
158
157
  let next = candidate;
159
158
  if (changed) {
160
159
  const at = currentTimestamp();
161
- next = { ...candidate, updatedAt: advanceTaskTimestamp(current.updatedAt, at) };
160
+ next = { ...candidate, updatedAt: advanceDebtTimestamp(current.updatedAt, at) };
162
161
  }
163
- const afterBytes = serializeTaskDocument(next);
162
+ const afterBytes = serializeDebtDocument(next);
164
163
  const after = Buffer.from(afterBytes).toString("utf8");
165
164
  if (before !== after &&
166
165
  (await replaceAuthority({ world, id, expected: predecessor, next: afterBytes })) !== "replaced") {
@@ -170,7 +169,7 @@ export async function updateTask(world, id, input) {
170
169
  return {
171
170
  kind: "accepted",
172
171
  value: {
173
- task: taskView(next),
172
+ debt: debtView(next),
174
173
  documentDiff: documentDiff(label, label, before, after),
175
174
  changedFields: updateFieldChanges(current, next, input),
176
175
  },
@@ -178,45 +177,45 @@ export async function updateTask(world, id, input) {
178
177
  });
179
178
  return result === "busy" ? { kind: "retry", reason: "busy" } : result;
180
179
  }
181
- export { batchTasks, lifecycleTask, settleTask } from "./lifecycle-operations.js";
180
+ export { batchDebts, lifecycleDebt, settleDebt } from "./lifecycle-operations.js";
182
181
  function readScope(namespace, scope) {
183
182
  return scope === "world" ? null : (namespace ?? []);
184
183
  }
185
- export async function listTasks(world, namespace, selection, scope, limit) {
184
+ export async function listDebts(world, namespace, selection, scope, limit) {
186
185
  const selectedLimit = boundedListLimit(limit);
187
186
  const selected = readScope(namespace, scope);
188
187
  const board = (await readBoard(world)).board;
189
188
  return {
190
189
  kind: "accepted",
191
- value: projectBoundedList(projectRows(board, createTaskRelations(board), selected, selection), selectedLimit),
190
+ value: projectBoundedList(projectRows(board, createDebtRelations(board), selected, selection), selectedLimit),
192
191
  };
193
192
  }
194
- export async function readTaskDetail(world, id) {
195
- const task = await readTaskDocument(world, id);
196
- if (task === undefined)
193
+ export async function readDebtDetail(world, id) {
194
+ const debt = await readDebtDocument(world, id);
195
+ if (debt === undefined)
197
196
  return null;
198
- const selected = new Map([[id, task]]);
197
+ const selected = new Map([[id, debt]]);
199
198
  const references = [
200
- ...task.needs,
201
- ...(task.parent === null ? [] : [task.parent]),
202
- ...task.supersedes,
203
- ...task.relates,
199
+ ...debt.needs,
200
+ ...(debt.parent === null ? [] : [debt.parent]),
201
+ ...debt.supersedes,
202
+ ...debt.relates,
204
203
  ];
205
204
  for (const reference of references) {
206
205
  if (selected.has(reference))
207
206
  continue;
208
- const document = await readTaskDocument(world, reference);
207
+ const document = await readDebtDocument(world, reference);
209
208
  if (document !== undefined)
210
209
  selected.set(reference, document);
211
210
  }
212
- return projectOwnedDetailFacts({ tasks: selected }, id);
211
+ return projectOwnedDetailFacts({ debts: selected }, id);
213
212
  }
214
213
  /** One board observation and predicate projection shared by the ready and blocked views. */
215
- async function readTaskQueryContext(input) {
214
+ async function readDebtQueryContext(input) {
216
215
  const board = (await readBoard(input.world)).board;
217
- if (input.parent !== undefined && !board.tasks.has(input.parent))
218
- return { kind: "refused", refusal: { kind: "task-missing", taskId: input.parent } };
219
- const relations = createTaskRelations(board);
216
+ if (input.parent !== undefined && !board.debts.has(input.parent))
217
+ return { kind: "refused", refusal: { kind: "debt-missing", debtId: input.parent } };
218
+ const relations = createDebtRelations(board);
220
219
  const scope = readScope(input.namespace, input.scope);
221
220
  const predicate = {
222
221
  kind: "predicate",
@@ -236,15 +235,15 @@ async function readTaskQueryContext(input) {
236
235
  },
237
236
  };
238
237
  }
239
- export async function readyTasks(world, namespace, scope, parent, limit) {
240
- const queried = await readTaskQueryContext({ world, field: "ready", namespace, scope, parent, limit });
238
+ export async function readyDebts(world, namespace, scope, parent, limit) {
239
+ const queried = await readDebtQueryContext({ world, field: "ready", namespace, scope, parent, limit });
241
240
  if (queried.kind !== "accepted")
242
241
  return queried;
243
242
  const rows = queried.value.rows.map(({ parent: _parent, needs: _needs, blocks: _blocks, createdAt: _createdAt, ...row }) => row);
244
243
  return { kind: "accepted", value: projectBoundedList(rows, queried.value.limit) };
245
244
  }
246
- export async function blockedTasks(world, namespace, scope, parent, limit) {
247
- const queried = await readTaskQueryContext({ world, field: "blocked", namespace, scope, parent, limit });
245
+ export async function blockedDebts(world, namespace, scope, parent, limit) {
246
+ const queried = await readDebtQueryContext({ world, field: "blocked", namespace, scope, parent, limit });
248
247
  if (queried.kind !== "accepted")
249
248
  return queried;
250
249
  const { board, scope: selected, relations, limit: selectedLimit, rows } = queried.value;
@@ -254,14 +253,14 @@ export async function blockedTasks(world, namespace, scope, parent, limit) {
254
253
  value: projectBoundedList(projectBlocked(board, selected, relations).filter((row) => ids.has(row.id)), selectedLimit),
255
254
  };
256
255
  }
257
- export async function queryTasks(input) {
256
+ export async function queryDebts(input) {
258
257
  const selectedLimit = boundedListLimit(input.limit);
259
258
  const selected = readScope(input.namespace, input.scope);
260
259
  const board = (await readBoard(input.world)).board;
261
- const relations = createTaskRelations(board);
260
+ const relations = createDebtRelations(board);
262
261
  for (const target of queryUnderTargets(input.expression))
263
- if (!board.tasks.has(target)) {
264
- return { kind: "refused", refusal: { kind: "task-missing", taskId: target } };
262
+ if (!board.debts.has(target)) {
263
+ return { kind: "refused", refusal: { kind: "debt-missing", debtId: target } };
265
264
  }
266
265
  return {
267
266
  kind: "accepted",
@@ -273,6 +272,6 @@ export async function queryTasks(input) {
273
272
  }),
274
273
  };
275
274
  }
276
- export async function observeTaskBoard(world) {
277
- return projectTaskBoardObservation((await readBoard(world)).board);
275
+ export async function observeDebtBoard(world) {
276
+ return projectDebtBoardObservation((await readBoard(world)).board);
278
277
  }