@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,116 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+ import { abortableDelay } from "./abort.js";
3
+ import { AkumaNotBornError } from "./akuma-errors.js";
4
+ import { OBSERVATION_POLL_MS } from "./akuma-observe.js";
5
+ import { createTimelineReader } from "./heart/index.js";
6
+ import { projectTurns, selectHistory } from "./projection.js";
7
+ /** The fixed number of projected rows one window retains. */
8
+ const STREAM_WINDOW = 500;
9
+ /**
10
+ * The private end-of-observation reason. It is deliberately not the caller's
11
+ * abort reason: a returned observation completes, while an aborted one keeps
12
+ * the caller's own failure.
13
+ */
14
+ const STREAM_RETURN = Symbol("akuma-stream-return");
15
+ /**
16
+ * Announce each retained outcome identity once per observation, keeping only
17
+ * the identities the current window still carries, so a long stream remembers
18
+ * a bounded set rather than every outcome it ever saw.
19
+ */
20
+ async function announceOutcomes(id, rows, observed, observe) {
21
+ const outcomes = new Set(rows.flatMap((row) => (row.kind === "outcome" ? [row.outcome.historyId] : [])));
22
+ const fresh = [...outcomes].filter((historyId) => !observed.has(historyId));
23
+ if (fresh.length > 0)
24
+ await observe?.(id, fresh);
25
+ return outcomes;
26
+ }
27
+ /**
28
+ * The observation loop itself. It decodes the retained timeline through the
29
+ * existing Turn projection on every pull and answers with the whole latest
30
+ * bounded window, holding only that window and one reader. Complete windows
31
+ * coalesce; they are not lossless event delivery, and the existing retention
32
+ * metadata keeps its honest meaning.
33
+ */
34
+ async function* observeTimeline(paths, id, signal, observe) {
35
+ const reader = createTimelineReader(paths);
36
+ let released = false;
37
+ const release = () => {
38
+ if (released)
39
+ return;
40
+ released = true;
41
+ reader.clear();
42
+ };
43
+ let observedOutcomes = new Set();
44
+ let previous;
45
+ signal.addEventListener("abort", release, { once: true });
46
+ try {
47
+ for (;;) {
48
+ signal.throwIfAborted();
49
+ const read = await reader.read(signal);
50
+ signal.throwIfAborted();
51
+ if (read.changed) {
52
+ if (!read.born)
53
+ throw new AkumaNotBornError(id);
54
+ const { rows, lowestRetained, highest } = read.slice;
55
+ const snapshot = selectHistory(projectTurns(rows, { lowestRetained, highest }), { limit: STREAM_WINDOW });
56
+ if (previous === undefined || !isDeepStrictEqual(snapshot, previous)) {
57
+ observedOutcomes = await announceOutcomes(id, snapshot.rows, observedOutcomes, observe);
58
+ previous = snapshot;
59
+ yield snapshot;
60
+ }
61
+ }
62
+ await abortableDelay(OBSERVATION_POLL_MS, signal);
63
+ }
64
+ }
65
+ finally {
66
+ signal.removeEventListener("abort", release);
67
+ release();
68
+ }
69
+ }
70
+ /**
71
+ * The one continuous timeline observation as its caller sees it: pull-driven,
72
+ * so a slow consumer accumulates no queue.
73
+ *
74
+ * The observation runs behind this wrapper because a bare async generator
75
+ * cannot honour an end request while a pull is pending: `return()` would queue
76
+ * behind a pull that an idle timeline never settles, and the observation would
77
+ * hold its reader and its polling timer forever. The wrapper owns an internal
78
+ * controller instead, and the observation watches the caller's cancellation
79
+ * composed with it. `return` aborts that controller, which settles the pending
80
+ * poll and lets the loop release its reader in the same turn; because a
81
+ * composed signal keeps the reason of whichever source aborted first, an end
82
+ * request reads as completion while a caller's own abort keeps its own failure.
83
+ */
84
+ export function createAkumaStream(paths, id, options = {}, observe) {
85
+ const caller = options.signal;
86
+ const control = new AbortController();
87
+ const signal = caller === undefined ? control.signal : AbortSignal.any([caller, control.signal]);
88
+ const observation = observeTimeline(paths, id, signal, observe);
89
+ let returning;
90
+ const next = async () => {
91
+ if (returning !== undefined)
92
+ return { done: true, value: undefined };
93
+ try {
94
+ return await observation.next();
95
+ }
96
+ catch (error) {
97
+ // An end request is completion, not the caller's failure to see.
98
+ if (signal.reason === STREAM_RETURN)
99
+ return { done: true, value: undefined };
100
+ throw error;
101
+ }
102
+ };
103
+ const end = (value) => {
104
+ if (returning === undefined) {
105
+ control.abort(STREAM_RETURN);
106
+ returning = observation.return(value).then((result) => ({ done: true, value: result.value }));
107
+ }
108
+ return returning;
109
+ };
110
+ const iterator = {
111
+ [Symbol.asyncIterator]: () => iterator,
112
+ next,
113
+ return: end,
114
+ };
115
+ return iterator;
116
+ }
@@ -1,30 +1,7 @@
1
- import type { AkumaAlias } from "../identity/selector.js";
2
1
  import type { WorldRoot } from "../world.js";
