@astrosheep/keiyaku 4.6.4 → 4.6.7

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 (247) hide show
  1. package/README.md +7 -0
  2. package/build/{integrations/marketplace → plugins}/.agents/plugins/marketplace.json +1 -1
  3. package/build/plugins/.claude-plugin/marketplace.json +5 -0
  4. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/.claude-plugin/plugin.json +1 -1
  5. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/SKILL.md +43 -8
  6. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/SKILL.md +7 -8
  7. package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-workflow/SKILL.md +3 -3
  8. package/build/{integrations/marketplace/plugins/keiyaku → plugins/codex}/.codex-plugin/plugin.json +1 -1
  9. package/build/plugins/codex/skills/keiyaku/SKILL.md +44 -0
  10. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +130 -0
  11. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +269 -0
  12. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +65 -0
  13. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +216 -0
  14. package/build/plugins/codex/skills/keiyaku-bind/agents/openai.yaml +4 -0
  15. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +104 -0
  16. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +129 -0
  17. package/build/plugins/opencode/package.json +6 -0
  18. package/build/plugins/opencode/skills/keiyaku/SKILL.md +44 -0
  19. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +130 -0
  20. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +269 -0
  21. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +65 -0
  22. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +216 -0
  23. package/build/plugins/opencode/skills/keiyaku-bind/agents/openai.yaml +4 -0
  24. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +104 -0
  25. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +129 -0
  26. package/build/skills/keiyaku/SKILL.md +44 -0
  27. package/build/skills/keiyaku-akuma/SKILL.md +130 -0
  28. package/build/skills/keiyaku-akuma/references/automation.md +269 -0
  29. package/build/skills/keiyaku-babysit/SKILL.md +65 -0
  30. package/build/skills/keiyaku-bind/SKILL.md +216 -0
  31. package/build/skills/keiyaku-bind/agents/openai.yaml +4 -0
  32. package/build/skills/keiyaku-task/SKILL.md +104 -0
  33. package/build/skills/keiyaku-workflow/SKILL.md +129 -0
  34. package/build/src/akuma/akuma-instance.js +7 -5
  35. package/build/src/akuma/akuma-observe.d.ts +22 -15
  36. package/build/src/akuma/akuma-observe.js +87 -16
  37. package/build/src/akuma/akuma-owner.d.ts +3 -2
  38. package/build/src/akuma/akuma-owner.js +28 -10
  39. package/build/src/akuma/akuma-selection-execution.d.ts +3 -1
  40. package/build/src/akuma/akuma-selection-execution.js +2 -1
  41. package/build/src/akuma/akuma-wait.d.ts +6 -4
  42. package/build/src/akuma/akuma-wait.js +78 -53
  43. package/build/src/akuma/akuma.d.ts +6 -4
  44. package/build/src/akuma/akuma.js +4 -0
  45. package/build/src/akuma/body.d.ts +1 -0
  46. package/build/src/akuma/body.js +12 -23
  47. package/build/src/akuma/call-initial-tell.d.ts +2 -2
  48. package/build/src/akuma/call-initial-tell.js +1 -1
  49. package/build/src/akuma/call-request.d.ts +2 -2
  50. package/build/src/akuma/heart/index.d.ts +7 -2
  51. package/build/src/akuma/heart/index.js +50 -5
  52. package/build/src/akuma/heart/tells.d.ts +33 -2
  53. package/build/src/akuma/heart/tells.js +24 -18
  54. package/build/src/akuma/heart/timeline.d.ts +23 -1
  55. package/build/src/akuma/heart/timeline.js +28 -21
  56. package/build/src/akuma/projection.d.ts +10 -10
  57. package/build/src/akuma/providers/pi/index.js +72 -39
  58. package/build/src/akuma/selection-observation.d.ts +20 -20
  59. package/build/src/akuma/selection-owner-port.d.ts +1 -1
  60. package/build/src/akuma/selection-owner-port.js +16 -5
  61. package/build/src/akuma/selection-request.d.ts +2 -0
  62. package/build/src/akuma/selection-request.js +2 -1
  63. package/build/src/akuma-body.js +5 -2
  64. package/build/src/alias/index.d.ts +0 -1
  65. package/build/src/alias/index.js +0 -4
  66. package/build/src/body/amend.d.ts +0 -4
  67. package/build/src/body/amend.js +0 -3
  68. package/build/src/body/region.d.ts +0 -1
  69. package/build/src/body/region.js +0 -3
  70. package/build/src/body/verification.d.ts +0 -1
  71. package/build/src/cli/commands/akuma-grammar.js +23 -66
  72. package/build/src/cli/commands/akuma.js +23 -42
  73. package/build/src/cli/commands/contract-grammar.d.ts +14 -1
  74. package/build/src/cli/commands/contract-grammar.js +54 -21
  75. package/build/src/cli/commands/contract-help.d.ts +9 -8
  76. package/build/src/cli/commands/contract-help.js +14 -7
  77. package/build/src/cli/commands/contract.js +57 -117
  78. package/build/src/cli/commands/install.d.ts +5 -5
  79. package/build/src/cli/commands/install.js +4 -7
  80. package/build/src/cli/commands/task-grammar.js +10 -66
  81. package/build/src/cli/commands/task.d.ts +0 -1
  82. package/build/src/cli/commands/task.js +34 -53
  83. package/build/src/cli/coordinates.d.ts +1 -2
  84. package/build/src/cli/coordinates.js +1 -4
  85. package/build/src/cli/parse.d.ts +2 -3
  86. package/build/src/cli/parse.js +24 -66
  87. package/build/src/cli/render/akuma.d.ts +3 -16
  88. package/build/src/cli/render/akuma.js +1 -13
  89. package/build/src/cli/render/audit.js +1 -1
  90. package/build/src/cli/render/contract.js +34 -32
  91. package/build/src/cli/render/kanshi-akuma.d.ts +8 -2
  92. package/build/src/cli/render/kanshi-akuma.js +14 -7
  93. package/build/src/cli/render/kanshi.d.ts +3 -1
  94. package/build/src/cli/render/kanshi.js +44 -32
  95. package/build/src/cli/render/receipt.js +6 -1
  96. package/build/src/cli/render/task.d.ts +1 -1
  97. package/build/src/cli/render/task.js +3 -27
  98. package/build/src/cli/render/terminal.d.ts +6 -2
  99. package/build/src/cli/render/terminal.js +8 -2
  100. package/build/src/cli/runtime.js +3 -16
  101. package/build/src/cli/scan.d.ts +26 -0
  102. package/build/src/cli/scan.js +82 -0
  103. package/build/src/cli/streams.d.ts +5 -0
  104. package/build/src/cli/streams.js +11 -0
  105. package/build/src/contract-worktree.js +38 -21
  106. package/build/src/core/facts/codec.d.ts +1 -2
  107. package/build/src/core/facts/codec.js +5 -11
  108. package/build/src/core/facts/types.d.ts +16 -2
  109. package/build/src/core/facts/types.js +15 -0
  110. package/build/src/core/verbs/abandon.js +3 -9
  111. package/build/src/core/verbs/amend.js +2 -9
  112. package/build/src/core/verbs/arc.js +6 -13
  113. package/build/src/core/verbs/attestation.js +2 -9
  114. package/build/src/core/verbs/bind.js +2 -9
  115. package/build/src/core/verbs/deliver.js +2 -9
  116. package/build/src/core/verbs/placement.d.ts +1 -1
  117. package/build/src/core/verbs/placement.js +2 -9
  118. package/build/src/core/verbs/reintegrate.d.ts +1 -1
  119. package/build/src/core/verbs/reintegrate.js +2 -9
  120. package/build/src/dispatch/index.d.ts +2 -2
  121. package/build/src/dispatch/index.js +33 -11
  122. package/build/src/git/hooks.d.ts +2 -4
  123. package/build/src/git/hooks.js +0 -12
  124. package/build/src/git/integration.d.ts +5 -3
  125. package/build/src/git/integration.js +36 -25
  126. package/build/src/git/nuke.js +4 -4
  127. package/build/src/git/observe.d.ts +4 -4
  128. package/build/src/git/observe.js +5 -5
  129. package/build/src/git/process.d.ts +1 -4
  130. package/build/src/git/process.js +1 -11
  131. package/build/src/git/read-observation.js +1 -1
  132. package/build/src/git/reconcile.d.ts +1 -1
  133. package/build/src/git/reconcile.js +15 -13
  134. package/build/src/git/repository.d.ts +2 -6
  135. package/build/src/git/repository.js +18 -31
  136. package/build/src/git/scratch.d.ts +6 -6
  137. package/build/src/git/scratch.js +110 -46
  138. package/build/src/git/target-placement.d.ts +5 -5
  139. package/build/src/git/target-placement.js +18 -33
  140. package/build/src/git/tender.d.ts +6 -2
  141. package/build/src/git/tender.js +19 -12
  142. package/build/src/git/terminal-reconcile.js +24 -13
  143. package/build/src/git/terminal-seal.d.ts +2 -5
  144. package/build/src/git/terminal-seal.js +5 -3
  145. package/build/src/git/workspace.d.ts +17 -13
  146. package/build/src/git/workspace.js +58 -41
  147. package/build/src/kanshi/index.d.ts +2 -2
  148. package/build/src/kanshi/index.js +1 -1
  149. package/build/src/kanshi/read.d.ts +8 -1
  150. package/build/src/kanshi/read.js +72 -7
  151. package/build/src/kanshi/report.d.ts +12 -0
  152. package/build/src/library/akuma-creation.d.ts +4 -4
  153. package/build/src/library/akuma-creation.js +21 -19
  154. package/build/src/library/bind.d.ts +1 -63
  155. package/build/src/library/bind.js +3 -9
  156. package/build/src/library/contract-creation.js +2 -30
  157. package/build/src/library/contract-execution.d.ts +0 -1
  158. package/build/src/library/contract-execution.js +9 -34
  159. package/build/src/library/contract-operations.d.ts +5 -1
  160. package/build/src/library/contract-operations.js +7 -3
  161. package/build/src/library/contract-types.d.ts +1 -1
  162. package/build/src/library/delivery.d.ts +91 -93
  163. package/build/src/library/delivery.js +2 -1
  164. package/build/src/library/input.d.ts +0 -2
  165. package/build/src/library/input.js +0 -4
  166. package/build/src/library/invocation.d.ts +0 -1
  167. package/build/src/library/invocation.js +3 -25
  168. package/build/src/library/outcome.d.ts +651 -602
  169. package/build/src/library/outcome.js +4 -4
  170. package/build/src/library/reconcile.d.ts +6 -0
  171. package/build/src/library/reconcile.js +31 -1
  172. package/build/src/library/repo.d.ts +0 -1
  173. package/build/src/library/selection.d.ts +1 -10
  174. package/build/src/library/selection.js +19 -17
  175. package/build/src/plugin/akuma-signals.d.ts +10 -11
  176. package/build/src/plugin/akuma-signals.js +36 -20
  177. package/build/src/plugin/public.d.ts +5 -0
  178. package/build/src/plugin/runtime.d.ts +1 -0
  179. package/build/src/plugin/runtime.js +34 -23
  180. package/build/src/protocol/abandon.d.ts +1 -1
  181. package/build/src/protocol/abandon.js +3 -10
  182. package/build/src/protocol/amend.js +2 -5
  183. package/build/src/protocol/arc.d.ts +1 -1
  184. package/build/src/protocol/arc.js +2 -9
  185. package/build/src/protocol/attempt.d.ts +3 -20
  186. package/build/src/protocol/attempt.js +6 -5
  187. package/build/src/protocol/audit.d.ts +1 -0
  188. package/build/src/protocol/audit.js +10 -11
  189. package/build/src/protocol/completion.d.ts +129 -55
  190. package/build/src/protocol/completion.js +62 -73
  191. package/build/src/protocol/deliver.d.ts +7 -5
  192. package/build/src/protocol/deliver.js +74 -44
  193. package/build/src/protocol/execution-observation.d.ts +2 -4
  194. package/build/src/protocol/execution-observation.js +3 -7
  195. package/build/src/protocol/intent.d.ts +1 -1
  196. package/build/src/protocol/intent.js +1 -0
  197. package/build/src/protocol/operations.d.ts +24 -12
  198. package/build/src/protocol/operations.js +36 -15
  199. package/build/src/protocol/placement.d.ts +2 -1
  200. package/build/src/protocol/placement.js +21 -5
  201. package/build/src/protocol/progress.d.ts +1 -1
  202. package/build/src/protocol/read/status.js +58 -41
  203. package/build/src/protocol/reintegrate.d.ts +1 -1
  204. package/build/src/protocol/reintegrate.js +10 -19
  205. package/build/src/protocol/review.d.ts +3 -28
  206. package/build/src/protocol/review.js +10 -37
  207. package/build/src/protocol/run.d.ts +19 -7
  208. package/build/src/protocol/run.js +19 -9
  209. package/build/src/runtime/proc/windows-launch.exe +0 -0
  210. package/build/src/settlement/holder.d.ts +2 -4
  211. package/build/src/settlement/holder.js +3 -6
  212. package/build/src/task/board.d.ts +6 -0
  213. package/build/src/task/board.js +30 -1
  214. package/build/src/task/catalog.js +1 -4
  215. package/build/src/task/compose.d.ts +0 -1
  216. package/build/src/task/compose.js +0 -1
  217. package/build/src/task/context.d.ts +0 -1
  218. package/build/src/task/context.js +0 -3
  219. package/build/src/task/created-observation.d.ts +5 -1
  220. package/build/src/task/created-observation.js +12 -5
  221. package/build/src/task/index.d.ts +1 -1
  222. package/build/src/task/index.js +7 -6
  223. package/build/src/task/input.d.ts +0 -6
  224. package/build/src/task/input.js +2 -14
  225. package/build/src/task/mutation.d.ts +3 -4
  226. package/build/src/task/mutation.js +11 -39
  227. package/build/src/task/operations.d.ts +2 -7
  228. package/build/src/task/operations.js +37 -49
  229. package/build/src/task/query.d.ts +0 -1
  230. package/build/src/task/query.js +1 -4
  231. package/build/src/task/store.d.ts +0 -2
  232. package/build/src/task/store.js +27 -11
  233. package/build/src/verification/declaration.js +3 -2
  234. package/build/src/verification/execution.d.ts +3 -2
  235. package/build/src/verification/execution.js +10 -6
  236. package/build/src/workspace-place.d.ts +0 -1
  237. package/build/src/workspace-place.js +0 -11
  238. package/package.json +13 -9
  239. package/build/integrations/marketplace/.claude-plugin/marketplace.json +0 -5
  240. package/build/integrations/marketplace/plugins/keiyaku/package.json +0 -17
  241. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku/SKILL.md +0 -0
  242. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/references/automation.md +0 -0
  243. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-babysit/SKILL.md +0 -0
  244. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/agents/openai.yaml +0 -0
  245. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-task/SKILL.md +0 -0
  246. /package/build/{integrations/marketplace/plugins/keiyaku/opencode.js → plugins/opencode/index.js} +0 -0
  247. /package/build/{integrations → plugins}/pi/keiyaku.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  /** @architectureCompositionRoot */
