@astrosheep/keiyaku 4.6.7 → 4.6.8

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 (165) hide show
  1. package/README.md +6 -2
  2. package/build/plugins/pi/keiyaku.ts +0 -5
  3. package/build/src/akuma/akuma-call.d.ts +2 -0
  4. package/build/src/akuma/akuma-call.js +8 -2
  5. package/build/src/akuma/akuma-instance.d.ts +12 -1
  6. package/build/src/akuma/akuma-instance.js +27 -7
  7. package/build/src/akuma/akuma-observe.js +2 -0
  8. package/build/src/akuma/akuma-owner.d.ts +3 -0
  9. package/build/src/akuma/akuma-owner.js +4 -0
  10. package/build/src/akuma/akuma.d.ts +35 -5
  11. package/build/src/akuma/akuma.js +8 -10
  12. package/build/src/akuma/archetype.d.ts +7 -15
  13. package/build/src/akuma/archetype.js +36 -35
  14. package/build/src/akuma/body.d.ts +5 -3
  15. package/build/src/akuma/body.js +29 -7
  16. package/build/src/akuma/call-request.d.ts +18 -10
  17. package/build/src/akuma/call-request.js +10 -3
  18. package/build/src/akuma/caller.d.ts +39 -0
  19. package/build/src/akuma/caller.js +36 -0
  20. package/build/src/akuma/dispatch-association.d.ts +0 -1
  21. package/build/src/akuma/dispatch-association.js +0 -3
  22. package/build/src/akuma/heart/facts.d.ts +16 -12
  23. package/build/src/akuma/heart/facts.js +8 -0
  24. package/build/src/akuma/heart/index.d.ts +2 -7
  25. package/build/src/akuma/heart/index.js +3 -17
  26. package/build/src/akuma/heart/rows.d.ts +3 -3
  27. package/build/src/akuma/heart/soul.d.ts +1 -1
  28. package/build/src/akuma/heart/soul.js +5 -24
  29. package/build/src/akuma/heart/storage.d.ts +5 -0
  30. package/build/src/akuma/heart/storage.js +7 -3
  31. package/build/src/akuma/identity.d.ts +0 -1
  32. package/build/src/akuma/identity.js +2 -5
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/nuke.js +6 -28
  36. package/build/src/akuma/projection.d.ts +0 -11
  37. package/build/src/akuma/provider-recipe.d.ts +7 -6
  38. package/build/src/akuma/provider-recipe.js +1 -1
  39. package/build/src/akuma/provider.d.ts +6 -10
  40. package/build/src/akuma/provider.js +6 -7
  41. package/build/src/akuma/providers/acp/events.js +5 -18
  42. package/build/src/akuma/providers/acp/index.js +2 -3
  43. package/build/src/akuma/providers/claude/events.js +35 -60
  44. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  45. package/build/src/akuma/providers/claude/index.js +2 -3
  46. package/build/src/akuma/providers/codex-app-server/index.js +2 -2
  47. package/build/src/akuma/providers/decode.d.ts +25 -0
  48. package/build/src/akuma/providers/decode.js +44 -0
  49. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  50. package/build/src/akuma/providers/execution-environment.js +3 -0
  51. package/build/src/akuma/providers/grok-build/index.js +6 -22
  52. package/build/src/akuma/providers/index.js +2 -0
  53. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  54. package/build/src/akuma/providers/lifecycle.js +10 -0
  55. package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
  56. package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
  58. package/build/src/akuma/providers/paseo/events.d.ts +25 -0
  59. package/build/src/akuma/providers/paseo/events.js +157 -0
  60. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  61. package/build/src/akuma/providers/paseo/index.js +353 -0
  62. package/build/src/akuma/providers/pi/events.js +5 -15
  63. package/build/src/akuma/publication.d.ts +2 -0
  64. package/build/src/akuma/publication.js +5 -0
  65. package/build/src/akuma/request-lifecycle.d.ts +3 -0
  66. package/build/src/akuma/request-lifecycle.js +25 -4
  67. package/build/src/akuma/requests.d.ts +3 -1
  68. package/build/src/akuma/requests.js +32 -0
  69. package/build/src/akuma/selection-observation.d.ts +72 -2
  70. package/build/src/akuma/selection-observation.js +0 -6
  71. package/build/src/akuma/turn-drive.js +2 -5
  72. package/build/src/cli/akuma-caller.d.ts +3 -0
  73. package/build/src/cli/akuma-caller.js +21 -0
  74. package/build/src/cli/commands/akuma-grammar.js +7 -12
  75. package/build/src/cli/commands/akuma.js +12 -4
  76. package/build/src/cli/commands/contract-grammar.d.ts +2 -1
  77. package/build/src/cli/commands/contract-grammar.js +13 -15
  78. package/build/src/cli/commands/contract-help.d.ts +2 -1
  79. package/build/src/cli/commands/contract-help.js +31 -1
  80. package/build/src/cli/commands/contract.js +24 -53
  81. package/build/src/cli/commands/task.js +18 -35
  82. package/build/src/cli/parse.d.ts +2 -2
  83. package/build/src/cli/render/catalog.d.ts +2 -5
  84. package/build/src/cli/render/contract-history.js +3 -6
  85. package/build/src/cli/render/contract.js +15 -50
  86. package/build/src/cli/render/receipt.js +3 -10
  87. package/build/src/cli/render/task.d.ts +4 -6
  88. package/build/src/cli/render/task.js +9 -26
  89. package/build/src/cli/runtime.d.ts +1 -1
  90. package/build/src/cli/runtime.js +11 -17
  91. package/build/src/cli/selectors.d.ts +3 -6
  92. package/build/src/cli/selectors.js +22 -53
  93. package/build/src/dispatch/index.d.ts +3 -3
  94. package/build/src/dispatch/index.js +1 -2
  95. package/build/src/git/observe.d.ts +6 -2
  96. package/build/src/git/observe.js +6 -2
  97. package/build/src/index.d.ts +6 -6
  98. package/build/src/index.js +2 -2
  99. package/build/src/kanshi/index.d.ts +1 -1
  100. package/build/src/kanshi/read.js +21 -6
  101. package/build/src/library/address.js +2 -4
  102. package/build/src/library/akuma-creation.d.ts +5 -1
  103. package/build/src/library/akuma-creation.js +27 -47
  104. package/build/src/library/akumas.d.ts +5 -4
  105. package/build/src/library/akumas.js +13 -9
  106. package/build/src/library/bind.d.ts +14 -14
  107. package/build/src/library/bind.js +11 -7
  108. package/build/src/library/contract-address.d.ts +9 -0
  109. package/build/src/library/contract-address.js +71 -0
  110. package/build/src/library/contract-composition.d.ts +4 -7
  111. package/build/src/library/contract-composition.js +6 -18
  112. package/build/src/library/contract-creation.d.ts +3 -5
  113. package/build/src/library/contract-creation.js +19 -17
  114. package/build/src/library/contract-execution.js +18 -23
  115. package/build/src/library/contract-outcomes.d.ts +2 -14
  116. package/build/src/library/contract-outcomes.js +2 -13
  117. package/build/src/library/contract-types.d.ts +36 -2
  118. package/build/src/library/delivery.d.ts +0 -2
  119. package/build/src/library/delivery.js +2 -5
  120. package/build/src/library/keiyaku.d.ts +0 -5
  121. package/build/src/library/keiyaku.js +6 -12
  122. package/build/src/library/outcome.d.ts +500 -499
  123. package/build/src/library/outcome.js +10 -0
  124. package/build/src/library/reconcile.js +8 -16
  125. package/build/src/library/refusal.d.ts +2 -2
  126. package/build/src/library/repo.d.ts +3 -2
  127. package/build/src/library/repo.js +10 -5
  128. package/build/src/library/selection.d.ts +4 -4
  129. package/build/src/library/selection.js +12 -12
  130. package/build/src/plugin/akuma-signals.d.ts +2 -0
  131. package/build/src/plugin/akuma-signals.js +4 -0
  132. package/build/src/plugin/public.d.ts +27 -2
  133. package/build/src/plugin/runtime.js +2 -2
  134. package/build/src/protocol/amend.js +3 -2
  135. package/build/src/protocol/attempt.js +3 -8
  136. package/build/src/protocol/bind.d.ts +2 -2
  137. package/build/src/protocol/bind.js +1 -1
  138. package/build/src/protocol/deliver.js +3 -3
  139. package/build/src/protocol/operations.d.ts +1 -3
  140. package/build/src/protocol/operations.js +0 -8
  141. package/build/src/protocol/outcome.d.ts +1 -2
  142. package/build/src/protocol/outcome.js +1 -13
  143. package/build/src/protocol/placement.js +3 -10
  144. package/build/src/protocol/read/status.js +31 -70
  145. package/build/src/protocol/reintegrate.js +3 -10
  146. package/build/src/protocol/review.js +3 -3
  147. package/build/src/protocol/run.d.ts +5 -1
  148. package/build/src/protocol/run.js +3 -3
  149. package/build/src/runtime/proc/windows-launch.exe +0 -0
  150. package/package.json +8 -4
  151. package/plugins/pi/keiyaku.ts +57 -0
  152. package/skills/keiyaku/SKILL.md +44 -0
  153. package/skills/keiyaku-akuma/SKILL.md +130 -0
  154. package/skills/keiyaku-akuma/references/automation.md +269 -0
  155. package/skills/keiyaku-babysit/SKILL.md +65 -0
  156. package/skills/keiyaku-bind/SKILL.md +216 -0
  157. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  158. package/skills/keiyaku-task/SKILL.md +104 -0
  159. package/skills/keiyaku-workflow/SKILL.md +129 -0
  160. package/build/src/cli/commands/amend.d.ts +0 -12
  161. package/build/src/cli/commands/amend.js +0 -10
  162. package/build/src/cli/commands/bind.d.ts +0 -11
  163. package/build/src/cli/commands/bind.js +0 -23
  164. package/build/src/dispatch/association.d.ts +0 -1
  165. package/build/src/dispatch/association.js +0 -1