3
2
  import { type OutcomeObserver, type WaitReason } from "./akuma-observe.js";
4
3
  import type { AkumaStatus } from "./akuma.js";
5
- import type { DispatchAssociation } from "./dispatch-association.js";
6
- import type { ActivityRow } from "./projection.js";
7
4
  import type { AkumaUnobserved } from "./selection-observation.js";
8
- export type WaitIdentityFacts = Readonly<{
9
- /** The alias currently addressing this Akuma in its world, when one is bound to it. */
10
- alias?: AkumaAlias;
11
- /** This Akuma's Dispatch association, read from the observing repository. */
12
- contract: DispatchAssociation;
13
- }>;
14
- /** One observed Akuma as a live wait viewer sees it: its status plus its identity facts. */
15
- export type WaitObservedAkuma = Readonly<{
16
- status: AkumaStatus;
17
- rows: readonly ActivityRow[];
18
- }> & WaitIdentityFacts;
19
- /** One selected Akuma's frozen identity, resolved before the first observation round. */
20
- export type WaitSelectedAkuma = Readonly<{
21
- id: AkumaStatus["id"];
22
- }> & WaitIdentityFacts;
23
- /** A live wait viewer: the frozen selected set, then every observation round. */
24
- export type WaitObserver = Readonly<{
25
- selected?: (selected: readonly WaitSelectedAkuma[]) => void;
26
- observe?: (observed: readonly WaitObservedAkuma[]) => void;
27
- }>;
28
5
  type WaitExecutionInput = Readonly<{
29
6
  path: WorldRoot;
30
7
  ids: readonly AkumaStatus["id"][];
@@ -34,14 +11,6 @@ type WaitExecutionInput = Readonly<{
34
11
  /** Internal custom completion judge over the full final observation where supplied. */
35
12
  predicate?: (status: AkumaStatus) => boolean;
36
13
  outcomeObserved?: OutcomeObserver;
37
- /** Resolves one Akuma's identity facts; consulted once per Akuma a viewer first sees. */
38
- identity?: (id: AkumaStatus["id"]) => Promise<WaitIdentityFacts>;
39
- /** The selected set in the caller's order; a viewer's head and scoreboard follow it. */
40
- selectionOrder?: readonly AkumaStatus["id"][];
41
- /** Reports the frozen selected set before the first round, so a viewer can fix its layout. */
42
- onSelected?: (selected: readonly WaitSelectedAkuma[]) => void;
43
- /** Reports every observation round to a live viewer. */
44
- observe?: (observed: readonly WaitObservedAkuma[]) => void;
45
14
  }>;
46
15
  /** One wait's association-free native evidence; upper composition attaches cross-product context. */
47
16
  export type NativeWaitResult = Readonly<{
@@ -50,14 +19,6 @@ export type NativeWaitResult = Readonly<{
50
19
  observations: readonly AkumaStatus[];
51
20
  unobserved: readonly AkumaUnobserved[];
52
21
  }>;
53
- /**
54
- * The one lower set-observation owner for Akuma wait completion. It serves the
55
- * standalone one-ID association-free face and the plural any/all face with one
56
- * ordered round algorithm, one shared ordinary-detail budget, transient
57
- * unreadable peers, and an honest final deadline edge. A silent observation —
58
- * no live row callback and no custom judge — decides which running rounds to
59
- * skip with the owner's lightweight completion probe over the selected set; a
60
- * live viewer or a custom judge always observes full rounds.
61
- */
22
+ /** Wait observes completion and returns final status snapshots, never a live stream. */
62
23
  export declare function executeWaitAkuma(input: WaitExecutionInput): Promise<NativeWaitResult>;
63
24
  export {};
@@ -1,19 +1,9 @@
1
1
  import { AkumaNotBornError } from "./akuma-errors.js";
2
- import { createLiveStatusReader, defaultWaitComplete, readLiveStatus, readWaitComplete, observeOutcomeRows, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
2
+ import { createLiveStatusReader, defaultWaitComplete, readWaitComplete, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
3
3
  import { pathsForAkuId } from "./identity.js";
4
4
  const SHARED_ORDINARY_BUDGET = 30;
5
- async function observeWaitRound(path, ids, signal, readers) {
6
- const read = async (id, ordinaryBudget) => {
7
- const options = { aperture: "monitoring", ...(ordinaryBudget === undefined ? {} : { ordinaryBudget }) };
8
- if (readers === undefined)
9
- return await readLiveStatus(path, id, options, signal);
10
- let reader = readers.get(id);
11
- if (reader === undefined) {
12
- reader = createLiveStatusReader(pathsForAkuId(path, id), id);
13
- readers.set(id, reader);
14
- }
15
- return await reader.read(options, signal);
16
- };
5
+ async function observeWaitRound(ids, readerFor, signal) {
6
+ const read = (id, ordinaryBudget) => readerFor(id).read({ aperture: "monitoring", ...(ordinaryBudget === undefined ? {} : { ordinaryBudget }) }, signal);
17
7
  signal?.throwIfAborted();
18
8
  if (ids.length <= 1) {
19
9
  const observations = await Promise.all(ids.map(async (id) => await read(id)));
@@ -30,8 +20,6 @@ async function observeWaitRound(path, ids, signal, readers) {
30
20
  remaining -= observed.ordinarySelected;
31
21
  }
32
22
  catch (error) {
33
- readers?.get(id)?.clear();
34
- readers?.delete(id);
35
23
  if (error instanceof AkumaNotBornError)
36
24
  throw error;
37
25
  unobserved.push({ id, diagnostic: diagnostic(error) });
@@ -45,80 +33,32 @@ function roundComplete(round, completion, predicate) {
45
33
  return (settled.length > 0 &&
46
34
  (completion === "any" ? settled.some(Boolean) : round.unobserved.length === 0 && settled.every(Boolean)));
47
35
  }
48
- /** Canonical ids in the caller's selection order, appending any id the caller never named. */
49
- function selectionOrderedIds(ids, order) {
50
- const present = new Set(ids);
51
- const seen = new Set();
52
- const ordered = [];
53
- for (const id of order) {
54
- if (present.has(id) && !seen.has(id)) {
55
- seen.add(id);
56
- ordered.push(id);
57
- }
58
- }
59
- for (const id of ids) {
60
- if (!seen.has(id)) {
61
- seen.add(id);
62
- ordered.push(id);
63
- }
64
- }
65
- return ordered;
66
- }
67
- /**
68
- * The one lower set-observation owner for Akuma wait completion. It serves the
69
- * standalone one-ID association-free face and the plural any/all face with one
70
- * ordered round algorithm, one shared ordinary-detail budget, transient
71
- * unreadable peers, and an honest final deadline edge. A silent observation —
72
- * no live row callback and no custom judge — decides which running rounds to
73
- * skip with the owner's lightweight completion probe over the selected set; a
74
- * live viewer or a custom judge always observes full rounds.
75
- */
36
+ /** Wait observes completion and returns final status snapshots, never a live stream. */
76
37
  export async function executeWaitAkuma(input) {
77
- const readers = input.observe === undefined ? undefined : new Map();
78
- try {
79
- // Identity facts are read once per observed Akuma, not once per 100ms round.
80
- const facts = new Map();
81
- if (input.onSelected !== undefined) {
82
- for (const id of input.ids) {
83
- input.signal?.throwIfAborted();
84
- const known = input.identity === undefined ? undefined : await input.identity(id);
85
- facts.set(id, known ?? { contract: { kind: "none" } });
86
- }
87
- const ordered = input.selectionOrder === undefined ? input.ids : selectionOrderedIds(input.ids, input.selectionOrder);
88
- input.onSelected(ordered.map((id) => ({ id, ...facts.get(id) })));
38
+ const readers = new Map();
39
+ const readerFor = (id) => {
40
+ let reader = readers.get(id);
41
+ if (reader === undefined) {
42
+ reader = createLiveStatusReader(pathsForAkuId(input.path, id), id);
43
+ readers.set(id, reader);
89
44
  }
90
- const observeRound = async (round) => {
91
- await Promise.all(round.observations.map(({ status, rows }) => input.observe === undefined
92
- ? observeStatusOutcome(status, input.outcomeObserved)
93
- : observeOutcomeRows(status.id, rows, input.outcomeObserved)));
94
- if (input.observe === undefined)
95
- return;
96
- const observed = [];
97
- for (const observation of round.observations) {
98
- input.signal?.throwIfAborted();
99
- const { status, rows } = observation;
100
- let known = facts.get(status.id);
101
- if (known === undefined && input.identity !== undefined) {
102
- known = await input.identity(status.id);
103
- facts.set(status.id, known);
104
- }
105
- if (known === undefined) {
106
- observed.push({ status, rows, contract: { kind: "none" } });
107
- continue;
108
- }
109
- observed.push({ status, rows, ...known });
110
- }
111
- input.observe(structuredClone(observed));
112
- };
45
+ return reader;
46
+ };
47
+ try {
113
48
  const waited = await waitForObservation({
49
+ pollMs: 250,
114
50
  ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
115
51
  ...(input.signal === undefined ? {} : { signal: input.signal }),
116
- ...(input.predicate === undefined && input.observe === undefined
117
- ? { probe: async () => await readWaitComplete(input.path, input.ids, input.completion, input.signal) }
52
+ ...(input.predicate === undefined
53
+ ? {
54
+ probe: async () => await readWaitComplete(input.path, input.ids, input.completion, input.signal, (id) => readerFor(id).complete(input.signal)),
55
+ }
118
56
  : {}),
119
- observe: async () => await observeWaitRound(input.path, input.ids, input.signal, readers),
57
+ observe: async () => await observeWaitRound(input.ids, readerFor, input.signal),
120
58
  complete: (round) => roundComplete(round, input.completion, input.predicate),
121
- onObserve: async (round) => await observeRound(round),
59
+ onObserve: async (round) => {
60
+ await Promise.all(round.observations.map(({ status }) => observeStatusOutcome(status, input.outcomeObserved)));
61
+ },
122
62
  });
123
63
  return {
124
64
  mode: input.completion,
@@ -128,9 +68,8 @@ export async function executeWaitAkuma(input) {
128
68
  };
129
69
  }
130
70
  finally {
131
- for (const reader of readers?.values() ?? [])
71
+ for (const reader of readers.values())
132
72
  reader.clear();
133
- readers?.clear();
134
73
  }
135
74
  }
136
75
  function diagnostic(error) {
@@ -67,24 +67,21 @@ export declare const akumaStatusSchema: z.ZodObject<{
67
67
  stranded: "stranded";
68
68
  }>;
69
69
  cwd: z.ZodOptional<z.ZodString>;
70
+ provider: z.ZodOptional<z.ZodString>;
71
+ model: z.ZodOptional<z.ZodString>;
70
72
  allowed: z.ZodPipe<z.ZodArray<z.ZodEnum<{
71
- "task.add": "task.add";
72
- "task.addDocument": "task.addDocument";
73
- "task.compose": "task.compose";
74
- "task.done": "task.done";
75
- "task.drop": "task.drop";
76
- "task.hold": "task.hold";
77
- "task.resume": "task.resume";
78
- "task.start": "task.start";
79
- "task.stop": "task.stop";
80
- "task.update": "task.update";
73
+ "debt.add": "debt.add";
74
+ "debt.addDocument": "debt.addDocument";
75
+ "debt.done": "debt.done";
76
+ "debt.drop": "debt.drop";
77
+ "debt.update": "debt.update";
81
78
  "akuma.call": "akuma.call";
82
79
  "akuma.kill": "akuma.kill";
83
80
  "akuma.tell": "akuma.tell";
84
81
  "contract.audit": "contract.audit";
85
82
  "contract.deliver": "contract.deliver";
86
83
  "contract.review": "contract.review";
87
- }>>, z.ZodTransform<import("./allowed.js").AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
84
+ }>>, z.ZodTransform<import("./allowed.js").AllowedActions, ("debt.add" | "debt.addDocument" | "debt.done" | "debt.drop" | "debt.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
88
85
  timeline: z.ZodUnion<readonly [z.ZodObject<{
89
86
  reportedChanges: z.ZodReadonly<z.ZodArray<z.ZodObject<{
90
87
  sequence: z.ZodNumber;
@@ -228,6 +225,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
228
225
  unspecified: "unspecified";
229
226
  }>;
230
227
  path: z.ZodString;
228
+ patch: z.ZodOptional<z.ZodString>;
231
229
  diffstat: z.ZodOptional<z.ZodObject<{
232
230
  added: z.ZodNumber;
233
231
  removed: z.ZodNumber;
@@ -242,6 +240,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
242
240
  }, z.core.$strict>>;
243
241
  }, z.core.$strict>]>;
244
242
  state: z.ZodLiteral<"active">;
243
+ toolId: z.ZodOptional<z.ZodString>;
245
244
  truncated: z.ZodOptional<z.ZodLiteral<true>>;
246
245
  }, z.core.$strict>, z.ZodObject<{
247
246
  kind: z.ZodLiteral<"tool">;
@@ -278,6 +277,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
278
277
  unspecified: "unspecified";
279
278
  }>;
280
279
  path: z.ZodString;
280
+ patch: z.ZodOptional<z.ZodString>;
281
281
  diffstat: z.ZodOptional<z.ZodObject<{
282
282
  added: z.ZodNumber;
283
283
  removed: z.ZodNumber;
@@ -297,8 +297,10 @@ export declare const akumaStatusSchema: z.ZodObject<{
297
297
  ok: "ok";
298
298
  }>;
299
299
  message: z.ZodOptional<z.ZodString>;
300
+ output: z.ZodOptional<z.ZodString>;
300
301
  exitCode: z.ZodOptional<z.ZodNumber>;
301
302
  }, z.core.$strict>;
303
+ toolId: z.ZodOptional<z.ZodString>;
302
304
  truncated: z.ZodOptional<z.ZodLiteral<true>>;
303
305
  }, z.core.$strict>]>;
304
306
  }, z.core.$strict>]>>>;
@@ -331,6 +333,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
331
333
  kind: z.ZodLiteral<"answered">;
332
334
  historyId: z.ZodString;
333
335
  answer: z.ZodString;
336
+ foldedSaidSequence: z.ZodOptional<z.ZodNumber>;
334
337
  }, z.core.$strict>, z.ZodObject<{
335
338
  kind: z.ZodLiteral<"failed">;
336
339
  historyId: z.ZodString;
@@ -436,6 +439,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
436
439
  unspecified: "unspecified";
437
440
  }>;
438
441
  path: z.ZodString;
442
+ patch: z.ZodOptional<z.ZodString>;
439
443
  diffstat: z.ZodOptional<z.ZodObject<{
440
444
  added: z.ZodNumber;
441
445
  removed: z.ZodNumber;
@@ -455,8 +459,10 @@ export declare const akumaStatusSchema: z.ZodObject<{
455
459
  ok: "ok";
456
460
  }>;
457
461
  message: z.ZodOptional<z.ZodString>;
462
+ output: z.ZodOptional<z.ZodString>;
458
463
  exitCode: z.ZodOptional<z.ZodNumber>;
459
464
  }, z.core.$strict>;
465
+ toolId: z.ZodOptional<z.ZodString>;
460
466
  truncated: z.ZodOptional<z.ZodLiteral<true>>;
461
467
  }, z.core.$strict>]>;
462
468
  }, z.core.$strict>]>>>;
@@ -15,6 +15,8 @@ export const akumaStatusSchema = z
15
15
  birth: akumaBirthSchema,
16
16
  life: z.enum(["running", "asleep", "stranded", "hung", "untidy", "killed"]),
17
17
  cwd: z.string().optional(),
18
+ provider: z.string().optional(),
19
+ model: z.string().optional(),
18
20
  allowed: allowedActionsSchema,
19
21
  timeline: activitySnapshotSchema,
20
22
  strandedReason: z.literal("resume-unsupported").optional(),
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- export declare const ALLOWED_ACTIONS: readonly ["akuma.call", "akuma.kill", "akuma.tell", "contract.audit", "contract.deliver", "contract.review", "task.add", "task.addDocument", "task.compose", "task.done", "task.drop", "task.hold", "task.resume", "task.start", "task.stop", "task.update"];
2
+ export declare const ALLOWED_ACTIONS: readonly ["akuma.call", "akuma.kill", "akuma.tell", "contract.audit", "contract.deliver", "contract.review", "debt.add", "debt.addDocument", "debt.done", "debt.drop", "debt.update"];
3
3
  export type AllowedAction = (typeof ALLOWED_ACTIONS)[number];
4
4
  export type AllowedActions = readonly AllowedAction[];
5
5
  export declare const DEFAULT_ALLOWED_ACTIONS: AllowedActions;
@@ -7,23 +7,18 @@ export declare function isAllowedAction(value: unknown): value is AllowedAction;
7
7
  export declare function decodeAllowedActions(value: unknown, label?: string): AllowedActions;
8
8
  /** Public codecs retain the Soul's canonical, duplicate-free action membership. */
9
9
  export declare const allowedActionsSchema: z.ZodPipe<z.ZodArray<z.ZodEnum<{
10
- "task.add": "task.add";
11
- "task.addDocument": "task.addDocument";
12
- "task.compose": "task.compose";
13
- "task.done": "task.done";
14
- "task.drop": "task.drop";
15
- "task.hold": "task.hold";
16
- "task.resume": "task.resume";
17
- "task.start": "task.start";
18
- "task.stop": "task.stop";
19
- "task.update": "task.update";
10
+ "debt.add": "debt.add";
11
+ "debt.addDocument": "debt.addDocument";
12
+ "debt.done": "debt.done";
13
+ "debt.drop": "debt.drop";
14
+ "debt.update": "debt.update";
20
15
  "akuma.call": "akuma.call";
21
16
  "akuma.kill": "akuma.kill";
22
17
  "akuma.tell": "akuma.tell";
23
18
  "contract.audit": "contract.audit";
24
19
  "contract.deliver": "contract.deliver";
25
20
  "contract.review": "contract.review";
26
- }>>, z.ZodTransform<AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
21
+ }>>, z.ZodTransform<AllowedActions, ("debt.add" | "debt.addDocument" | "debt.done" | "debt.drop" | "debt.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
27
22
  export declare function historicalAllowedActions(value: unknown): AllowedActions;
28
23
  export declare function unionAllowedActions(base: AllowedActions, additions: AllowedActions): AllowedActions;
29
24
  export declare function clipAllowedActions(requested: AllowedActions, parent: AllowedActions): AllowedActions;
@@ -1,4 +1,4 @@
1
- import { TASK_MUTATION_ACTIONS } from "../task/mutation.js";
1
+ import { DEBT_MUTATION_ACTIONS } from "../debt/mutation.js";
2
2
  import { z } from "zod";
3
3
  const AKUMA_MUTATION_ACTIONS = Object.freeze(["akuma.call", "akuma.kill", "akuma.tell"]);
4
4
  export const ALLOWED_ACTIONS = Object.freeze([
@@ -6,13 +6,13 @@ export const ALLOWED_ACTIONS = Object.freeze([
6
6
  "contract.audit",
7
7
  "contract.deliver",
8
8
  "contract.review",
9
- ...TASK_MUTATION_ACTIONS,
9
+ ...DEBT_MUTATION_ACTIONS,
10
10
  ]);
11
11
  export const DEFAULT_ALLOWED_ACTIONS = Object.freeze([
12
12
  ...AKUMA_MUTATION_ACTIONS,
13
13
  "contract.audit",
14
14
  "contract.deliver",
15
- ...TASK_MUTATION_ACTIONS,
15
+ ...DEBT_MUTATION_ACTIONS,
16
16
  ]);
17
17
  const ALLOWED_ACTION_SET = new Set(ALLOWED_ACTIONS);
18
18
  export function isAllowedAction(value) {
@@ -42,7 +42,16 @@ export const allowedActionsSchema = z.array(z.enum(ALLOWED_ACTIONS)).transform((
42
42
  }
43
43
  });
44
44
  export function historicalAllowedActions(value) {
45
- return value === undefined ? ALLOWED_ACTIONS : decodeAllowedActions(value);
45
+ if (value === undefined)
46
+ return ALLOWED_ACTIONS;
47
+ if (!Array.isArray(value))
48
+ return decodeAllowedActions(value);
49
+ // Persisted permissions retain the same surviving capabilities after rename;
50
+ // removed planning/progress operations confer no replacement permission.
51
+ const retired = new Set(["task.compose", "task.start", "task.stop", "task.hold", "task.resume"]);
52
+ return decodeAllowedActions(value
53
+ .filter((action) => !retired.has(action))
54
+ .map((action) => typeof action === "string" && action.startsWith("task.") ? `debt.${action.slice("task.".length)}` : action));
46
55
  }
47
56
  export function unionAllowedActions(base, additions) {
48
57
  const merged = new Set(base);
@@ -1,10 +1,11 @@
1
- import { type HeartSnapshot, type HeldAkumaLeash } from "./heart/index.js";
1
+ import { type BodyControlSnapshot, type HeldAkumaLeash } from "./heart/index.js";
2
2
  import type { AkumaPaths } from "./identity.js";
3
3
  export declare const CONTROL_RESPONSE_MS = 1000;
4
4
  export declare class BodySupervisor {
5
5
  private readonly paths;
6
6
  private readonly bodySequence;
7
7
  private readonly leash;
8
+ private readonly reader;
8
9
  readonly signal: AbortSignal;
9
10
  private readonly controller;
10
11
  private readonly finished;
@@ -15,12 +16,11 @@ export declare class BodySupervisor {
15
16
  private constructor();
16
17
  static open(paths: AkumaPaths, bodySequence: number, leash: HeldAkumaLeash): Promise<BodySupervisor>;
17
18
  get reason(): "control" | "heart-gone" | undefined;
18
- current(): HeartSnapshot;
19
+ current(): BodyControlSnapshot;
19
20
  recordHung(diagnostic: string, at: string): Promise<void>;
20
- refresh(): Promise<HeartSnapshot>;
21
- next(after: HeartSnapshot): Promise<HeartSnapshot>;
21
+ refresh(): Promise<BodyControlSnapshot>;
22
+ next(after: BodyControlSnapshot): Promise<BodyControlSnapshot>;
22
23
  cancel(reason: "control" | "heart-gone"): void;
23
24
  close(): Promise<void>;
24
- private publish;
25
25
  private observe;
26
26
  }
@@ -1,11 +1,13 @@
1
1
  import { abortableDelay } from "./abort.js";
2
- import { heartExists, readHeart } from "./heart/index.js";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ import { createBodyHeartReader } from "./heart/index.js";
3
4
  const BODY_CONTROL_OBSERVATION_MS = 100;
4
5
  export const CONTROL_RESPONSE_MS = 1_000;
5
6
  export class BodySupervisor {
6
7
  paths;
7
8
  bodySequence;
8
9
  leash;
10
+ reader;
9
11
  signal;
10
12
  controller = new AbortController();
11
13
  finished = new AbortController();
@@ -13,16 +15,18 @@ export class BodySupervisor {
13
15
  waiter;
14
16
  observation;
15
17
  stopping;
16
- constructor(paths, bodySequence, leash, observation) {
18
+ constructor(paths, bodySequence, leash, reader, observation) {
17
19
  this.paths = paths;
18
20
  this.bodySequence = bodySequence;
19
21
  this.leash = leash;
22
+ this.reader = reader;
20
23
  this.signal = this.controller.signal;
21
24
  this.observation = observation;
22
25
  this.observer = this.observe();
23
26
  }
24
27
  static async open(paths, bodySequence, leash) {
25
- return new BodySupervisor(paths, bodySequence, leash, await readHeart(paths));
28
+ const reader = createBodyHeartReader(paths);
29
+ return new BodySupervisor(paths, bodySequence, leash, reader, await reader.read());
26
30
  }
27
31
  get reason() {
28
32
  return this.stopping;
@@ -34,7 +38,12 @@ export class BodySupervisor {
34
38
  await this.leash.recordBodyHung(this.paths, { sequence: this.bodySequence, diagnostic, at });
35
39
  }
36
40
  async refresh() {
37
- this.publish(await readHeart(this.paths));
41
+ const snapshot = await this.reader.read();
42
+ if (!isDeepStrictEqual(snapshot, this.observation)) {
43
+ this.observation = snapshot;
44
+ this.waiter?.(snapshot);
45
+ this.waiter = undefined;
46
+ }
38
47
  return this.observation;
39
48
  }
40
49
  next(after) {
@@ -54,18 +63,18 @@ export class BodySupervisor {
54
63
  }
55
64
  async close() {
56
65
  this.finished.abort();
57
- await this.observer;
58
- this.waiter = undefined;
59
- }
60
- publish(snapshot) {
61
- this.observation = snapshot;
62
- this.waiter?.(snapshot);
63
- this.waiter = undefined;
66
+ try {
67
+ await this.observer;
68
+ }
69
+ finally {
70
+ this.reader.clear();
71
+ this.waiter = undefined;
72
+ }
64
73
  }
65
74
  async observe() {
66
75
  for (;;) {
67
76
  const snapshot = this.observation;
68
- if (!(await heartExists(this.paths)))
77
+ if (snapshot.soul === null)
69
78
  return this.cancel("heart-gone");
70
79
  if (snapshot.stop?.bodySequence === this.bodySequence || snapshot.pause?.bodySequence === this.bodySequence) {
71
80
  return this.cancel("control");
@@ -76,14 +85,7 @@ export class BodySupervisor {
76
85
  catch {
77
86
  return;
78
87
  }
79
- try {
80
- await this.refresh();
81
- }
82
- catch (error) {
83
- if (await heartExists(this.paths))
84
- throw error;
85
- return this.cancel("heart-gone");
86
- }
88
+ await this.refresh();
87
89
  }
88
90
  }
89
91
  }