2
2
  import { z } from "zod";
3
3
  import { contractFileEffectSchema } from "../contract-worktree.js";
4
- import { decodeJournalEntry } from "../core/facts/codec.js";
4
+ import { validateEntry } from "../core/facts/codec.js";
5
5
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
6
6
  import { contractHeadSchema } from "../git/identity.js";
7
7
  import { reconcileEffectSchema } from "../git/reconcile.js";
@@ -100,7 +100,7 @@ function phasePending(operation, value) {
100
100
  if (concluded === undefined)
101
101
  return [];
102
102
  const pending = [];
103
- if (concluded.verification !== undefined)
103
+ if (concluded.verification?.kind === "stopped")
104
104
  pending.push(surface("verification", true));
105
105
  if (concluded.placement !== undefined)
106
106
  pending.push(surface("placement", true));
@@ -306,7 +306,7 @@ const amendEvidenceSchema = z
306
306
  .strict()
307
307
  .refine((value) => value.overlaps === undefined || value.overlapFailure === undefined);
308
308
  const partialDeliverySchema = deliveryValueSchema.partial().superRefine((value, context) => {
309
- const fields = deliverDataSchema.keyof().options;
309
+ const fields = deliverDataSchema.omit({ note: true }).keyof().options;
310
310
  const present = fields.filter((field) => value[field] !== undefined);
311
311
  if (present.length !== 0 && present.length !== fields.length)
312
312
  context.addIssue({ code: "custom", message: "delivery identity must be complete when present" });
@@ -322,7 +322,7 @@ const partialValueSchemas = {
322
322
  };
323
323
  const journalEntrySchema = z.unknown().transform((value, context) => {
324
324
  try {
325
- return decodeJournalEntry(value);
325
+ return validateEntry(value);
326
326
  }
327
327
  catch {
328
328
  context.addIssue({ code: "custom", message: "invalid journal fact" });
@@ -8,6 +8,7 @@ import type { ReconcileResult } from "../git/reconcile.js";
8
8
  import { type RepositoryScope } from "../protocol/operations.js";
9
9
  import { type ProtocolProgress } from "../protocol/progress.js";
10
10
  import { type SettlementReport } from "../settlement/settle.js";
11
+ import type { InvocationAccumulator } from "./invocation.js";
11
12
  export type ReconcileReport = Readonly<{
12
13
  effects: readonly (ReconcileResult["effects"][number] | ContractFileEffect)[];
13
14
  lag: readonly (ReconcileResult["lag"][number] | ContractFileLag)[];
@@ -128,5 +129,10 @@ type ReconcileOptions = Readonly<{
128
129
  export declare function completeReconcile(input: ReconcileOptions & Readonly<{
129
130
  contractId: ContractId;
130
131
  }>): Promise<ReconcileCompletion>;
132
+ /**
133
+ * The one post-admission reconciliation walk: every affected Contract is observed afresh, and an
134
+ * operational stop is recorded rather than thrown.
135
+ */
136
+ export declare function reconcileAffectedContracts(accumulator: InvocationAccumulator, contractId: ContractId, scope: RepositoryScope, channel: GitDecodeChannel, hooks: WorktreeHooks): Promise<void>;
131
137
  export declare function completeRepoReconcile(input: ReconcileOptions): Promise<RepoReconcileReport>;
132
138
  export {};
@@ -4,7 +4,7 @@ import { contractFileLagSchema, projectContractWorktree, } from "../contract-wor
4
4
  import { gitReconcileLagSchema, reconcileObservationFailure } from "../git/reconcile.js";
5
5
  import { worktreePath } from "../git/workspace.js";
6
6
  import { stateOperation } from "../protocol/operations.js";
7
- import { isOperationalFailure } from "../protocol/progress.js";
7
+ import { isOperationalFailure, isOperationalStop, executionStop } from "../protocol/progress.js";
8
8
  import { reconcileAllOperation, reconcileOperation, worldContractStates } from "../protocol/reconcile.js";
9
9
  import { settle, settleAll } from "../settlement/settle.js";
10
10
  import { appointManagedWorktrees, placeRegisterPath, releaseManagedWorktrees, } from "../workspace-place.js";
@@ -205,6 +205,36 @@ export async function completeReconcile(input) {
205
205
  const terminal = await finishTerminalReconcile(input, retained, appointed);
206
206
  return assembleReconcile(retained.report, projection, settlement, terminal);
207
207
  }
208
+ /**
209
+ * The one post-admission reconciliation walk: every affected Contract is observed afresh, and an
210
+ * operational stop is recorded rather than thrown.
211
+ */
212
+ export async function reconcileAffectedContracts(accumulator, contractId, scope, channel, hooks) {
213
+ for (const contract of [...new Set([contractId, ...accumulator.snapshot().affected])]) {
214
+ try {
215
+ scope.signal?.throwIfAborted();
216
+ accumulator.observe({ kind: "stage", contractId: contract, stage: "reconciliation", state: "started" });
217
+ try {
218
+ await completeReconcile({
219
+ scope,
220
+ channel,
221
+ contractId: contract,
222
+ hooks,
223
+ retryHooks: false,
224
+ progress: accumulator,
225
+ });
226
+ }
227
+ finally {
228
+ accumulator.observe({ kind: "stage", contractId: contract, stage: "reconciliation", state: "finished" });
229
+ }
230
+ }
231
+ catch (error) {
232
+ if (!isOperationalStop(error, scope.signal))
233
+ throw error;
234
+ accumulator.recordStop(executionStop(contract, "reconciliation", error, scope.signal));
235
+ }
236
+ }
237
+ }
208
238
  function attachReleaseLag(contracts, released, lag) {
209
239
  const affected = new Set(released);
210
240
  return {
@@ -1,7 +1,6 @@
1
1
  import { type RepositoryScope } from "../protocol/operations.js";
2
2
  import { NoGitWorldError } from "../git/repository.js";
3
3
  export { NoGitWorldError };
4
- export type { RepoContractReconcileReport, RepoReconcileReport } from "./reconcile.js";
5
4
  export type RepoAtInput = Readonly<{
6
5
  path?: string;
7
6
  gitPath?: string;
@@ -56,10 +56,7 @@ export type AkumaAskInput<T = string> = AkumaAddressInput & Readonly<{
56
56
  signal?: AbortSignal;
57
57
  observe?: AskObserver;
58
58
  }>;
59
- export type { TellResult, TellWake } from "../akuma/body.js";
60
- export type { AkumaAskResult, AkumaKillResult, AkumaObservation, AkumaObservationStage, AkumaTellResult, AkumaUnobserved, AkumaWaitResult, } from "../akuma/selection-observation.js";
61
- export type { DispatchAssociation } from "../dispatch/association.js";
62
- export type { CreatedTaskObservation } from "../task/created-observation.js";
59
+ export type { AkumaAskResult, AkumaKillResult, AkumaObservation, AkumaObservationStage, AkumaTellResult, AkumaWaitResult, } from "../akuma/selection-observation.js";
63
60
  export type AkumaKillInput = AkumaSetAddressInput & Readonly<{
64
61
  signal?: AbortSignal;
65
62
  }>;
@@ -98,18 +95,12 @@ export type AkumaHistoryResult = Readonly<{
98
95
  export declare function statusAkuma(input: AkumaAddressInput & Readonly<{
99
96
  path: WorldRoot;
100
97
  }>): Promise<AkumaObservation>;
101
- export declare function waitAkuma(input: AkumaWaitInput & Readonly<{
102
- path: WorldRoot;
103
- }>, execution?: ExecutionContext): Promise<AkumaWaitResult>;
104
98
  export declare function waitAkumaOn(seam: SelectionSeam, input: AkumaWaitInput & Readonly<{
105
99
  path: WorldRoot;
106
100
  }>): Promise<AkumaWaitResult>;
107
101
  export declare function killAkumaOn(seam: SelectionSeam, input: AkumaKillInput & Readonly<{
108
102
  path: WorldRoot;
109
103
  }>): Promise<AkumaKillResult>;
110
- export declare function tellAkuma(input: AkumaTellInput & Readonly<{
111
- path: WorldRoot;
112
- }>, execution?: ExecutionContext): Promise<AkumaTellResult>;
113
104
  export declare function tellAkumaOn(seam: SelectionSeam, input: AkumaTellInput & Readonly<{
114
105
  path: WorldRoot;
115
106
  }>): Promise<AkumaTellResult>;
@@ -5,14 +5,15 @@ import { AkumaOwner } from "../akuma/akuma-owner.js";
5
5
  import { decodeAskObservation, executeAskAkuma, executeKillAkuma, executeTellAkuma, } from "../akuma/akuma-selection-execution.js";
6
6
  import { executeWaitAkuma, } from "../akuma/akuma-wait.js";
7
7
  import { parsePublicHistoryId } from "../akuma/identity.js";
8
- import { executionChannel, localExecutionContext } from "../akuma/requests.js";
8
+ import { executionChannel } from "../akuma/requests.js";
9
9
  import { schemaJsonText } from "../akuma/schema.js";
10
10
  import { requestForwardedSelectionAsk, requestForwardedSelectionKill, requestForwardedSelectionTell, requestForwardedSelectionWait, } from "../akuma/selection-request.js";
11
11
  import { readAliases } from "../alias/index.js";
12
- import { observeDispatchAssociation } from "../dispatch/index.js";
12
+ import { observeDispatchAssociations } from "../dispatch/index.js";
13
13
  import { observeContractAt } from "../git/observe.js";
14
14
  import { withGitDecodeChannel } from "../git/read-observation.js";
15
15
  import { observeCreatedTaskObservations } from "../task/created-observation.js";
16
+ import { outcomePluginObserver } from "../plugin/akuma-signals.js";
16
17
  import { addressAkuma, addressAkumaSet, resolveAkuma, resolveAkumaSet, } from "./address.js";
17
18
  import { requireInput } from "./input.js";
18
19
  import { scopeForRepo } from "./repo.js";
@@ -77,6 +78,7 @@ function localSelection() {
77
78
  const result = await executeAskAkuma({
78
79
  path: addressed.path,
79
80
  id: addressed.id,
81
+ outcomeObserved: outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error }),
80
82
  body: input.body,
81
83
  ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
82
84
  ...(input.schema === undefined ? {} : { schemaJson: schemaJsonText(input.schema) }),
@@ -99,8 +101,8 @@ function observationError(id, error) {
99
101
  return error;
100
102
  return new AkumaObservationError(id, observationDiagnostic(error));
101
103
  }
102
- async function dispatchAssociation(repo, id) {
103
- return await observeDispatchAssociation(repo === undefined ? undefined : scopeForRepo(repo), id);
104
+ async function dispatchAssociations(repo, ids) {
105
+ return await observeDispatchAssociations(repo === undefined ? undefined : scopeForRepo(repo), ids);
104
106
  }
105
107
  /**
106
108
  * Read-time placement discharge. Reported changes describe a candidate that a
@@ -141,9 +143,12 @@ async function createdTasksFor(path, statuses) {
141
143
  * One wait's identity-fact resolver: the alias bound to an Akuma in its world and
142
144
  * its Dispatch association. The alias index is read once, on the first observed
143
145
  * Akuma, and each Akuma's alias is the first binding the canonical order offers.
146
+ * Alias bindings and selected Dispatch associations are read once for this live
147
+ * stage. Final result composition owns a separate, fresh Dispatch observation.
144
148
  */
145
- function waitIdentityFacts(path, repo) {
149
+ function waitIdentityFacts(path, repo, selected) {
146
150
  let aliases;
151
+ let contracts;
147
152
  return async (id) => {
148
153
  if (aliases === undefined) {
149
154
  const bound = new Map();
@@ -153,8 +158,9 @@ function waitIdentityFacts(path, repo) {
153
158
  }
154
159
  aliases = bound;
155
160
  }
161
+ contracts ??= await dispatchAssociations(repo, selected);
156
162
  const alias = aliases.get(id);
157
- return { ...(alias === undefined ? {} : { alias }), contract: await dispatchAssociation(repo, id) };
163
+ return { ...(alias === undefined ? {} : { alias }), contract: contracts.get(id) };
158
164
  };
159
165
  }
160
166
  async function observeAkuma(status, path, repo) {
@@ -168,8 +174,9 @@ async function observeAkuma(status, path, repo) {
168
174
  async function composeAkumaAssociations(statuses, path, repo) {
169
175
  const created = await createdTasksFor(path, statuses);
170
176
  const discharged = placementDischarged(repo);
177
+ const contracts = await dispatchAssociations(repo, statuses.map((status) => status.id));
171
178
  return await Promise.all(statuses.map(async (status, index) => {
172
- const contract = await dispatchAssociation(repo, status.id);
179
+ const contract = contracts.get(status.id);
173
180
  return {
174
181
  status: await composeObservation(status, contract, discharged),
175
182
  contract,
@@ -234,7 +241,7 @@ function setAddress(values) {
234
241
  export async function statusAkuma(input) {
235
242
  const addressed = await addressAkuma(input);
236
243
  try {
237
- return await observeAkuma(await new AkumaOwner(addressed.id, addressed.path).status(), addressed.path, input.repo);
244
+ return await observeAkuma(await new AkumaOwner(addressed.id, addressed.path, outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error })).status(), addressed.path, input.repo);
238
245
  }
239
246
  catch (error) {
240
247
  throw observationError(addressed.id, error);
@@ -263,9 +270,10 @@ async function localWait(addressed, input) {
263
270
  path: addressed.path,
264
271
  ids: addressed.orderedIds,
265
272
  completion: input.completion,
273
+ outcomeObserved: outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error }),
266
274
  ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
267
275
  ...(input.signal === undefined ? {} : { signal: input.signal }),
268
- identity: waitIdentityFacts(addressed.path, input.repo),
276
+ identity: waitIdentityFacts(addressed.path, input.repo, addressed.orderedIds),
269
277
  selectionOrder: addressed.orderedIds,
270
278
  ...(input.observer?.selected === undefined ? {} : { onSelected: input.observer.selected }),
271
279
  ...(input.observer?.observe === undefined ? {} : { observe: input.observer.observe }),
@@ -277,9 +285,6 @@ async function localWait(addressed, input) {
277
285
  throw observationError(addressed.orderedIds[0], error);
278
286
  }
279
287
  }
280
- export async function waitAkuma(input, execution = localExecutionContext()) {
281
- return await waitAkumaOn(selectionSeam(execution), input);
282
- }
283
288
  function waitObserver(value) {
284
289
  if (value === undefined)
285
290
  return undefined;
@@ -330,9 +335,6 @@ export async function killAkumaOn(seam, input) {
330
335
  }
331
336
  return await seam.kill(await seam.addressSet(setAddress(values)), signal(values.signal));
332
337
  }
333
- export async function tellAkuma(input, execution = localExecutionContext()) {
334
- return await tellAkumaOn(selectionSeam(execution), input);
335
- }
336
338
  export async function tellAkumaOn(seam, input) {
337
339
  const values = requireInput(input, "Akumas.tell input");
338
340
  for (const key of Object.keys(values)) {
@@ -391,8 +393,8 @@ export async function historyAkuma(input) {
391
393
  validateHistoryInput(values);
392
394
  const addressed = await addressAkuma(directAddress(values));
393
395
  try {
394
- const handle = new AkumaOwner(addressed.id, addressed.path);
395
- const contract = await dispatchAssociation(values.repo, addressed.id);
396
+ const handle = new AkumaOwner(addressed.id, addressed.path, outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error }));
397
+ const contract = (await dispatchAssociations(values.repo, [addressed.id])).get(addressed.id);
396
398
  if (values.last === true) {
397
399
  const answer = await handle.lastAnswer();
398
400
  return answer.kind === "answer"
@@ -1,18 +1,17 @@
1
1
  import type { Settings } from "../settings.js";
2
2
  import type { WorldRoot } from "../world.js";
3
- type CalledPluginSignalInput = Readonly<{
3
+ import type { PluginSignal } from "./public.js";
4
+ type PluginSignalEmission = Readonly<{
4
5
  world: WorldRoot;
5
6
  settings?: Settings;
6
7
  reportDiagnostic: (message: string) => void;
7
- akumaId: string;
8
- callerAkumaId?: string;
9
- contractId?: string;
10
8
  }>;
11
- export declare function emitInitiatingPluginSignal(input: Readonly<{
12
- world: WorldRoot;
13
- settings?: Settings;
14
- initiator: string;
15
- reportDiagnostic: (message: string) => void;
16
- }>): Promise<void>;
17
- export declare function emitCalledPluginSignal(input: CalledPluginSignalInput): Promise<void>;
9
+ /**
10
+ * The one producer entry for plugin signals. It owns runtime acquisition, the
11
+ * World Settings fallback, bounded delivery, and failure isolation: a delivery
12
+ * problem reaches the producer only as a diagnostic, never as a thrown error.
13
+ */
14
+ export declare function emitPluginSignal(emission: PluginSignalEmission, signal: PluginSignal): Promise<void>;
15
+ /** One public observer operation, never shared with incidental owner reads. */
16
+ export declare function outcomePluginObserver(emission: PluginSignalEmission, observer?: string): (akumaId: string, historyIds: readonly string[]) => Promise<void>;
18
17
  export {};
@@ -1,22 +1,38 @@
1
- import { pluginRuntime } from "./runtime.js";
2
- export async function emitInitiatingPluginSignal(input) {
3
- const runtime = await pluginRuntime({
4
- world: input.world,
5
- ...(input.settings === undefined ? {} : { settings: input.settings }),
6
- reportDiagnostic: input.reportDiagnostic,
7
- });
8
- await runtime.emit({ kind: "akuma.initiating", initiator: input.initiator }, input.reportDiagnostic);
1
+ import { pluginRuntime, reportPluginDiagnostic } from "./runtime.js";
2
+ /**
3
+ * The one producer entry for plugin signals. It owns runtime acquisition, the
4
+ * World Settings fallback, bounded delivery, and failure isolation: a delivery
5
+ * problem reaches the producer only as a diagnostic, never as a thrown error.
6
+ */
7
+ export async function emitPluginSignal(emission, signal) {
8
+ try {
9
+ const runtime = await pluginRuntime({
10
+ world: emission.world,
11
+ ...(emission.settings === undefined ? {} : { settings: emission.settings }),
12
+ reportDiagnostic: emission.reportDiagnostic,
13
+ });
14
+ await runtime.emit(signal, emission.reportDiagnostic);
15
+ }
16
+ catch (error) {
17
+ reportPluginDiagnostic(emission.reportDiagnostic, "runtime", "signal", error);
18
+ }
9
19
  }
10
- export async function emitCalledPluginSignal(input) {
11
- const runtime = await pluginRuntime({
12
- world: input.world,
13
- ...(input.settings === undefined ? {} : { settings: input.settings }),
14
- reportDiagnostic: input.reportDiagnostic,
15
- });
16
- await runtime.emit({
17
- kind: "akuma.called",
18
- akumaId: input.akumaId,
19
- ...(input.callerAkumaId === undefined ? {} : { callerAkumaId: input.callerAkumaId }),
20
- ...(input.contractId === undefined ? {} : { contractId: input.contractId }),
21
- }, input.reportDiagnostic);
20
+ /** One public observer operation, never shared with incidental owner reads. */
21
+ export function outcomePluginObserver(emission, observer) {
22
+ const seen = new Set();
23
+ return async (akumaId, historyIds) => {
24
+ const fresh = historyIds.filter((historyId) => {
25
+ const key = `${akumaId}:${historyId}`;
26
+ if (seen.has(key))
27
+ return false;
28
+ seen.add(key);
29
+ return true;
30
+ });
31
+ await Promise.all(fresh.map(async (historyId) => await emitPluginSignal(emission, {
32
+ kind: "akuma.outcome-observed",
33
+ akumaId,
34
+ historyId,
35
+ ...(observer === undefined ? {} : { observer }),
36
+ })));
37
+ };
22
38
  }
@@ -24,6 +24,11 @@ export type PluginSignalMap = Readonly<{
24
24
  callerAkumaId?: string;
25
25
  contractId?: string;
26
26
  }>;
27
+ "akuma.outcome-observed": Readonly<{
28
+ akumaId: string;
29
+ historyId: string;
30
+ observer?: string;
31
+ }>;
27
32
  "akuma.turn-outcome": Readonly<{
28
33
  akumaId: string;
29
34
  bodySequence: number;
@@ -10,5 +10,6 @@ type PluginRuntimeInput = Readonly<{
10
10
  export type PluginRuntime = Readonly<{
11
11
  emit(signal: PluginSignal, reportDiagnostic?: PluginDiagnostic): Promise<void>;
12
12
  }>;
13
+ export declare function reportPluginDiagnostic(report: PluginDiagnostic | undefined, subject: string, stage: string, error: unknown): void;
13
14
  export declare function pluginRuntime(input: PluginRuntimeInput): Promise<PluginRuntime>;
14
15
  export {};
@@ -18,7 +18,7 @@ function object(value) {
18
18
  function message(error) {
19
19
  return (error instanceof Error ? error.message : String(error)).slice(0, DIAGNOSTIC_LIMIT);
20
20
  }
21
- function diagnostic(report, subject, stage, error) {
21
+ export function reportPluginDiagnostic(report, subject, stage, error) {
22
22
  if (report === undefined)
23
23
  return;
24
24
  try {
@@ -67,30 +67,30 @@ async function settleBefore(promise, cancellation) {
67
67
  }
68
68
  function selectedEntry(entry, report) {
69
69
  if (entry.name.trim().length === 0) {
70
- diagnostic(report, "<unnamed>", "selection", new TypeError("plugin setting name must be nonblank"));
70
+ reportPluginDiagnostic(report, "<unnamed>", "selection", new TypeError("plugin setting name must be nonblank"));
71
71
  return null;
72
72
  }
73
73
  if (!object(entry.value)) {
74
- diagnostic(report, entry.name, "selection", new TypeError("plugin setting must be an object"));
74
+ reportPluginDiagnostic(report, entry.name, "selection", new TypeError("plugin setting must be an object"));
75
75
  return null;
76
76
  }
77
77
  const names = Object.keys(entry.value);
78
78
  if (!names.includes("package") || names.some((name) => !["package", "enabled", "config"].includes(name))) {
79
- diagnostic(report, entry.name, "selection", new TypeError("plugin setting has unknown or missing fields"));
79
+ reportPluginDiagnostic(report, entry.name, "selection", new TypeError("plugin setting has unknown or missing fields"));
80
80
  return null;
81
81
  }
82
82
  const packageName = entry.value.package;
83
83
  if (typeof packageName !== "string" || packageName.trim().length === 0) {
84
- diagnostic(report, entry.name, "selection", new TypeError("plugin package must be a nonblank string"));
84
+ reportPluginDiagnostic(report, entry.name, "selection", new TypeError("plugin package must be a nonblank string"));
85
85
  return null;
86
86
  }
87
87
  if (packageName !== packageName.trim()) {
88
- diagnostic(report, entry.name, "selection", new TypeError("plugin package must not have surrounding whitespace"));
88
+ reportPluginDiagnostic(report, entry.name, "selection", new TypeError("plugin package must not have surrounding whitespace"));
89
89
  return null;
90
90
  }
91
91
  const enabled = entry.value.enabled;
92
92
  if (enabled !== undefined && typeof enabled !== "boolean") {
93
- diagnostic(report, entry.name, "selection", new TypeError("plugin enabled must be a boolean"));
93
+ reportPluginDiagnostic(report, entry.name, "selection", new TypeError("plugin enabled must be a boolean"));
94
94
  return null;
95
95
  }
96
96
  if (enabled === false)
@@ -101,7 +101,7 @@ function selectedPlugins(input, report) {
101
101
  const view = input.namespace(PLUGIN_NAMESPACE);
102
102
  if (view.kind === "failed") {
103
103
  for (const failure of view.failures)
104
- diagnostic(report, "settings", failure.scope, failure.diagnostic);
104
+ reportPluginDiagnostic(report, "settings", failure.scope, failure.diagnostic);
105
105
  return BUILTIN_PLUGINS;
106
106
  }
107
107
  if (view.entries.length === 0)
@@ -197,6 +197,21 @@ async function writablePaths(world, declarations) {
197
197
  }
198
198
  return paths;
199
199
  }
200
+ /**
201
+ * The runtime's acceptance vocabulary. The record is exhaustive over the public
202
+ * payload map, so adding a signal there fails compilation here until the same
203
+ * kind is accepted.
204
+ */
205
+ const SIGNAL_KINDS = Object.freeze({
206
+ "akuma.initiating": true,
207
+ "akuma.called": true,
208
+ "akuma.outcome-observed": true,
209
+ "akuma.turn-outcome": true,
210
+ "akuma.body-ended": true,
211
+ });
212
+ function isSignalKind(kind) {
213
+ return Object.hasOwn(SIGNAL_KINDS, kind);
214
+ }
200
215
  function handlers(pluginId, instance) {
201
216
  if (!object(instance))
202
217
  throw new TypeError("plugin activation must return an object");
@@ -208,12 +223,8 @@ function handlers(pluginId, instance) {
208
223
  throw new TypeError("plugin signals must be an object");
209
224
  const registered = [];
210
225
  for (const [kind, handler] of Object.entries(instance.signals)) {
211
- if (kind !== "akuma.initiating" &&
212
- kind !== "akuma.called" &&
213
- kind !== "akuma.turn-outcome" &&
214
- kind !== "akuma.body-ended") {
226
+ if (!isSignalKind(kind))
215
227
  throw new TypeError(`plugin signal is unknown: ${kind}`);
216
- }
217
228
  if (typeof handler !== "function")
218
229
  throw new TypeError(`plugin signal handler is not a function: ${kind}`);
219
230
  registered.push({ pluginId, kind, handler });
@@ -270,7 +281,7 @@ async function activate(input) {
270
281
  }
271
282
  catch (error) {
272
283
  markStarted();
273
- diagnostic(report, selected.id, "import", error);
284
+ reportPluginDiagnostic(report, selected.id, "import", error);
274
285
  return [];
275
286
  }
276
287
  if (cancellation.aborted) {
@@ -288,7 +299,7 @@ async function activate(input) {
288
299
  }
289
300
  catch (error) {
290
301
  markStarted();
291
- diagnostic(report, selected.id, "validation", error);
302
+ reportPluginDiagnostic(report, selected.id, "validation", error);
292
303
  return [];
293
304
  }
294
305
  let context;
@@ -307,7 +318,7 @@ async function activate(input) {
307
318
  }
308
319
  catch (error) {
309
320
  markStarted();
310
- diagnostic(report, selected.id, "validation", error);
321
+ reportPluginDiagnostic(report, selected.id, "validation", error);
311
322
  return [];
312
323
  }
313
324
  if (cancellation.aborted) {
@@ -324,16 +335,16 @@ async function activate(input) {
324
335
  return registered;
325
336
  }
326
337
  catch (error) {
327
- diagnostic(report, selected.id, "activation", error);
338
+ reportPluginDiagnostic(report, selected.id, "activation", error);
328
339
  return [];
329
340
  }
330
341
  }
331
342
  async function deliver(entry, signal, reportDiagnostic, timeoutMs) {
332
343
  const result = await boundedAttempt((cancellation) => entry.handler(signal, cancellation), timeoutMs);
333
344
  if (result.kind === "timed-out")
334
- diagnostic(reportDiagnostic, entry.pluginId, "signal", timeoutError());
345
+ reportPluginDiagnostic(reportDiagnostic, entry.pluginId, "signal", timeoutError());
335
346
  if (result.kind === "failed")
336
- diagnostic(reportDiagnostic, entry.pluginId, "signal", result.error);
347
+ reportPluginDiagnostic(reportDiagnostic, entry.pluginId, "signal", result.error);
337
348
  }
338
349
  export async function pluginRuntime(input) {
339
350
  let runtime = PROCESS_RUNTIMES.get(input.world);
@@ -358,7 +369,7 @@ async function createPluginRuntime(input) {
358
369
  releaseStarted();
359
370
  if (result.kind === "settled")
360
371
  return { handlers: result.value, timedOut: false };
361
- diagnostic(report, entry.id, "activation", result.kind === "failed" ? result.error : timeoutError());
372
+ reportPluginDiagnostic(report, entry.id, "activation", result.kind === "failed" ? result.error : timeoutError());
362
373
  return { handlers: [], timedOut: result.kind === "timed-out" };
363
374
  });
364
375
  previousStarted = started;
@@ -372,16 +383,16 @@ async function createPluginRuntime(input) {
372
383
  const activatedHandlers = await settleBefore(activation, cancellation);
373
384
  if (activatedHandlers !== ABORTED) {
374
385
  if (activatedHandlers.timedOut)
375
- diagnostic(reportDiagnostic, selected[index].id, "signal", timeoutError());
386
+ reportPluginDiagnostic(reportDiagnostic, selected[index].id, "signal", timeoutError());
376
387
  return activatedHandlers.handlers;
377
388
  }
378
- diagnostic(reportDiagnostic, selected[index].id, "signal", timeoutError());
389
+ reportPluginDiagnostic(reportDiagnostic, selected[index].id, "signal", timeoutError());
379
390
  return [];
380
391
  }));
381
392
  return handlers.flat();
382
393
  });
383
394
  if (activated.kind === "failed") {
384
- diagnostic(reportDiagnostic, "runtime", "signal", activated.error);
395
+ reportPluginDiagnostic(reportDiagnostic, "runtime", "signal", activated.error);
385
396
  return;
386
397
  }
387
398
  if (activated.kind === "timed-out")
@@ -1,7 +1,7 @@
1
1
  import type { ActiveContractRefusal } from "../core/facts/observation.js";
2
2
  import type { GitTreeSelection } from "../git/read-observation.js";
3
3
  import type { CompanionDecorator } from "./run.js";
4
- import type { IntentOutcome, MutationOperationInput } from "./operations.js";
4
+ import { type IntentOutcome, type MutationOperationInput } from "./operations.js";
5
5
  export declare function abandonOperation(input: MutationOperationInput & Readonly<{
6
6
  note?: string;
7
7
  decorateOffer?: CompanionDecorator;
@@ -1,16 +1,9 @@
1
1
  import { decideAbandon } from "../core/verbs/abandon.js";
2
- import { admitIntent } from "./intent.js";
3
- import { complete } from "./outcome.js";
4
- import { timestamp } from "./operations.js";
2
+ import { admitVoidIntent } from "./operations.js";
5
3
  export async function abandonOperation(input) {
6
- return complete(await admitIntent(input.channel, input.scope, {
7
- contractId: input.contractId,
8
- ...(input.actor === undefined ? {} : { actor: input.actor }),
9
- at: timestamp(),
10
- ...(input.note === undefined ? {} : { note: input.note }),
11
- }, decideAbandon, {
4
+ return admitVoidIntent(input, { ...(input.note === undefined ? {} : { note: input.note }) }, decideAbandon, {
12
5
  ...(input.decorateOffer === undefined ? {} : { decorateOffer: input.decorateOffer }),
13
6
  ...(input.observationSelection === undefined ? {} : { observationSelection: input.observationSelection }),
14
7
  ...(input.progress === undefined ? {} : { progress: input.progress }),
15
- }), undefined);
8
+ });
16
9
  }
@@ -63,14 +63,11 @@ export async function amendOperation(input) {
63
63
  if (decision.kind === "refused")
64
64
  return decision;
65
65
  const admission = await admitDecidedOffer({
66
- channel: input.channel,
67
- repository: input.scope,
66
+ ...input,
68
67
  seat,
69
- decisionObservation: observation,
68
+ observation,
70
69
  attempt: attempts[index],
71
70
  offer: decision.offer,
72
- primaryContract: input.contractId,
73
- ...(input.progress === undefined ? {} : { progress: input.progress }),
74
71
  });
75
72
  if (admission.kind === "accepted") {
76
73
  if (amendment === undefined)
@@ -1,5 +1,5 @@
1
1
  import type { ActiveContractRefusal } from "../core/facts/observation.js";
2
- import type { IntentOutcome, MutationOperationInput } from "./operations.js";
2
+ import { type IntentOutcome, type MutationOperationInput } from "./operations.js";
3
3
  export declare function arcOperation(input: MutationOperationInput & Readonly<{
4
4
  chapter: Readonly<{
5
5
  title: string;
@@ -1,12 +1,5 @@
1
1
  import { decideArc } from "../core/verbs/arc.js";
2
- import { admitIntent } from "./intent.js";
3
- import { complete } from "./outcome.js";
4
- import { timestamp } from "./operations.js";
2
+ import { admitVoidIntent } from "./operations.js";
5
3
  export async function arcOperation(input) {
6
- return complete(await admitIntent(input.channel, input.scope, {
7
- contractId: input.contractId,
8
- ...(input.actor === undefined ? {} : { actor: input.actor }),
9
- at: timestamp(),
10
- data: input.chapter,
11
- }, decideArc), undefined);
4
+ return admitVoidIntent(input, { data: input.chapter }, decideArc);
12
5
  }