@@ -257,6 +257,16 @@ export function errorCategory(error) {
257
257
  return "aborted";
258
258
  return "internal";
259
259
  }
260
+ export async function readContractValue(operation) {
261
+ try {
262
+ return await operation();
263
+ }
264
+ catch (error) {
265
+ if (error instanceof KeiyakuError)
266
+ throw error;
267
+ throw new KeiyakuError(errorCategory(error), errorDiagnostic(error), { cause: error });
268
+ }
269
+ }
260
270
  function errorDiagnostic(error) {
261
271
  return error instanceof Error ? error.message : String(error);
262
272
  }
@@ -54,11 +54,8 @@ function registerLag(scope, error) {
54
54
  function emptySettlement() {
55
55
  return { actions: [], lags: [] };
56
56
  }
57
- function isManagedWorktree(state) {
58
- return state.coordinates.workspace === "worktree";
59
- }
60
57
  function isManagedTerminal(state) {
61
- return state !== null && isManagedWorktree(state) && state.terminal !== null;
58
+ return state !== null && state.terminal !== null;
62
59
  }
63
60
  /**
64
61
  * Terminal cleanup retires the appointed worktree. Name its short name only when this
@@ -76,7 +73,7 @@ function terminalWorktreeOutcome(scope, cleanup, place) {
76
73
  return undefined;
77
74
  }
78
75
  function appointableManagedContracts(states) {
79
- return states.filter((state) => isManagedWorktree(state) && state.terminal === null).map((state) => state.id);
76
+ return states.filter((state) => state.terminal === null).map((state) => state.id);
80
77
  }
81
78
  async function appointPlaces(scope, states) {
82
79
  return await appointManagedWorktrees(scope, appointableManagedContracts(states));
@@ -114,8 +111,6 @@ async function observeState(scope, channel, contractId) {
114
111
  }
115
112
  }
116
113
  async function appointForContract(scope, state) {
117
- if (!isManagedWorktree(state))
118
- return {};
119
114
  try {
120
115
  const register = await appointPlaces(scope, [state]);
121
116
  const place = register.byContract.get(state.id)?.place;
@@ -265,16 +260,13 @@ export async function completeRepoReconcile(input) {
265
260
  if (!isOperationalFailure(error))
266
261
  throw error;
267
262
  const lag = registerLag(input.scope, error);
268
- const contracts = [];
269
- for (const state of states) {
270
- contracts.push({
263
+ return {
264
+ kind: "completed",
265
+ contracts: states.map((state) => ({
271
266
  contractId: state.id,
272
- report: isManagedWorktree(state)
273
- ? { effects: [], lag: [lag], settlement: emptySettlement() }
274
- : await completeReconcile({ ...input, contractId: state.id }),
275
- });
276
- }
277
- return { kind: "completed", contracts };
267
+ report: { effects: [], lag: [lag], settlement: emptySettlement() },
268
+ })),
269
+ };
278
270
  }
279
271
  const places = new Map(appointed.appointments.map((appointment) => [appointment.contract, appointment.place]));
280
272
  const retained = await reconcileAllOperation({
@@ -177,8 +177,8 @@ export declare const keiyakuRefusalSchema: z.ZodUnion<readonly [z.ZodUnion<reado
177
177
  }, z.core.$strict>>>;
178
178
  }, z.core.$strict>]>, z.ZodObject<{
179
179
  kind: z.ZodEnum<{
180
- "unborn-head": "unborn-head";
181
180
  "target-missing": "target-missing";
181
+ "unborn-head": "unborn-head";
182
182
  "invalid-target": "invalid-target";
183
183
  }>;
184
184
  }, z.core.$strict>, z.ZodObject<{
@@ -302,8 +302,8 @@ export declare const operationRefusalSchemas: {
302
302
  contractId: z.ZodPipe<z.ZodString, z.ZodTransform<import("../index.js").ContractId, string>>;
303
303
  }, z.core.$strict>, z.ZodObject<{
304
304
  kind: z.ZodEnum<{
305
- "unborn-head": "unborn-head";
306
305
  "target-missing": "target-missing";
306
+ "unborn-head": "unborn-head";
307
307
  "invalid-target": "invalid-target";
308
308
  }>;
309
309
  }, z.core.$strict>, z.ZodUnion<readonly [z.ZodObject<{
@@ -1,8 +1,9 @@
1
1
  import { type RepositoryScope } from "../protocol/operations.js";
2
2
  import { NoGitWorldError } from "../git/repository.js";
3
3
  export { NoGitWorldError };
4
+ /** One explicit worktree coordinate. The caller resolves relative and ambient spellings, never this edge. */
4
5
  export type RepoAtInput = Readonly<{
5
- path?: string;
6
+ path: string;
6
7
  gitPath?: string;
7
8
  }>;
8
9
  /** One Git world shared by its worktrees; it is coordinate proof and branch observation only. */
@@ -10,7 +11,7 @@ export declare class Repo {
10
11
  readonly root: string;
11
12
  readonly cwd: string;
12
13
  private constructor();
13
- static at(input?: RepoAtInput): Promise<Repo>;
14
+ static at(input: RepoAtInput): Promise<Repo>;
14
15
  currentBranch(): Promise<string | null>;
15
16
  }
16
17
  export declare function scopeForRepo(value: unknown): RepositoryScope;
@@ -1,13 +1,19 @@
1
1
  import { realpath } from "node:fs/promises";
2
- import { resolve } from "node:path";
2
+ import { isAbsolute } from "node:path";
3
3
  import { currentBranchOperation, scopeOperation } from "../protocol/operations.js";
4
4
  import { NoGitWorldError } from "../git/repository.js";
5
5
  import { optionalNonblank, requireInput } from "./input.js";
6
6
  export { NoGitWorldError };
7
7
  const REPO_SCOPES = new WeakMap();
8
- async function resolvePinnedScope(path, gitPath) {
8
+ async function resolvePinnedScope(values) {
9
+ const path = values.path;
10
+ if (typeof path !== "string" || path.trim().length === 0)
11
+ throw new TypeError("repository path must be a nonblank string");
12
+ if (!isAbsolute(path))
13
+ throw new TypeError(`repository path must be absolute: ${path}`);
14
+ const gitPath = optionalNonblank(values.gitPath, "Git executable path");
9
15
  return await scopeOperation({
10
- coordinate: await realpath(resolve(path === undefined ? process.cwd() : path)),
16
+ coordinate: await realpath(path),
11
17
  ...(gitPath === undefined ? {} : { gitPath }),
12
18
  });
13
19
  }
@@ -21,8 +27,7 @@ export class Repo {
21
27
  REPO_SCOPES.set(this, scope);
22
28
  }
23
29
  static async at(input) {
24
- const values = input === undefined ? undefined : requireInput(input, "Repo.at input");
25
- return new Repo(await resolvePinnedScope(optionalNonblank(values?.path, "repository path"), optionalNonblank(values?.gitPath, "Git executable path")));
30
+ return new Repo(await resolvePinnedScope(requireInput(input, "Repo.at input", ["path", "gitPath"])));
26
31
  }
27
32
  async currentBranch() {
28
33
  return await currentBranchOperation({ scope: scopeForRepo(this) });
@@ -5,7 +5,7 @@ import { type ActivityHistory, type OutcomeRow } from "../akuma/projection.js";
5
5
  import { type ExecutionContext } from "../akuma/requests.js";
6
6
  import { type Schema } from "../akuma/schema.js";
7
7
  import type { AkumaAskResult, AkumaKillResult, AkumaObservation, AkumaTellResult, AkumaWaitResult } from "../akuma/selection-observation.js";
8
- import { type DispatchAssociation } from "../dispatch/index.js";
8
+ import type { DispatchAssociation } from "../akuma/dispatch-association.js";
9
9
  import type { WorldRoot } from "../world.js";
10
10
  import { addressAkuma, addressAkumaSet, type AkumaAddressInput, type AkumaSetAddressInput } from "./address.js";
11
11
  import { type Repo } from "./repo.js";
@@ -33,7 +33,7 @@ export type SelectionSeam = Readonly<{
33
33
  tell(addressed: AddressedAkuma, input: AkumaTellInput, signal?: AbortSignal): Promise<AkumaTellResult>;
34
34
  ask<T>(addressed: AddressedAkuma, input: AkumaAskInput<T>, signal?: AbortSignal): Promise<AkumaAskResult<T>>;
35
35
  }>;
36
- export declare function selectionSeam(execution: ExecutionContext): SelectionSeam;
36
+ export declare function selectionSeam(execution: ExecutionContext, reportDiagnostic?: (message: string) => void): SelectionSeam;
37
37
  export type AkumaWaitInput = AkumaSetAddressInput & Readonly<{
38
38
  completion?: "any" | "all";
39
39
  timeoutMs?: number;
@@ -94,7 +94,7 @@ export type AkumaHistoryResult = Readonly<{
94
94
  }>;
95
95
  export declare function statusAkuma(input: AkumaAddressInput & Readonly<{
96
96
  path: WorldRoot;
97
- }>): Promise<AkumaObservation>;
97
+ }>, reportDiagnostic?: (message: string) => void): Promise<AkumaObservation>;
98
98
  export declare function waitAkumaOn(seam: SelectionSeam, input: AkumaWaitInput & Readonly<{
99
99
  path: WorldRoot;
100
100
  }>): Promise<AkumaWaitResult>;
@@ -109,4 +109,4 @@ export declare function askAkumaOn<T = string>(seam: SelectionSeam, input: Akuma
109
109
  }>): Promise<AkumaAskResult<T>>;
110
110
  export declare function historyAkuma(input: AkumaHistoryInput & Readonly<{
111
111
  path: WorldRoot;
112
- }>): Promise<AkumaHistoryResult>;
112
+ }>, reportDiagnostic?: (message: string) => void): Promise<AkumaHistoryResult>;
@@ -13,13 +13,13 @@ 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
+ import { outcomePluginObserver, stderrPluginDiagnostic } from "../plugin/akuma-signals.js";
17
17
  import { addressAkuma, addressAkumaSet, resolveAkuma, resolveAkumaSet, } from "./address.js";
