@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
@@ -1,24 +1,24 @@
1
1
  import { contractIdSchema } from "../git/identity.js";
2
2
  import { z } from "zod";
3
- import { taskIdSchema } from "../task/identity.js";
3
+ import { debtIdSchema } from "../debt/identity.js";
4
4
  import { observeContractsForAdmissionAt } from "../git/observe.js";
5
5
  import { appendPrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
6
6
  import { GitPlumbingError } from "../git/process.js";
7
7
  import { SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
8
8
  import { AuthorityCorruptionError } from "../core/facts/errors.js";
9
- import { settleTask } from "../task/operations.js";
10
- import { publishTaskHolderRelease, readTaskHolderProjectionFromDecision, taskHolderObservationSelection, } from "./holder.js";
11
- import { acquireTaskSettlementFence } from "./fence.js";
9
+ import { settleDebt } from "../debt/operations.js";
10
+ import { publishDebtHolderRelease, readDebtHolderProjectionFromDecision, debtHolderObservationSelection, } from "./holder.js";
11
+ import { acquireDebtSettlementFence } from "./fence.js";
12
12
  import { World } from "../world.js";
13
13
  export const settlementActionSchema = z
14
- .object({ kind: z.literal("task"), taskId: taskIdSchema, action: z.literal("done") })
14
+ .object({ kind: z.literal("debt"), debtId: debtIdSchema, action: z.literal("done") })
15
15
  .strict();
16
16
  export const settlementLagSchema = z
17
17
  .object({
18
18
  kind: z.literal("settlement-failed"),
19
- surface: z.enum(["task-holder", "task"]),
19
+ surface: z.enum(["debt-holder", "debt"]),
20
20
  contractId: contractIdSchema,
21
- taskId: taskIdSchema.optional(),
21
+ debtId: debtIdSchema.optional(),
22
22
  path: z
23
23
  .string()
24
24
  .refine((value) => value.trim() !== "")
@@ -36,10 +36,10 @@ function operational(error) {
36
36
  function diagnostic(error) {
37
37
  return error instanceof Error ? error.message : String(error);
38
38
  }
39
- function taskFailure(result) {
39
+ function debtFailure(result) {
40
40
  return result.kind === "retry"
41
- ? `Task settlement requires retry: ${result.reason}`
42
- : `Task settlement refused: ${JSON.stringify(result.refusal)}`;
41
+ ? `Debt settlement requires retry: ${result.reason}`
42
+ : `Debt settlement refused: ${JSON.stringify(result.refusal)}`;
43
43
  }
44
44
  function recordLag(input, lag) {
45
45
  input.lags.push(lag);
@@ -53,11 +53,11 @@ async function observeApplicableHolder(input) {
53
53
  const { repository, channel, candidate } = input;
54
54
  let observation;
55
55
  try {
56
- observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id], taskHolderObservationSelection());
56
+ observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id], debtHolderObservationSelection());
57
57
  const state = observation.journals.get(candidate.id)?.state ?? null;
58
58
  if (state === null || state.terminal?.kind !== "claimed")
59
59
  return null;
60
- const holder = (await readTaskHolderProjectionFromDecision(channel, observation)).get(candidate.id) ?? null;
60
+ const holder = (await readDebtHolderProjectionFromDecision(channel, observation)).get(candidate.id) ?? null;
61
61
  return holder?.disposition === "held" ? holder : null;
62
62
  }
63
63
  catch (error) {
@@ -65,15 +65,15 @@ async function observeApplicableHolder(input) {
65
65
  throw error;
66
66
  recordLag(input, {
67
67
  kind: "settlement-failed",
68
- surface: "task-holder",
68
+ surface: "debt-holder",
69
69
  contractId: candidate.id,
70
70
  diagnostic: diagnostic(error),
71
71
  });
72
72
  return null;
73
73
  }
74
74
  }
75
- async function completeHeldTask(input) {
76
- const { repository, candidate, taskId } = input;
75
+ async function completeHeldDebt(input) {
76
+ const { repository, candidate, debtId } = input;
77
77
  let world;
78
78
  try {
79
79
  world = await World.at(repository.primaryWorktree);
@@ -83,38 +83,38 @@ async function completeHeldTask(input) {
83
83
  throw error;
84
84
  recordLag(input, {
85
85
  kind: "settlement-failed",
86
- surface: "task",
86
+ surface: "debt",
87
87
  contractId: candidate.id,
88
- taskId,
88
+ debtId,
89
89
  diagnostic: diagnostic(error),
90
90
  });
91
91
  return false;
92
92
  }
93
93
  let result;
94
94
  try {
95
- result = await settleTask(world, taskId);
95
+ result = await settleDebt(world, debtId);
96
96
  }
97
97
  catch (error) {
98
98
  if (!operational(error))
99
99
  throw error;
100
100
  recordLag(input, {
101
101
  kind: "settlement-failed",
102
- surface: "task",
102
+ surface: "debt",
103
103
  contractId: candidate.id,
104
- taskId,
104
+ debtId,
105
105
  diagnostic: diagnostic(error),
106
106
  });
107
107
  return false;
108
108
  }
109
109
  if (result.kind === "changed")
110
- recordAction(input, { kind: "task", taskId, action: "done" });
110
+ recordAction(input, { kind: "debt", debtId, action: "done" });
111
111
  if (result.kind === "changed" && result.cleanup !== undefined) {
112
112
  for (const detail of result.cleanup.diagnostics) {
113
113
  recordLag(input, {
114
114
  kind: "settlement-failed",
115
- surface: "task",
115
+ surface: "debt",
116
116
  contractId: candidate.id,
117
- taskId,
117
+ debtId,
118
118
  diagnostic: detail,
119
119
  });
120
120
  }
@@ -123,32 +123,32 @@ async function completeHeldTask(input) {
123
123
  return true;
124
124
  recordLag(input, {
125
125
  kind: "settlement-failed",
126
- surface: "task",
126
+ surface: "debt",
127
127
  contractId: candidate.id,
128
- taskId,
129
- diagnostic: taskFailure(result),
128
+ debtId,
129
+ diagnostic: debtFailure(result),
130
130
  });
131
131
  return false;
132
132
  }
133
- async function releaseHeldTaskHolder(input) {
134
- const { repository, channel, candidate, seatClose, taskId } = input;
133
+ async function releaseHeldDebtHolder(input) {
134
+ const { repository, channel, candidate, seatClose, debtId } = input;
135
135
  try {
136
136
  const outcome = await withPrivateStatePublicationSeat(repository, async (seat) => {
137
- const observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id], taskHolderObservationSelection());
137
+ const observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id], debtHolderObservationSelection());
138
138
  const state = observation.journals.get(candidate.id)?.state ?? null;
139
139
  if (state === null || state.terminal?.kind !== "claimed")
140
140
  return "inert";
141
- const holder = (await readTaskHolderProjectionFromDecision(channel, observation)).get(candidate.id) ?? null;
142
- if (holder === null || holder.disposition !== "held" || holder.taskId !== taskId)
141
+ const holder = (await readDebtHolderProjectionFromDecision(channel, observation)).get(candidate.id) ?? null;
142
+ if (holder === null || holder.disposition !== "held" || holder.debtId !== debtId)
143
143
  return "inert";
144
- const publication = await publishTaskHolderRelease(repository, channel, observation, candidate.id, seat);
144
+ const publication = await publishDebtHolderRelease(repository, channel, observation, candidate.id, seat);
145
145
  if (publication.kind === "non-published") {
146
146
  recordLag(input, {
147
147
  kind: "settlement-failed",
148
- surface: "task-holder",
148
+ surface: "debt-holder",
149
149
  contractId: candidate.id,
150
- taskId,
151
- diagnostic: `Task holder release requires retry: ${publication.diagnostic}`,
150
+ debtId,
151
+ diagnostic: `Debt holder release requires retry: ${publication.diagnostic}`,
152
152
  });
153
153
  return "held";
154
154
  }
@@ -165,51 +165,51 @@ async function releaseHeldTaskHolder(input) {
165
165
  throw error;
166
166
  recordLag(input, {
167
167
  kind: "settlement-failed",
168
- surface: "task-holder",
168
+ surface: "debt-holder",
169
169
  contractId: candidate.id,
170
- taskId,
170
+ debtId,
171
171
  diagnostic: diagnostic(error),
172
172
  });
173
173
  return "held";
174
174
  }
175
175
  }
176
- async function settleTasks(input) {
176
+ async function settleDebts(input) {
177
177
  const { repository, channel, candidate, lags, seatClose } = input;
178
178
  const hint = await observeApplicableHolder(input);
179
179
  if (hint === null)
180
180
  return false;
181
- const taskId = hint.taskId;
181
+ const debtId = hint.debtId;
182
182
  let fence;
183
183
  try {
184
- fence = await acquireTaskSettlementFence(repository, taskId);
184
+ fence = await acquireDebtSettlementFence(repository, debtId);
185
185
  }
186
186
  catch (error) {
187
187
  if (!operational(error))
188
188
  throw error;
189
189
  recordLag(input, {
190
190
  kind: "settlement-failed",
191
- surface: "task",
191
+ surface: "debt",
192
192
  contractId: candidate.id,
193
- taskId,
193
+ debtId,
194
194
  diagnostic: diagnostic(error),
195
195
  });
196
196
  return true;
197
197
  }
198
198
  let failure;
199
- let taskSettled = false;
199
+ let debtSettled = false;
200
200
  let holderDisposition = null;
201
201
  try {
202
202
  const holder = await observeApplicableHolder(input);
203
- if (holder === null || holder.taskId !== taskId)
203
+ if (holder === null || holder.debtId !== debtId)
204
204
  return false;
205
- taskSettled = await completeHeldTask({ ...input, taskId });
206
- if (!taskSettled)
205
+ debtSettled = await completeHeldDebt({ ...input, debtId });
206
+ if (!debtSettled)
207
207
  return true;
208
- holderDisposition = await releaseHeldTaskHolder({
208
+ holderDisposition = await releaseHeldDebtHolder({
209
209
  repository,
210
210
  channel,
211
211
  candidate,
212
- taskId,
212
+ debtId,
213
213
  lags,
214
214
  seatClose,
215
215
  ...(input.progress === undefined ? {} : { progress: input.progress }),
@@ -229,15 +229,15 @@ async function settleTasks(input) {
229
229
  if (failure === undefined)
230
230
  throw error;
231
231
  }
232
- else if (!taskSettled && failure === undefined)
232
+ else if (!debtSettled && failure === undefined)
233
233
  throw error;
234
234
  // Post-release fence teardown is custodial residue, not an owed holder publication.
235
235
  if (holderDisposition !== "released") {
236
236
  recordLag(input, {
237
237
  kind: "settlement-failed",
238
- surface: "task-holder",
238
+ surface: "debt-holder",
239
239
  contractId: candidate.id,
240
- taskId,
240
+ debtId,
241
241
  diagnostic: diagnostic(error),
242
242
  });
243
243
  }
@@ -258,7 +258,7 @@ async function settleObserved(input) {
258
258
  const candidate = input.state;
259
259
  if (candidate.terminal?.kind === "claimed") {
260
260
  try {
261
- await settleTasks({
261
+ await settleDebts({
262
262
  repository: input.repository,
263
263
  channel: input.channel,
264
264
  candidate,
@@ -273,7 +273,7 @@ async function settleObserved(input) {
273
273
  throw error;
274
274
  recordLag({ candidate, lags, ...(input.progress === undefined ? {} : { progress: input.progress }) }, {
275
275
  kind: "settlement-failed",
276
- surface: "task",
276
+ surface: "debt",
277
277
  contractId: candidate.id,
278
278
  diagnostic: diagnostic(error),
279
279
  });
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@astrosheep/keiyaku",
3
- "version": "4.6.8",
3
+ "version": "4.6.9",
4
4
  "workspaces": [
5
- "plugins/square"
5
+ "plugins/square",
6
+ "plugins/paseo/forwarder"
6
7
  ],
7
8
  "files": [
8
9
  "build",
9
10
  "plugins/pi",
11
+ "plugins/paseo/plugin",
10
12
  "skills"
11
13
  ],
12
14
  "main": "./build/src/index.js",
@@ -31,7 +33,7 @@
31
33
  },
32
34
  "scripts": {
33
35
  "release": "npm run test:release && npm version patch && npm publish",
34
- "build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('build', { recursive: true, force: true })\" && tsc -p tsconfig.json && npm run build --workspace @astrosheep/keiyaku-plugin-square && node scripts/copy-plugins.js && node scripts/build-windows-launcher.js && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('build/src/cli/index.js', 0o755)\"",
36
+ "build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('build', { recursive: true, force: true })\" && tsc -p tsconfig.json && npm run build --workspace @astrosheep/keiyaku-plugin-square && npm run build --workspace @astrosheep/keiyaku-plugin-paseo && node scripts/copy-plugins.js && node scripts/build-windows-launcher.js && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('build/src/cli/index.js', 0o755)\"",
35
37
  "prepack": "node scripts/verify-package.js",
36
38
  "postpack": "node scripts/verify-package.js",
37
39
  "harness:version": "node scripts/update-harness-version.js",
@@ -63,8 +65,10 @@
63
65
  },
64
66
  "devDependencies": {
65
67
  "@earendil-works/pi-coding-agent": "^1.0.0",
68
+ "@getpaseo/plugin": "0.11.2",
66
69
  "@types/cross-spawn": "^6.0.6",
67
70
  "@types/node": "^25.0.0",
71
+ "@types/ws": "^8.18.2",
68
72
  "@typescript-eslint/parser": "^8.66.0",
69
73
  "eslint": "^9.39.5",
70
74
  "knip": "^6.31.0",
@@ -75,13 +79,15 @@
75
79
  "dependencies": {
76
80
  "@agentclientprotocol/sdk": "^1.3.0",
77
81
  "@anthropic-ai/claude-agent-sdk": "^0.3.226",
78
- "@astrosheep/keiyaku-plugin-square": "0.1.8",
79
- "@astrosheep/square": "^0.3.70",
82
+ "@astrosheep/keiyaku-plugin-paseo": "0.1.0",
83
+ "@astrosheep/keiyaku-plugin-square": "0.1.9",
84
+ "@astrosheep/square": "^0.3.79",
80
85
  "@getpaseo/client": "0.11.2",
81
86
  "@getpaseo/protocol": "0.11.2",
82
- "@opencode-ai/sdk": "1.18.3",
87
+ "@opencode/client": "2.0.20",
83
88
  "cross-spawn": "^7.0.6",
84
89
  "diff": "^8.0.4",
90
+ "undici": "8.10.2",
85
91
  "yaml": "^2.9.0",
86
92
  "zod": "^4.5.2"
87
93
  },
@@ -0,0 +1,17 @@
1
+ import type { PluginServerContext } from "@getpaseo/plugin/server";
2
+ import { createProvider } from "./server/provider.js";
3
+ import { createSdkTransport } from "./server/sdk.js";
4
+ import { attach } from "./server/attach.js";
5
+ import { attachRpc } from "./shared/attach-rpc.js";
6
+ import { refreshRpc } from "./shared/refresh-rpc.js";
7
+
8
+ export default function contribute(server: PluginServerContext) {
9
+ const transport = createSdkTransport();
10
+ const mirror = createProvider(transport);
11
+ server.registerProvider(mirror.provider);
12
+ server.handle(refreshRpc, (input) => mirror.refresh(input));
13
+ server.handle(attachRpc, (input, context) => attach(input, context, mirror.sync));
14
+ return async () => {
15
+ try { await mirror.close(); } finally { await transport.close(); }
16
+ };
17
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "id": "keiyaku-paseo",
3
+ "requirements": { "paseo": ">=0.11.2" }
4
+ }
@@ -0,0 +1,52 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import type { PluginHandlerContext } from "@getpaseo/plugin/server";
3
+ import type { z } from "zod";
4
+ import type { attachRpc } from "../shared/attach-rpc.js";
5
+
6
+ function skip(reason: string) {
7
+ console.warn(`Keiyaku mirror not attached: ${reason}`);
8
+ return { attached: false };
9
+ }
10
+ export async function attach(input: z.output<typeof attachRpc.input>, { paseo }: PluginHandlerContext,
11
+ sync: (input: { world: string; akuId: string }) => Promise<void>) {
12
+ const caller = input.caller;
13
+ if (caller?.kind !== "external") return skip("caller is not an external host");
14
+ const native = ["codex", "pi", "claude"].includes(caller.integration);
15
+ let parentId = caller.id;
16
+ const matches = (agent: { persistence?: { provider: string; sessionId: string } | null }) =>
17
+ agent.persistence?.provider === caller.integration && agent.persistence.sessionId === caller.id;
18
+ if (native) {
19
+ const candidates: string[] = [];
20
+ let cursor: string | undefined;
21
+ do {
22
+ const filter = { includeArchived: true };
23
+ const page = await paseo.agents.list({ filter, page: { limit: 200, ...(cursor ? { cursor } : {}) } });
24
+ for (const { agent } of page.entries) if (matches(agent)) candidates.push(agent.id);
25
+ if (candidates.length > 1) return skip(`ambiguous ${caller.integration} session ${caller.id}: multiple parents`);
26
+ if (!page.pageInfo.hasMore) break;
27
+ const next = page.pageInfo.nextCursor;
28
+ if (!next || next === cursor) return skip("incomplete parent directory pagination");
29
+ cursor = next;
30
+ } while (cursor);
31
+ if (!candidates[0]) return skip(`no parent for ${caller.integration} session ${caller.id}`);
32
+ parentId = candidates[0];
33
+ } else if (caller.integration !== "paseo") {
34
+ return skip(`unsupported caller integration ${caller.integration}`);
35
+ }
36
+ const parent = await paseo.agents.ref(parentId).refresh();
37
+ if (!parent) return skip(`parent ${parentId} does not exist`);
38
+ if (parent.agent.archivedAt) return skip(`parent ${parentId} is archived`);
39
+ if (native && !matches(parent.agent)) return skip(`parent ${parentId} changed native identity`);
40
+ const world = await realpath(input.world);
41
+ // Keep the creation fingerprint immutable: aliases belong to the forwarder's
42
+ // rename path, not this idempotent request (including retries after rename).
43
+ await paseo.agents.create({ parent: parentId, cwd: parent.agent.cwd, title: input.akuId,
44
+ config: { provider: "keiyaku/mirror", options: { world, akuId: input.akuId } },
45
+ idempotencyKey: `keiyaku:${world}:${input.akuId}`,
46
+ });
47
+ // Creation returns only after the host has registered and subscribed to the session.
48
+ // Opening's ready event is too early to restore running presentation there.
49
+ try { await sync({ world, akuId: input.akuId }); }
50
+ catch (error) { console.warn(`Keiyaku mirror attached, but synchronization failed: ${error instanceof Error ? error.message : String(error)}`); }
51
+ return { attached: true };
52
+ }
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+
3
+ export const identityKeys = [
4
+ "CLAUDE_CODE_SESSION_ID", "CLAUDE_CODE_CHILD_SESSION", "CLAUDECODE", "CODEX_THREAD_ID",
5
+ "OPENCODE_SESSION_ID", "PI_SESSION_ID", "PI_SESSION_FILE", "PASEO_AGENT_ID",
6
+ "SQUARE_PARTICIPANT_NAME", "AKUMA_REQUESTS", "KEIYAKU_ACTOR_ID", "KEIYAKU_EXTERNAL_CALLER",
7
+ ] as const;
8
+ const count = z.number().int().nonnegative();
9
+ const base = z.object({ sequence: count, at: z.string() });
10
+ const turnFields = { turnSequence: count };
11
+ const input = z.object({ json: z.string(), truncated: z.boolean() });
12
+ const call = z.discriminatedUnion("kind", [
13
+ z.object({ kind: z.literal("run"), command: z.string() }),
14
+ z.object({ kind: z.literal("read"), path: z.string(), offset: count.optional(), limit: count.optional() }),
15
+ z.object({ kind: z.literal("search"), query: z.string(), scope: z.enum(["content", "files", "web"]).optional(),
16
+ path: z.string().optional(), glob: z.string().optional() }),
17
+ z.object({ kind: z.literal("fileChange"), changes: z.array(z.object({
18
+ op: z.enum(["add", "update", "delete", "unspecified"]), path: z.string(),
19
+ diffstat: z.object({ added: count, removed: count }).optional(), patch: z.string().optional(),
20
+ })) }),
21
+ z.object({ kind: z.literal("other"), display: z.string(), input: input.optional() }),
22
+ ]);
23
+ const row = z.union([
24
+ base.extend({ kind: z.literal("turn"), ...turnFields, bodySequence: count.optional() }),
25
+ base.extend({ kind: z.literal("tell"), tellId: z.string(), text: z.string(), state: z.enum(["pending", "told"]),
26
+ deliveries: z.array(z.object({ deliveredAt: z.string(), route: z.enum(["launch", "live"]),
27
+ turnSequence: count, receipt: z.enum(["unavailable", "required"]).optional() })).optional() }),
28
+ base.extend({ kind: z.literal("outcome"), ...turnFields, outcome: z.discriminatedUnion("kind", [
29
+ z.object({ kind: z.literal("answered"), historyId: z.string().optional(), answer: z.string(),
30
+ foldedSaidSequence: count.optional() }),
31
+ z.object({ kind: z.literal("failed"), historyId: z.string().optional(), diagnostic: z.string() }),
32
+ ]) }),
33
+ base.extend({ kind: z.literal("tool"), ...turnFields, name: z.string(), toolId: z.string().optional(), call,
34
+ state: z.union([z.enum(["active", "unsettled"]), z.object({ status: z.enum(["ok", "error"]),
35
+ message: z.string().optional(), exitCode: z.number().int().optional(), output: z.string().optional() })]),
36
+ durationMs: z.number().nonnegative().optional(), truncated: z.literal(true).optional() }),
37
+ base.extend({ kind: z.enum(["said", "thought", "note", "call"]), ...turnFields, text: z.string(),
38
+ truncated: z.literal(true).optional() }),
39
+ ]);
40
+ export const historySchema = z.object({ rows: z.array(row), omitted: count,
41
+ hasEarlier: z.boolean(), hasLater: z.boolean(), historyLost: z.boolean(),
42
+ lowestRetained: count.nullable(), highest: count.nullable() });
43
+ export type Row = z.infer<typeof row>;
44
+ export type History = z.infer<typeof historySchema>;
@@ -0,0 +1,60 @@
1
+ import type { ProviderEvent, ProviderPrompt } from "@getpaseo/plugin/server/provider";
2
+ import { z } from "zod";
3
+
4
+ const sequence = z.number().int().nonnegative();
5
+ export const tellReceiptSchema = z.object({
6
+ akuma: z.string(),
7
+ tell: z.object({
8
+ admission: z.object({ fact: z.literal("recorded"), tellId: z.string().min(1) }),
9
+ row: z.object({ kind: z.literal("tell"), sequence, at: z.string(), tellId: z.string().min(1), text: z.string(),
10
+ state: z.enum(["pending", "told"]), deliveries: z.array(z.object({
11
+ route: z.enum(["live", "launch"]), turnSequence: sequence, deliveredAt: z.string(),
12
+ receipt: z.enum(["unavailable", "required"]).optional(),
13
+ })).optional() }),
14
+ wake: z.discriminatedUnion("kind", [
15
+ z.object({ kind: z.literal("told") }), z.object({ kind: z.literal("held") }),
16
+ z.object({ kind: z.literal("pursuing"), bodySequence: sequence }),
17
+ z.object({ kind: z.literal("failed"), diagnostic: z.string() }),
18
+ ]),
19
+ }),
20
+ });
21
+ /** One durable Tell admission and the wake it observed, however that wake settled. */
22
+ export type TellAdmission = z.infer<typeof tellReceiptSchema>["tell"];
23
+ export type AdmittedMessage = TellAdmission["row"];
24
+ /** Submit one plain-text Tell and return its admission receipt. */
25
+ export type Tell = (world: string, akuId: string, signal: AbortSignal, text: string) => Promise<TellAdmission>;
26
+ type PromptResult = Extract<ProviderEvent, { type: "session.prompt_result" }>["result"];
27
+
28
+ export function messageText(prompt: ProviderPrompt): string {
29
+ // Paseo requests stale permission cleanup on ordinary steering. This mirror
30
+ // owns no permission requests, so there is nothing to clear.
31
+ if (prompt.outputSchema !== undefined) {
32
+ throw new Error("Keiyaku messages do not support output schemas");
33
+ }
34
+ if (prompt.input.type !== "message") {
35
+ throw new Error("Keiyaku messages support plain text only, not commands");
36
+ }
37
+ const parts: string[] = [];
38
+ for (const part of prompt.input.content) {
39
+ if (part.type !== "text" || "mimeType" in part) throw new Error("Keiyaku messages support plain text only, not attachments");
40
+ parts.push(part.text);
41
+ }
42
+ const text = parts.join("\n");
43
+ if (!text.trim()) throw new Error("Keiyaku messages require nonblank text");
44
+ return text;
45
+ }
46
+
47
+ /**
48
+ * Map one admitted Tell to its Paseo presentation. Paseo steering acknowledges
49
+ * durable input acceptance, never native delivery: the observed Turn is a host
50
+ * presentation correlation, never a Heart binding.
51
+ */
52
+ export function tellPresentation(admitted: TellAdmission, steerTurnId?: string): { row: AdmittedMessage; result: PromptResult } {
53
+ const { row, wake } = admitted;
54
+ if (wake.kind === "failed") console.warn(`Keiyaku Tell ${row.tellId} recorded; wake failed: ${wake.diagnostic}`);
55
+ if (steerTurnId !== undefined) return { row, result: { type: "steer", turnId: steerTurnId } };
56
+ const delivery = row.deliveries?.at(-1);
57
+ if (delivery) return { row, result: { type: "turn", turnId: `turn/${delivery.turnSequence}` } };
58
+ // The host may complete its send command; no Akuma outcome is manufactured.
59
+ return { row, result: { type: "completed" } };
60
+ }