18
18
  import { requireInput } from "./input.js";
19
19
  import { scopeForRepo } from "./repo.js";
20
- export function selectionSeam(execution) {
20
+ export function selectionSeam(execution, reportDiagnostic = stderrPluginDiagnostic) {
21
21
  const channel = executionChannel(execution);
22
- return channel.kind === "body-request" ? forwardedSelection(channel.directory) : localSelection();
22
+ return channel.kind === "body-request" ? forwardedSelection(channel.directory) : localSelection(reportDiagnostic);
23
23
  }
24
24
  function forwardedSelection(directory) {
25
25
  return {
@@ -56,11 +56,11 @@ function forwardedSelection(directory) {
56
56
  },
57
57
  };
58
58
  }
59
- function localSelection() {
59
+ function localSelection(reportDiagnostic) {
60
60
  return {
61
61
  addressOne: addressAkuma,
62
62
  addressSet: addressAkumaSet,
63
- wait: async (addressed, mode, observer) => await localWait(addressed, { ...mode, ...(observer === undefined ? {} : { observer }) }),
63
+ wait: async (addressed, mode, observer) => await localWait(addressed, { ...mode, ...(observer === undefined ? {} : { observer }) }, reportDiagnostic),
64
64
  kill: async (addressed, abort) => await executeKillAkuma({
65
65
  path: addressed.path,
66
66
  ids: addressed.orderedIds,
@@ -78,7 +78,7 @@ function localSelection() {
78
78
  const result = await executeAskAkuma({
79
79
  path: addressed.path,
80
80
  id: addressed.id,
81
- outcomeObserved: outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error }),
81
+ outcomeObserved: outcomePluginObserver({ world: addressed.path, reportDiagnostic }),
82
82
  body: input.body,
83
83
  ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
84
84
  ...(input.schema === undefined ? {} : { schemaJson: schemaJsonText(input.schema) }),
@@ -238,10 +238,10 @@ function setAddress(values) {
238
238
  ...(values.repo === undefined ? {} : { repo: values.repo }),
239
239
  };
240
240
  }
241
- export async function statusAkuma(input) {
241
+ export async function statusAkuma(input, reportDiagnostic = stderrPluginDiagnostic) {
242
242
  const addressed = await addressAkuma(input);
243
243
  try {
244
- return await observeAkuma(await new AkumaOwner(addressed.id, addressed.path, outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error })).status(), addressed.path, input.repo);
244
+ return await observeAkuma(await new AkumaOwner(addressed.id, addressed.path, outcomePluginObserver({ world: addressed.path, reportDiagnostic })).status(), addressed.path, input.repo);
245
245
  }
246
246
  catch (error) {
247
247
  throw observationError(addressed.id, error);
@@ -264,13 +264,13 @@ async function forwardedWait(addressed, input) {
264
264
  ...(input.signal === undefined ? {} : { signal: input.signal }),
265
265
  }));
266
266
  }
267
- async function localWait(addressed, input) {
267
+ async function localWait(addressed, input, reportDiagnostic) {
268
268
  try {
269
269
  return await composeWaitResult(addressed.path, input.repo, await executeWaitAkuma({
270
270
  path: addressed.path,
271
271
  ids: addressed.orderedIds,
272
272
  completion: input.completion,
273
- outcomeObserved: outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error }),
273
+ outcomeObserved: outcomePluginObserver({ world: addressed.path, reportDiagnostic }),
274
274
  ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
275
275
  ...(input.signal === undefined ? {} : { signal: input.signal }),
276
276
  identity: waitIdentityFacts(addressed.path, input.repo, addressed.orderedIds),
@@ -388,12 +388,12 @@ function validateHistoryInput(values) {
388
388
  (values.last === true || values.before !== undefined || values.since !== undefined || values.limit !== undefined))
389
389
  throw new TypeError("id cannot be combined with last, before, since, or limit");
390
390
  }
391
- export async function historyAkuma(input) {
391
+ export async function historyAkuma(input, reportDiagnostic = stderrPluginDiagnostic) {
392
392
  const values = requireInput(input, "Akumas.history input");
393
393
  validateHistoryInput(values);
394
394
  const addressed = await addressAkuma(directAddress(values));
395
395
  try {
396
- const handle = new AkumaOwner(addressed.id, addressed.path, outcomePluginObserver({ world: addressed.path, reportDiagnostic: console.error }));
396
+ const handle = new AkumaOwner(addressed.id, addressed.path, outcomePluginObserver({ world: addressed.path, reportDiagnostic }));
397
397
  const contract = (await dispatchAssociations(values.repo, [addressed.id])).get(addressed.id);
398
398
  if (values.last === true) {
399
399
  const answer = await handle.lastAnswer();
@@ -1,6 +1,8 @@
1
1
  import type { Settings } from "../settings.js";
2
2
  import type { WorldRoot } from "../world.js";
3
3
  import type { PluginSignal } from "./public.js";
4
+ /** The local library observation default; CLI and Body supply their own sinks. */
5
+ export declare function stderrPluginDiagnostic(message: string): void;
4
6
  type PluginSignalEmission = Readonly<{
5
7
  world: WorldRoot;
6
8
  settings?: Settings;
@@ -1,4 +1,8 @@
1
1
  import { pluginRuntime, reportPluginDiagnostic } from "./runtime.js";
2
+ /** The local library observation default; CLI and Body supply their own sinks. */
3
+ export function stderrPluginDiagnostic(message) {
4
+ console.error(message);
5
+ }
2
6
  /**
3
7
  * The one producer entry for plugin signals. It owns runtime acquisition, the
4
8
  * World Settings fallback, bounded delivery, and failure isolation: a delivery
@@ -15,13 +15,38 @@ export type PluginOutcome = Readonly<{
15
15
  reason: string;
16
16
  }>;
17
17
  export type PluginBodyEnd = "exited" | "broke-off" | "put-down" | "hung";
18
+ export type PluginAkumaOrigin = Readonly<{
19
+ kind: "direct";
20
+ }> | Readonly<{
21
+ kind: "request";
22
+ parent: string;
23
+ requestId: string;
24
+ }> | Readonly<{
25
+ kind: "fork";
26
+ parent: string;
27
+ at: string;
28
+ }>;
29
+ export type PluginAkumaCaller = Readonly<{
30
+ kind: "akuma";
31
+ world: string;
32
+ akuId: string;
33
+ }> | Readonly<{
34
+ kind: "external";
35
+ integration: string;
36
+ id: string;
37
+ }> | Readonly<{
38
+ kind: "unknown";
39
+ }>;
18
40
  export type PluginSignalMap = Readonly<{
19
41
  "akuma.initiating": Readonly<{
20
42
  initiator: string;
21
43
  }>;
22
- "akuma.called": Readonly<{
44
+ "akuma.born": Readonly<{
23
45
  akumaId: string;
24
- callerAkumaId?: string;
46
+ bodySequence: number;
47
+ origin: PluginAkumaOrigin;
48
+ caller: PluginAkumaCaller;
49
+ initiator?: string;
25
50
  contractId?: string;
26
51
  }>;
27
52
  "akuma.outcome-observed": Readonly<{
@@ -22,7 +22,7 @@ export function reportPluginDiagnostic(report, subject, stage, error) {
22
22
  if (report === undefined)
23
23
  return;
24
24
  try {
25
- report(`plugin ${subject} ${stage}: ${message(error)}`.slice(0, DIAGNOSTIC_LIMIT));
25
+ void Promise.resolve(report(`plugin ${subject} ${stage}: ${message(error)}`.slice(0, DIAGNOSTIC_LIMIT))).catch(() => { });
26
26
  }
27
27
  catch {
28
28
  // Diagnostics are optional side effects too.
@@ -204,7 +204,7 @@ async function writablePaths(world, declarations) {
204
204
  */
205
205
  const SIGNAL_KINDS = Object.freeze({
206
206
  "akuma.initiating": true,
207
- "akuma.called": true,
207
+ "akuma.born": true,
208
208
  "akuma.outcome-observed": true,
209
209
  "akuma.turn-outcome": true,
210
210
  "akuma.body-ended": true,
@@ -3,7 +3,8 @@ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
3
3
  import { contractState } from "../core/facts/observation.js";
4
4
  import { decideAmend } from "../core/verbs/amend.js";
5
5
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
6
- import { admitted, intentOutcomeWithSeatClose } from "./outcome.js";
6
+ import { admitted } from "./outcome.js";
7
+ import { protocolSeatClose } from "./run.js";
7
8
  import { timestamp } from "./operations.js";
8
9
  async function extendPrerequisiteClosureAt(channel, observation, seeds) {
9
10
  let current = observation;
@@ -34,7 +35,7 @@ export async function amendOperation(input) {
34
35
  const amendment = source === undefined || input.deriveAmendment === undefined
35
36
  ? undefined
36
37
  : { source, ...input.deriveAmendment(source) };
37
- return intentOutcomeWithSeatClose(await withPrivateStatePublicationSeat(input.scope, async (seat) => {
38
+ return protocolSeatClose(await withPrivateStatePublicationSeat(input.scope, async (seat) => {
38
39
  const attempts = mintAttempts({ entryCount: 1 });
39
40
  for (let index = 0; index < attempts.length; index += 1) {
40
41
  let observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
@@ -65,12 +65,6 @@ function validateOffer(offer, attempt) {
65
65
  if (actualEntries.size === 0)
66
66
  throw new Error("offer requires at least one current-attempt ULID");
67
67
  }
68
- function snapshotFor(append, journals, head) {
69
- const record = journals.get(append.contractId);
70
- if (record === undefined)
71
- throw new Error("accepted offer contract is missing from its observation");
72
- return foldJournal(append.contractId, [...record.entries, ...append.entries], head);
73
- }
74
68
  function journalFor(append, journals) {
75
69
  const record = journals.get(append.contractId);
76
70
  if (record === undefined)
@@ -118,11 +112,12 @@ export async function admitDecidedOffer(input) {
118
112
  if (admission.kind === "accepted") {
119
113
  confirmPrivateStatePublication(seat);
120
114
  input.progress?.recordPublication(primaryContract, admission.heads[primary.contractId], offerEntries(offer));
115
+ const journal = journalFor(primary, decisionObservation.journals);
121
116
  const accepted = {
122
117
  kind: "accepted",
123
118
  facts: offerEntries(offer),
124
- state: snapshotFor(primary, decisionObservation.journals, admission.heads[primary.contractId]),
125
- journal: journalFor(primary, decisionObservation.journals),
119
+ state: foldJournal(primary.contractId, journal, admission.heads[primary.contractId]),
120
+ journal,
126
121
  };
127
122
  input.progress?.recordAdmission(accepted);
128
123
  return accepted;
@@ -11,8 +11,8 @@ export type { BindRefusal } from "../core/verbs/bind.js";
11
11
  export type { BindTargetSelection };
12
12
  export declare const targetInputRefusalSchema: z.ZodObject<{
13
13
  kind: z.ZodEnum<{
14
- "unborn-head": "unborn-head";
15
14
  "target-missing": "target-missing";
15
+ "unborn-head": "unborn-head";
16
16
  "invalid-target": "invalid-target";
17
17
  }>;
18
18
  }, z.core.$strict>;
@@ -27,7 +27,7 @@ type BindOperationInput = Readonly<{
27
27
  channel: GitDecodeChannel;
28
28
  terms: BindData["terms"];
29
29
  verification: VerificationDeclarationPreparation;
30
- targetSelection?: BindTargetSelection;
30
+ targetSelection: BindTargetSelection;
31
31
  workspace: "worktree";
32
32
  actor?: ActorId;
33
33
  decorateOffer?: CompanionDecorator;
@@ -67,7 +67,7 @@ async function assembleBindInput(input, selection, seed, prepared) {
67
67
  };
68
68
  }
69
69
  export async function bindOperation(input) {
70
- let selection = input.targetSelection ?? { kind: "targetless" };
70
+ let selection = input.targetSelection;
71
71
  if (selection.kind === "explicit") {
72
72
  const normalized = await normalizeTargetBranch(input.scope, selection.target);
73
73
  if (normalized === null)
@@ -6,13 +6,13 @@ import { materializeIntegrationSnapshot, materializeJudgedConflict, planIntegrat
6
6
  import { captureTender, dirtyTenderRefusal, materializeTenderSnapshot, prepareDeliveryCommitMetadata, } from "../git/tender.js";
7
7
  import { checkoutDetachedSnapshot, recordConflictHandoff, retireConflictHandoff, workspaceMergeStatePresent, worktreePath, conflictRecovery, } from "../git/workspace.js";
8
8
  import { observeContractsForAdmissionAt } from "../git/observe.js";
9
- import { externalPreparation, privateStateSeatAttempt, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
9
+ import { externalPreparation, privateStateSeatAttempt, protocolSeatClose, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
10
10
  import { contractState } from "../core/facts/observation.js";
11
11
  import { decideDeliver } from "../core/verbs/deliver.js";
12
12
  import { currentVerifiedAttestation } from "./intent.js";
13
13
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
14
14
  import { appointmentFor, readPlaceRegister } from "../workspace-place.js";
15
- import { attemptDecisionWithSeatClose, recordedIntegrationSnapshots, timestamp } from "./operations.js";
15
+ import { recordedIntegrationSnapshots, timestamp } from "./operations.js";
16
16
  export const deliverLeadingSchema = z
17
17
  .object({
18
18
  kind: z.enum(["admitted-now", "already-admitted"]),
@@ -418,7 +418,7 @@ async function deliverAttempt(input, attempt) {
418
418
  if (assembled.kind === "stale")
419
419
  return STALE_PRIVATE_STATE_PREPARATION;
420
420
  return await decideAndAdmitDelivery(input, attempt, seat, observation, assembled);
421
- }, attemptDecisionWithSeatClose);
421
+ }, protocolSeatClose);
422
422
  }
423
423
  function isIntegrationConflict(refusal) {
424
424
  return refusal.kind === "integration-failed" && refusal.reason === "conflict";
@@ -2,7 +2,6 @@ import { z } from "zod";
2
2
  import type { DecideInput, OfferDecision } from "../core/decide.js";
3
3
  import type { ActorId, ContractId, ContractState, DeliverData, DocumentKey, JournalEntry, SnapshotId } from "../core/facts/types.js";
4
4
  import type { IntegrationPreparationRefusal } from "../git/integration.js";
5
- import { type PrivateStateSeatOutcome } from "../git/private-state-seat.js";
6
5
  import type { GitRepository } from "../git/process.js";
7
6
  import { type GitDecodeChannel } from "../git/read-observation.js";
8
7
  import type { WorktreeLeak } from "../git/scratch.js";
@@ -389,8 +388,8 @@ export declare const intentRefusalSchema: z.ZodUnion<readonly [z.ZodObject<{
389
388
  }, z.core.$strict>>>;
390
389
  }, z.core.$strict>]>, z.ZodObject<{
391
390
  kind: z.ZodEnum<{
392
- "unborn-head": "unborn-head";
393
391
  "target-missing": "target-missing";
392
+ "unborn-head": "unborn-head";
394
393
  "invalid-target": "invalid-target";
395
394
  }>;
396
395
  }, z.core.$strict>, z.ZodObject<{
@@ -630,7 +629,6 @@ export type AttemptDecision<Value, Refusal = IntentRefusal> = (AcceptedAdmission
630
629
  kind: "publication-failed";
631
630
  }>;
632
631
  export declare function timestamp(): string;
633
- export declare function attemptDecisionWithSeatClose<Value, Refusal = IntentRefusal>(outcome: PrivateStateSeatOutcome<AttemptDecision<Value, Refusal>>): AttemptDecision<Value, Refusal>;
634
632
  export declare function unpackVerificationOutcome(verification: VerificationResult): Readonly<{
635
633
  cleanup?: VerificationCleanupFailure;
636
634
  leak?: WorktreeLeak;
@@ -4,7 +4,6 @@ import { gate } from "../core/facts/types.js";
4
4
  import { changeIdSchema, contractIdSchema, snapshotIdSchema } from "../git/identity.js";
5
5
  import { integrationPreparationRefusalSchema, readDeliveryDiff } from "../git/integration.js";
6
6
  import { currentBranch, observeContractAt } from "../git/observe.js";
7
- import { appendPrivateStateSeatClose, mergePrivateStateSeatClose, } from "../git/private-state-seat.js";
8
7
  import { withGitReadObservation } from "../git/read-observation.js";
9
8
  import { repositoryAt } from "../git/repository.js";
10
9
  import { checkoutNotFollowableRefusalSchema } from "../git/target-placement.js";
@@ -216,13 +215,6 @@ export const placementStopSchema = z.union([
216
215
  export function timestamp() {
217
216
  return new Date().toISOString();
218
217
  }
219
- export function attemptDecisionWithSeatClose(outcome) {
220
- return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
221
- if (value.kind !== "accepted")
222
- throw new Error(closeLag.diagnostic);
223
- return { ...value, seatClose: appendPrivateStateSeatClose(value.seatClose, closeLag) };
224
- });
225
- }
226
218
  function stepStop(result) {
227
219
  if (result.kind === "accepted")
228
220
  return undefined;
@@ -1,7 +1,7 @@
1
1
  import type { ContractHead, ContractState, JournalEntry } from "../core/facts/types.js";
2
2
  import type { WorktreeLeak } from "../git/scratch.js";
3
3
  import type { ReconcileResult } from "../git/reconcile.js";
4
- import { type PrivateStateSeatCloseLag, type PrivateStateSeatOutcome } from "../git/private-state-seat.js";
4
+ import type { PrivateStateSeatCloseLag } from "../git/private-state-seat.js";
5
5
  import type { AcceptedAdmission } from "./attempt.js";
6
6
  import type { VerificationCleanupFailure } from "./intent.js";
7
7
  import type { ProtocolResult, ProtocolTerminal } from "./run.js";
@@ -38,5 +38,4 @@ export type IntentOutcome<Value, Refusal = never> = Readonly<{
38
38
  export declare function accepted<Value, Refusal = never>(state: ContractState, facts: readonly JournalEntry[], value: Value, physical?: ReconcileResult, obligations?: AcceptedObligations): IntentOutcome<Value, Refusal>;
39
39
  export declare function admitted<Value, Refusal = never>(admission: AcceptedProtocolStep, value: Value): IntentOutcome<Value, Refusal>;
40
40
  export declare function complete<Value, Refusal>(result: ProtocolResult<Refusal>, value: Value): IntentOutcome<Value, Refusal>;
41
- export declare function intentOutcomeWithSeatClose<Value, Refusal>(outcome: PrivateStateSeatOutcome<IntentOutcome<Value, Refusal>>): IntentOutcome<Value, Refusal>;
42
41
  export {};
@@ -1,4 +1,3 @@
1
- import { appendPrivateStateSeatClose, mergePrivateStateSeatClose, } from "../git/private-state-seat.js";
2
1
  export function accepted(state, facts, value, physical, obligations) {
3
2
  if (state.head === null)
4
3
  throw new Error("accepted contract is missing its journal head");
@@ -16,12 +15,8 @@ export function accepted(state, facts, value, physical, obligations) {
16
15
  function seatCloseObligations(seatClose) {
17
16
  return seatClose === undefined || seatClose.length === 0 ? {} : { seatClose };
18
17
  }
19
- function admissionObligations(admission) {
20
- const seatClose = admission.seatClose;
21
- return seatClose === undefined || seatClose.length === 0 ? undefined : { seatClose };
22
- }
23
18
  export function admitted(admission, value) {
24
- return accepted(admission.state, admission.facts, value, admission.physical, admissionObligations(admission));
19
+ return accepted(admission.state, admission.facts, value, admission.physical, admission.seatClose === undefined ? undefined : { seatClose: admission.seatClose });
25
20
  }
26
21
  export function complete(result, value) {
27
22
  if (result.kind === "refused")
@@ -30,10 +25,3 @@ export function complete(result, value) {
30
25
  return { kind: "retry", reason: result };
31
26
  return admitted(result, value);
32
27
  }
33
- export function intentOutcomeWithSeatClose(outcome) {
34
- return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
35
- if (value.kind !== "accepted")
36
- throw new Error(closeLag.diagnostic);
37
- return { ...value, seatClose: appendPrivateStateSeatClose(value.seatClose, closeLag) };
38
- });
39
- }
@@ -3,12 +3,12 @@ import { AuthorityCorruptionError } from "../core/facts/errors.js";
3
3
  import { contractState } from "../core/facts/observation.js";
4
4
  import { decidePlacement } from "../core/verbs/placement.js";
5
5
  import { observeContractsForAdmissionAt, observeGitForAdmissionAt } from "../git/observe.js";
6
- import { appendPrivateStateSeatClose, mergePrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
6
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
7
7
  import { reconcileEffectFailure } from "../git/reconcile.js";
8
8
  import { GitPlumbingError } from "../git/process.js";
9
9
  import { acquireTargetPlacementFence, followTargetPlacement, prepareTargetPlacement, prepareTargetPlacementChanges, observeTargetHead, observedTreeEqualsCandidate, } from "../git/target-placement.js";
10
10
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
11
- import { prepareProtocolAttempt, runProtocol } from "./run.js";
11
+ import { prepareProtocolAttempt, protocolSeatClose, runProtocol, } from "./run.js";
12
12
  export { observeTargetPlacement } from "../git/target-placement.js";
13
13
  export async function observeIntegrationTargetMovement(repository, state) {
14
14
  const target = state.coordinates.target;
@@ -39,13 +39,6 @@ function expectedOperationalDiagnostic(error) {
39
39
  function expectedPlacementFailure(error) {
40
40
  return { kind: "placement-failed", diagnostic: expectedOperationalDiagnostic(error) };
41
41
  }
42
- function placementResultWithSeatClose(outcome) {
43
- return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
44
- if (value.kind !== "accepted")
45
- throw new Error(closeLag.diagnostic);
46
- return { ...value, seatClose: appendPrivateStateSeatClose(value.seatClose, closeLag) };
47
- });
48
- }
49
42
  async function placementChangesHint(repository, channel, contractId) {
50
43
  const observation = await observeContractsForAdmissionAt(repository, channel, [contractId]);
51
44
  const state = contractState(observation.decision, contractId);
@@ -63,7 +56,7 @@ async function runFencedPlacement(repository, input, protocol) {
63
56
  (changes?.predecessor !== movement.expectedOid || changes.candidate !== movement.newOid))
64
57
  changes = await prepareTargetPlacementChanges(repository, movement);
65
58
  let preparedPhysical;
66
- const result = placementResultWithSeatClose(await withPrivateStatePublicationSeat(repository, async (seat) => {
59
+ const result = protocolSeatClose(await withPrivateStatePublicationSeat(repository, async (seat) => {
67
60
  // The hint carries no acceptance authority. Form a fresh semantic offer under the seat.
68
61
  const prepared = await prepareProtocolAttempt(protocol, protocol.attempts[index]);
69
62
  if (prepared.kind !== "offered")