@astrosheep/keiyaku 4.6.6 → 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 (217) hide show
  1. package/README.md +11 -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/codex}/.codex-plugin/plugin.json +1 -1
  6. package/build/plugins/codex/skills/keiyaku/SKILL.md +44 -0
  7. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +130 -0
  8. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +269 -0
  9. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +65 -0
  10. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +216 -0
  11. package/build/plugins/codex/skills/keiyaku-bind/agents/openai.yaml +4 -0
  12. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +104 -0
  13. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +129 -0
  14. package/build/plugins/opencode/package.json +6 -0
  15. package/build/plugins/opencode/skills/keiyaku/SKILL.md +44 -0
  16. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +130 -0
  17. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +269 -0
  18. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +65 -0
  19. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +216 -0
  20. package/build/plugins/opencode/skills/keiyaku-bind/agents/openai.yaml +4 -0
  21. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +104 -0
  22. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +129 -0
  23. package/build/{integrations → plugins}/pi/keiyaku.ts +0 -5
  24. package/build/skills/keiyaku/SKILL.md +44 -0
  25. package/build/skills/keiyaku-akuma/SKILL.md +130 -0
  26. package/build/skills/keiyaku-akuma/references/automation.md +269 -0
  27. package/build/skills/keiyaku-babysit/SKILL.md +65 -0
  28. package/build/skills/keiyaku-bind/SKILL.md +216 -0
  29. package/build/skills/keiyaku-bind/agents/openai.yaml +4 -0
  30. package/build/skills/keiyaku-task/SKILL.md +104 -0
  31. package/build/skills/keiyaku-workflow/SKILL.md +129 -0
  32. package/build/src/akuma/akuma-call.d.ts +2 -0
  33. package/build/src/akuma/akuma-call.js +8 -2
  34. package/build/src/akuma/akuma-instance.d.ts +12 -1
  35. package/build/src/akuma/akuma-instance.js +31 -9
  36. package/build/src/akuma/akuma-observe.d.ts +4 -0
  37. package/build/src/akuma/akuma-observe.js +14 -0
  38. package/build/src/akuma/akuma-owner.d.ts +6 -2
  39. package/build/src/akuma/akuma-owner.js +32 -10
  40. package/build/src/akuma/akuma-selection-execution.d.ts +3 -1
  41. package/build/src/akuma/akuma-selection-execution.js +2 -1
  42. package/build/src/akuma/akuma-wait.d.ts +2 -1
  43. package/build/src/akuma/akuma-wait.js +4 -1
  44. package/build/src/akuma/akuma.d.ts +35 -5
  45. package/build/src/akuma/akuma.js +8 -10
  46. package/build/src/akuma/archetype.d.ts +7 -15
  47. package/build/src/akuma/archetype.js +36 -35
  48. package/build/src/akuma/body.d.ts +6 -3
  49. package/build/src/akuma/body.js +41 -30
  50. package/build/src/akuma/call-request.d.ts +18 -10
  51. package/build/src/akuma/call-request.js +10 -3
  52. package/build/src/akuma/caller.d.ts +39 -0
  53. package/build/src/akuma/caller.js +36 -0
  54. package/build/src/akuma/dispatch-association.d.ts +0 -1
  55. package/build/src/akuma/dispatch-association.js +0 -3
  56. package/build/src/akuma/heart/facts.d.ts +16 -12
  57. package/build/src/akuma/heart/facts.js +8 -0
  58. package/build/src/akuma/heart/index.d.ts +2 -7
  59. package/build/src/akuma/heart/index.js +3 -17
  60. package/build/src/akuma/heart/rows.d.ts +3 -3
  61. package/build/src/akuma/heart/soul.d.ts +1 -1
  62. package/build/src/akuma/heart/soul.js +5 -24
  63. package/build/src/akuma/heart/storage.d.ts +5 -0
  64. package/build/src/akuma/heart/storage.js +7 -3
  65. package/build/src/akuma/identity.d.ts +0 -1
  66. package/build/src/akuma/identity.js +2 -5
  67. package/build/src/akuma/index.d.ts +5 -2
  68. package/build/src/akuma/index.js +1 -0
  69. package/build/src/akuma/nuke.js +6 -28
  70. package/build/src/akuma/projection.d.ts +0 -11
  71. package/build/src/akuma/provider-recipe.d.ts +7 -6
  72. package/build/src/akuma/provider-recipe.js +1 -1
  73. package/build/src/akuma/provider.d.ts +6 -10
  74. package/build/src/akuma/provider.js +6 -7
  75. package/build/src/akuma/providers/acp/events.js +5 -18
  76. package/build/src/akuma/providers/acp/index.js +2 -3
  77. package/build/src/akuma/providers/claude/events.js +35 -60
  78. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  79. package/build/src/akuma/providers/claude/index.js +2 -3
  80. package/build/src/akuma/providers/codex-app-server/index.js +2 -2
  81. package/build/src/akuma/providers/decode.d.ts +25 -0
  82. package/build/src/akuma/providers/decode.js +44 -0
  83. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  84. package/build/src/akuma/providers/execution-environment.js +3 -0
  85. package/build/src/akuma/providers/grok-build/index.js +6 -22
  86. package/build/src/akuma/providers/index.js +2 -0
  87. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  88. package/build/src/akuma/providers/lifecycle.js +10 -0
  89. package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
  90. package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
  91. package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
  92. package/build/src/akuma/providers/paseo/events.d.ts +25 -0
  93. package/build/src/akuma/providers/paseo/events.js +157 -0
  94. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  95. package/build/src/akuma/providers/paseo/index.js +353 -0
  96. package/build/src/akuma/providers/pi/events.js +5 -15
  97. package/build/src/akuma/publication.d.ts +2 -0
  98. package/build/src/akuma/publication.js +5 -0
  99. package/build/src/akuma/request-lifecycle.d.ts +3 -0
  100. package/build/src/akuma/request-lifecycle.js +25 -4
  101. package/build/src/akuma/requests.d.ts +3 -1
  102. package/build/src/akuma/requests.js +32 -0
  103. package/build/src/akuma/selection-observation.d.ts +72 -2
  104. package/build/src/akuma/selection-observation.js +0 -6
  105. package/build/src/akuma/selection-owner-port.d.ts +1 -1
  106. package/build/src/akuma/selection-owner-port.js +16 -5
  107. package/build/src/akuma/selection-request.d.ts +2 -0
  108. package/build/src/akuma/selection-request.js +2 -1
  109. package/build/src/akuma/turn-drive.js +2 -5
  110. package/build/src/akuma-body.js +4 -2
  111. package/build/src/cli/akuma-caller.d.ts +3 -0
  112. package/build/src/cli/akuma-caller.js +21 -0
  113. package/build/src/cli/commands/akuma-grammar.js +7 -12
  114. package/build/src/cli/commands/akuma.js +18 -16
  115. package/build/src/cli/commands/contract-grammar.d.ts +2 -1
  116. package/build/src/cli/commands/contract-grammar.js +13 -15
  117. package/build/src/cli/commands/contract-help.d.ts +2 -1
  118. package/build/src/cli/commands/contract-help.js +31 -1
  119. package/build/src/cli/commands/contract.js +24 -53
  120. package/build/src/cli/commands/install.js +3 -3
  121. package/build/src/cli/commands/task.js +18 -35
  122. package/build/src/cli/parse.d.ts +2 -2
  123. package/build/src/cli/render/catalog.d.ts +2 -5
  124. package/build/src/cli/render/contract-history.js +3 -6
  125. package/build/src/cli/render/contract.js +15 -50
  126. package/build/src/cli/render/receipt.js +3 -10
  127. package/build/src/cli/render/task.d.ts +4 -6
  128. package/build/src/cli/render/task.js +9 -26
  129. package/build/src/cli/runtime.d.ts +1 -1
  130. package/build/src/cli/runtime.js +11 -17
  131. package/build/src/cli/selectors.d.ts +3 -6
  132. package/build/src/cli/selectors.js +22 -53
  133. package/build/src/dispatch/index.d.ts +3 -3
  134. package/build/src/dispatch/index.js +1 -2
  135. package/build/src/git/observe.d.ts +6 -2
  136. package/build/src/git/observe.js +6 -2
  137. package/build/src/index.d.ts +6 -6
  138. package/build/src/index.js +2 -2
  139. package/build/src/kanshi/index.d.ts +1 -1
  140. package/build/src/kanshi/read.js +21 -6
  141. package/build/src/library/address.js +2 -4
  142. package/build/src/library/akuma-creation.d.ts +5 -1
  143. package/build/src/library/akuma-creation.js +33 -51
  144. package/build/src/library/akumas.d.ts +5 -4
  145. package/build/src/library/akumas.js +13 -9
  146. package/build/src/library/bind.d.ts +14 -14
  147. package/build/src/library/bind.js +11 -7
  148. package/build/src/library/contract-address.d.ts +9 -0
  149. package/build/src/library/contract-address.js +71 -0
  150. package/build/src/library/contract-composition.d.ts +4 -7
  151. package/build/src/library/contract-composition.js +6 -18
  152. package/build/src/library/contract-creation.d.ts +3 -5
  153. package/build/src/library/contract-creation.js +19 -17
  154. package/build/src/library/contract-execution.js +18 -23
  155. package/build/src/library/contract-outcomes.d.ts +2 -14
  156. package/build/src/library/contract-outcomes.js +2 -13
  157. package/build/src/library/contract-types.d.ts +36 -2
  158. package/build/src/library/delivery.d.ts +0 -2
  159. package/build/src/library/delivery.js +2 -5
  160. package/build/src/library/keiyaku.d.ts +0 -5
  161. package/build/src/library/keiyaku.js +6 -12
  162. package/build/src/library/outcome.d.ts +500 -499
  163. package/build/src/library/outcome.js +10 -0
  164. package/build/src/library/reconcile.js +8 -16
  165. package/build/src/library/refusal.d.ts +2 -2
  166. package/build/src/library/repo.d.ts +3 -2
  167. package/build/src/library/repo.js +10 -5
  168. package/build/src/library/selection.d.ts +4 -4
  169. package/build/src/library/selection.js +12 -9
  170. package/build/src/plugin/akuma-signals.d.ts +12 -11
  171. package/build/src/plugin/akuma-signals.js +40 -20
  172. package/build/src/plugin/public.d.ts +32 -2
  173. package/build/src/plugin/runtime.d.ts +1 -0
  174. package/build/src/plugin/runtime.js +35 -24
  175. package/build/src/protocol/amend.js +3 -2
  176. package/build/src/protocol/attempt.js +3 -8
  177. package/build/src/protocol/bind.d.ts +2 -2
  178. package/build/src/protocol/bind.js +1 -1
  179. package/build/src/protocol/deliver.js +3 -3
  180. package/build/src/protocol/operations.d.ts +1 -3
  181. package/build/src/protocol/operations.js +0 -8
  182. package/build/src/protocol/outcome.d.ts +1 -2
  183. package/build/src/protocol/outcome.js +1 -13
  184. package/build/src/protocol/placement.js +3 -10
  185. package/build/src/protocol/read/status.js +31 -70
  186. package/build/src/protocol/reintegrate.js +3 -10
  187. package/build/src/protocol/review.js +3 -3
  188. package/build/src/protocol/run.d.ts +5 -1
  189. package/build/src/protocol/run.js +3 -3
  190. package/build/src/runtime/proc/windows-launch.exe +0 -0
  191. package/package.json +12 -8
  192. package/plugins/pi/keiyaku.ts +57 -0
  193. package/skills/keiyaku/SKILL.md +44 -0
  194. package/skills/keiyaku-akuma/SKILL.md +130 -0
  195. package/skills/keiyaku-akuma/references/automation.md +269 -0
  196. package/skills/keiyaku-babysit/SKILL.md +65 -0
  197. package/skills/keiyaku-bind/SKILL.md +216 -0
  198. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  199. package/skills/keiyaku-task/SKILL.md +104 -0
  200. package/skills/keiyaku-workflow/SKILL.md +129 -0
  201. package/build/integrations/marketplace/.claude-plugin/marketplace.json +0 -5
  202. package/build/integrations/marketplace/plugins/keiyaku/package.json +0 -17
  203. package/build/src/cli/commands/amend.d.ts +0 -12
  204. package/build/src/cli/commands/amend.js +0 -10
  205. package/build/src/cli/commands/bind.d.ts +0 -11
  206. package/build/src/cli/commands/bind.js +0 -23
  207. package/build/src/dispatch/association.d.ts +0 -1
  208. package/build/src/dispatch/association.js +0 -1
  209. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku/SKILL.md +0 -0
  210. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/SKILL.md +0 -0
  211. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/references/automation.md +0 -0
  212. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-babysit/SKILL.md +0 -0
  213. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/SKILL.md +0 -0
  214. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/agents/openai.yaml +0 -0
  215. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-task/SKILL.md +0 -0
  216. /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-workflow/SKILL.md +0 -0
  217. /package/build/{integrations/marketplace/plugins/keiyaku/opencode.js → plugins/opencode/index.js} +0 -0
@@ -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")
@@ -57,9 +57,6 @@ function appointedWorkspace(repository, register, state) {
57
57
  ? undefined
58
58
  : { contractId: state.id, place: appointed.place, workspace: worktreePath(repository, appointed.place) };
59
59
  }
60
- async function readSelectedHandoffs(observation, workspaces) {
61
- return await readConflictHandoffs(observation.repository, observation.readBlobs, workspaces.flatMap((workspace) => (workspace === undefined ? [] : [workspace])));
62
- }
63
60
  async function managedWorkspaceFacts(repository, state, appointed, targetObservation, handoff) {
64
61
  if (appointed === undefined) {
65
62
  return {
@@ -101,10 +98,10 @@ function afterEdges(state, endpoints) {
101
98
  endpoint: afterEndpoint(endpoints.get(contractId)),
102
99
  }));
103
100
  }
104
- function reverseDependents(id, rows) {
105
- return rows
106
- .filter((row) => row.disposition === "active" && row.after.some((edge) => edge.contractId === id))
107
- .map((row) => ({ contractId: row.id, phase: row.phase }))
101
+ function reverseDependents(id, states) {
102
+ return states
103
+ .filter(({ state }) => state.terminal === null && state.terms.after.includes(id))
104
+ .map(({ state }) => ({ contractId: state.id, phase: phaseFor(state) }))
108
105
  .sort((left, right) => left.contractId.localeCompare(right.contractId));
109
106
  }
110
107
  async function rowFor(input) {
@@ -148,6 +145,25 @@ async function afterEndpointMap(observation, known, ids) {
148
145
  const extra = await observeContractsForAdmissionInObservationAt(observation, missing);
149
146
  return new Map([...known, ...[...extra.journals].map(([id, record]) => [id, record.state])]);
150
147
  }
148
+ async function hydrateRows(observation, states, endpoints, dependentStates = []) {
149
+ const register = await readPlaceRegister(observation.repository);
150
+ const selected = states.map((value) => ({
151
+ ...value,
152
+ workspace: appointedWorkspace(observation.repository, register, value.state),
153
+ }));
154
+ const handoffs = await readConflictHandoffs(observation.repository, observation.readBlobs, selected.flatMap(({ workspace }) => (workspace === undefined ? [] : [workspace])));
155
+ return await Promise.all(selected.map(async ({ state, bindAt, lastJournalAt, workspace }) => await rowFor({
156
+ repository: observation.repository,
157
+ state,
158
+ bindAt,
159
+ lastJournalAt,
160
+ targetObservation: await observeDeliveryTargetAt(observation, state),
161
+ workspace,
162
+ handoff: handoffs.get(state.id),
163
+ after: afterEdges(state, endpoints),
164
+ dependents: reverseDependents(state.id, dependentStates),
165
+ })));
166
+ }
151
167
  /** Build the Contract board from one immutable git observation. */
152
168
  export async function readContractBoard(observation, include) {
153
169
  const observedAt = new Date().toISOString();
@@ -165,29 +181,8 @@ export async function readContractBoard(observation, include) {
165
181
  endpoints = new Map(await afterEndpointMap(observation, endpoints, record.state.terms.after));
166
182
  }
167
183
  }
168
- const register = await readPlaceRegister(observation.repository);
169
- const selected = [...contracts.values()].flatMap((value) => value.state === null
170
- ? []
171
- : [
172
- {
173
- ...value,
174
- state: value.state,
175
- workspace: appointedWorkspace(observation.repository, register, value.state),
176
- },
177
- ]);
178
- const handoffs = await readSelectedHandoffs(observation, selected.map(({ workspace }) => workspace));
179
- const projected = await Promise.all(selected.map(async ({ state, entries, workspace }) => await rowFor({
180
- repository: observation.repository,
181
- state,
182
- bindAt: entries[0].at,
183
- lastJournalAt: lastJournalAtFor(entries),
184
- targetObservation: await observeDeliveryTargetAt(observation, state),
185
- workspace,
186
- handoff: handoffs.get(state.id),
187
- after: afterEdges(state, endpoints),
188
- dependents: [],
189
- })));
190
- const rows = projected.map((row) => ({ ...row, dependents: reverseDependents(row.id, projected) }));
184
+ const selected = selectedContractStates(contracts);
185
+ const rows = await hydrateRows(observation, selected, endpoints, selected);
191
186
  return {
192
187
  root: observation.repository.primaryWorktree,
193
188
  state: observed.snapshot,
@@ -199,8 +194,8 @@ function compareRecentContracts(left, right) {
199
194
  return (right.lastJournalAt.localeCompare(left.lastJournalAt) ||
200
195
  Buffer.compare(Buffer.from(left.state.id), Buffer.from(right.state.id)));
201
196
  }
202
- function activeContractStates(contracts) {
203
- return [...contracts.values()].flatMap((record) => record.state === null || record.state.terminal !== null
197
+ function selectedContractStates(contracts) {
198
+ return [...contracts.values()].flatMap((record) => record.state === null
204
199
  ? []
205
200
  : [
206
201
  {
@@ -210,37 +205,15 @@ function activeContractStates(contracts) {
210
205
  },
211
206
  ]);
212
207
  }
213
- function reverseDependentsFromStates(id, states) {
214
- return states
215
- .filter(({ state }) => state.terms.after.includes(id))
216
- .map(({ state }) => ({ contractId: state.id, phase: phaseFor(state) }))
217
- .sort((left, right) => left.contractId.localeCompare(right.contractId));
218
- }
219
208
  /** Observe a bounded recent active Contract catalogue from one immutable git observation. */
220
209
  export async function readContractCatalogue(observation, limit) {
221
210
  const observedAt = new Date().toISOString();
222
211
  const observed = await observeActiveContractWorld(observation);
223
- const active = activeContractStates(observed.contracts);
212
+ const active = selectedContractStates(observed.contracts).filter(({ state }) => state.terminal === null);
224
213
  const selected = projectBoundedList([...active].sort(compareRecentContracts), limit);
225
214
  const afterIds = selected.rows.flatMap(({ state }) => state.terms.after);
226
215
  const endpoints = await afterEndpointMap(observation, new Map(observed.eligibility), afterIds);
227
- const register = await readPlaceRegister(observation.repository);
228
- const selectedWorkspaces = selected.rows.map((value) => ({
229
- ...value,
230
- workspace: appointedWorkspace(observation.repository, register, value.state),
231
- }));
232
- const handoffs = await readSelectedHandoffs(observation, selectedWorkspaces.map(({ workspace }) => workspace));
233
- const rows = await Promise.all(selectedWorkspaces.map(async ({ state, bindAt, lastJournalAt, workspace }) => await rowFor({
234
- repository: observation.repository,
235
- state,
236
- bindAt,
237
- lastJournalAt,
238
- targetObservation: await observeDeliveryTargetAt(observation, state),
239
- workspace,
240
- handoff: handoffs.get(state.id),
241
- after: afterEdges(state, endpoints),
242
- dependents: reverseDependentsFromStates(state.id, active),
243
- })));
216
+ const rows = await hydrateRows(observation, selected.rows, endpoints, active);
244
217
  return {
245
218
  root: observation.repository.primaryWorktree,
246
219
  state: observed.snapshot,
@@ -270,22 +243,10 @@ export async function readContractObservation(observation, id) {
270
243
  if (state === null)
271
244
  return { kind: "missing", id };
272
245
  const endpoints = await afterEndpointMap(observation, new Map([[id, state]]), state.terms.after);
273
- const register = await readPlaceRegister(observation.repository);
274
- const workspace = appointedWorkspace(observation.repository, register, state);
275
- const handoffs = await readSelectedHandoffs(observation, [workspace]);
246
+ const rows = await hydrateRows(observation, selectedContractStates(observed.journals), endpoints);
276
247
  return {
277
248
  kind: "present",
278
- row: await rowFor({
279
- repository: observation.repository,
280
- state,
281
- bindAt: record.entries[0].at,
282
- lastJournalAt: lastJournalAtFor(record.entries),
283
- targetObservation: await observeDeliveryTargetAt(observation, state),
284
- workspace,
285
- handoff: handoffs.get(state.id),
286
- after: afterEdges(state, endpoints),
287
- dependents: [],
288
- }),
249
+ row: rows[0],
289
250
  };
290
251
  }
291
252
  /** Observe one Contract and its target from one fresh ref epoch. */
@@ -2,18 +2,11 @@ import { contractState } from "../core/facts/observation.js";
2
2
  import { decideReintegrate } from "../core/verbs/reintegrate.js";
3
3
  import { materializeReintegrationSnapshot, persistedTender, planIntegration, reusableIntegrationSnapshot, } from "../git/integration.js";
4
4
  import { observeContractsForAdmissionAt } from "../git/observe.js";
5
- import { appendPrivateStateSeatClose, mergePrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
5
+ import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
6
6
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
7
7
  import { recordedIntegrationSnapshots, timestamp } from "./operations.js";
8
- import { externalPreparation, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
8
+ import { externalPreparation, protocolSeatClose, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
9
9
  import { runUnderTargetPlacementFence } from "./placement.js";
10
- function reintegrationResultWithSeatClose(outcome) {
11
- return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
12
- if (value.kind !== "accepted")
13
- throw new Error(closeLag.diagnostic);
14
- return { ...value, seatClose: appendPrivateStateSeatClose(value.seatClose, closeLag) };
15
- });
16
- }
17
10
  /** Plan and materialize the target-specific reintegration artifacts outside the publication seat. */
18
11
  async function prepareExternalReintegration(input) {
19
12
  return await externalPreparation({ ...input, scope: input.repository }, (observation, state) => planReintegrationArtifacts(input, state, recordedIntegrationSnapshots(observation.journals.get(state.id)?.entries ?? [])));
@@ -54,7 +47,7 @@ async function runReintegration(input) {
54
47
  for (let index = 0; index < attempts.length; index += 1) {
55
48
  const attempt = attempts[index];
56
49
  const external = await prepareExternalReintegration(input);
57
- const result = reintegrationResultWithSeatClose(await withPrivateStatePublicationSeat(input.repository, async (seat) => {
50
+ const result = protocolSeatClose(await withPrivateStatePublicationSeat(input.repository, async (seat) => {
58
51
  const observation = await observeContractsForAdmissionAt(input.repository, input.channel, [input.contractId]);
59
52
  const assembled = assembleReintegrationAttempt(input, observation, external);
60
53
  if (assembled.kind === "stale")
@@ -4,14 +4,14 @@ import { worktreeChangeId } from "../git/integration.js";
4
4
  import { captureTender, dirtyTenderDelta, dirtyTenderRefusal } from "../git/tender.js";
5
5
  import { observeContractsForAdmissionAt } from "../git/observe.js";
6
6
  import { unmergedWorkspacePaths, worktreePath } from "../git/workspace.js";
7
- import { externalPreparation, privateStateSeatAttempt, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
7
+ import { externalPreparation, privateStateSeatAttempt, protocolSeatClose, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
8
8
  import { dependencyKeySet } from "../core/subject.js";
9
9
  import { contractState } from "../core/facts/observation.js";
10
10
  import { gate } from "../core/facts/types.js";
11
11
  import { decideAttestation } from "../core/verbs/attestation.js";
12
12
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
13
13
  import { appointmentFor, readPlaceRegister } from "../workspace-place.js";
14
- import { attemptDecisionWithSeatClose, timestamp } from "./operations.js";
14
+ import { timestamp } from "./operations.js";
15
15
  const REVIEWED = gate("reviewed");
16
16
  const reviewWorkspaceEvidenceSchema = workspaceDirtyDeltaSchema
17
17
  .extend({ unmergedPaths: z.array(z.string().refine((value) => value.trim() !== "")).readonly() })
@@ -153,7 +153,7 @@ async function reviewAttempt(input, attempt) {
153
153
  if (assembled.kind === "stale")
154
154
  return STALE_PRIVATE_STATE_PREPARATION;
155
155
  return await decideAndAdmitReview(input, attempt, seat, observation, assembled);
156
- }, attemptDecisionWithSeatClose);
156
+ }, protocolSeatClose);
157
157
  }
158
158
  export async function admitReviewOperation(input) {
159
159
  const result = await runBoundedAttempts(mintAttempts({ entryCount: 1 }), (attempt) => reviewAttempt(input, attempt));
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import type { ProtocolProgress } from "./progress.js";
3
3
  import { type GitDecisionObservation } from "../git/observe.js";
4
- import { type PrivateStatePublicationSeat, type PrivateStateSeatOutcome } from "../git/private-state-seat.js";
4
+ import { type PrivateStatePublicationSeat, type PrivateStateSeatCloseLag, type PrivateStateSeatOutcome } from "../git/private-state-seat.js";
5
5
  import type { GitDecodeChannel, GitTreeSelection } from "../git/read-observation.js";
6
6
  import type { GitRepository } from "../git/process.js";
7
7
  import { type GitRefAssertion } from "../git/repository.js";
@@ -177,6 +177,10 @@ export declare function externalPreparation<Artifacts>(input: Readonly<{
177
177
  artifacts: Artifacts;
178
178
  }>>;
179
179
  export declare function privateStateSeatAttempt<T>(repository: GitRepository, action: (seat: PrivateStatePublicationSeat) => Promise<T>, wrap: (outcome: PrivateStateSeatOutcome<T>) => T): Promise<T | AttemptTerminal>;
180
+ export declare function protocolSeatClose<T extends Readonly<{
181
+ kind: string;
182
+ seatClose?: readonly PrivateStateSeatCloseLag[];
183
+ }>>(outcome: PrivateStateSeatOutcome<T>): T;
180
184
  /** Form one decided offer without admitting or reinterpreting it. */
181
185
  export declare function prepareProtocolAttempt<Input extends Readonly<{
182
186
  contractId: ContractId;
@@ -122,7 +122,7 @@ async function admitDecidedProtocolOffer(admission, primaryContract, seat, decis
122
122
  assertions: decided.assertions,
123
123
  });
124
124
  }
125
- function protocolAttemptWithSeatClose(outcome) {
125
+ export function protocolSeatClose(outcome) {
126
126
  return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
127
127
  if (value.kind !== "accepted")
128
128
  throw new Error(closeLag.diagnostic);
@@ -137,7 +137,7 @@ async function runDirectProtocolAttempt(input, attempt) {
137
137
  input: input.input,
138
138
  assertions: [],
139
139
  });
140
- }, protocolAttemptWithSeatClose);
140
+ }, protocolSeatClose);
141
141
  }
142
142
  /**
143
143
  * One full attempt: repeatable preparation outside custody, then a single in-custody cycle of
@@ -160,7 +160,7 @@ async function runSplitProtocolAttempt(input, attempt) {
160
160
  input: assembled.input,
161
161
  assertions,
162
162
  });
163
- }, protocolAttemptWithSeatClose);
163
+ }, protocolSeatClose);
164
164
  }
165
165
  /** Form one decided offer without admitting or reinterpreting it. */
166
166
  export async function prepareProtocolAttempt(input, baseAttempt) {
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@astrosheep/keiyaku",
3
- "version": "4.6.6",
3
+ "version": "4.6.8",
4
4
  "workspaces": [
5
- "plugins/*"
5
+ "plugins/square"
6
6
  ],
7
7
  "files": [
8
- "build"
8
+ "build",
9
+ "plugins/pi",
10
+ "skills"
9
11
  ],
10
12
  "main": "./build/src/index.js",
11
13
  "types": "./build/src/index.d.ts",
@@ -29,7 +31,7 @@
29
31
  },
30
32
  "scripts": {
31
33
  "release": "npm run test:release && npm version patch && npm publish",
32
- "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-integrations.js && node scripts/build-windows-launcher.js && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('build/src/cli/index.js', 0o755)\"",
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)\"",
33
35
  "prepack": "node scripts/verify-package.js",
34
36
  "postpack": "node scripts/verify-package.js",
35
37
  "harness:version": "node scripts/update-harness-version.js",
@@ -73,8 +75,10 @@
73
75
  "dependencies": {
74
76
  "@agentclientprotocol/sdk": "^1.3.0",
75
77
  "@anthropic-ai/claude-agent-sdk": "^0.3.226",
76
- "@astrosheep/keiyaku-plugin-square": "0.1.7",
77
- "@astrosheep/square": "^0.3.63",
78
+ "@astrosheep/keiyaku-plugin-square": "0.1.8",
79
+ "@astrosheep/square": "^0.3.70",
80
+ "@getpaseo/client": "0.11.2",
81
+ "@getpaseo/protocol": "0.11.2",
78
82
  "@opencode-ai/sdk": "1.18.3",
79
83
  "cross-spawn": "^7.0.6",
80
84
  "diff": "^8.0.4",
@@ -91,10 +95,10 @@
91
95
  ],
92
96
  "pi": {
93
97
  "extensions": [
94
- "./build/integrations/pi/keiyaku.ts"
98
+ "./plugins/pi/keiyaku.ts"
95
99
  ],
96
100
  "skills": [
97
- "./build/integrations/marketplace/plugins/keiyaku/skills"
101
+ "./skills"
98
102
  ]
99
103
  },
100
104
  "author": "",
@@ -0,0 +1,57 @@
1
+ import type { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent";
2
+
3
+ type ExecResult = Readonly<{ stdout: string; stderr: string; code: number }>;
4
+
5
+ async function runStatus(pi: ExtensionAPI): Promise<ExecResult> {
6
+ return await pi.exec("keiyaku", ["status"]);
7
+ }
8
+
9
+ function lineForWidth(value: string, width: number): string {
10
+ const clean = value.replaceAll(/[\u0000-\u001f\u007f]/gu, " ");
11
+ return clean.length <= width ? clean : `${clean.slice(0, Math.max(0, width - 1))}…`;
12
+ }
13
+
14
+ function overlay(lines: readonly string[], theme: Theme, done: () => void) {
15
+ return {
16
+ invalidate(): void {},
17
+ handleInput(data: string): void {
18
+ if (data === "\u001b" || data === "q" || data === "Q" || data === "\r") done();
19
+ },
20
+ render(width: number): string[] {
21
+ const inner = Math.max(1, Math.min(100, width - 2));
22
+ const border = theme.fg("border", "+");
23
+ const rule = theme.fg("border", "-".repeat(inner));
24
+ return [
25
+ `${border}${rule}${border}`,
26
+ `${theme.fg("border", "|")}${lineForWidth("Keiyaku", inner).padEnd(inner)}${theme.fg("border", "|")}`,
27
+ `${theme.fg("border", "|")}${" ".repeat(inner)}${theme.fg("border", "|")}`,
28
+ ...lines.map(
29
+ (line) => `${theme.fg("border", "|")}${lineForWidth(line, inner).padEnd(inner)}${theme.fg("border", "|")}`,
30
+ ),
31
+ `${theme.fg("border", "|")}${" ".repeat(inner)}${theme.fg("border", "|")}`,
32
+ `${theme.fg("border", "|")}${lineForWidth("esc/q/enter close", inner).padEnd(inner)}${theme.fg("border", "|")}`,
33
+ `${border}${rule}${border}`,
34
+ ];
35
+ },
36
+ };
37
+ }
38
+
39
+ export default function keiyakuExtension(pi: ExtensionAPI): void {
40
+ pi.registerCommand("keiyaku", {
41
+ description: "Open the Kanshi world status",
42
+ handler: async (_args, ctx) => {
43
+ if (!ctx.hasUI) return;
44
+ let body: string[];
45
+ try {
46
+ const result = await runStatus(pi);
47
+ body = result.code === 0 ? result.stdout.trimEnd().split("\n") : [result.stderr.trim() || "status unavailable"];
48
+ } catch {
49
+ body = ["status unavailable"];
50
+ }
51
+ await ctx.ui.custom<void>((_tui, theme, _keybindings, done) => overlay(body, theme, done), {
52
+ overlay: true,
53
+ overlayOptions: { anchor: "center", width: 100, maxHeight: 40 },
54
+ });
55
+ },
56
+ });
57
+ }
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: keiyaku
3
+ description: >-
4
+ Keiyaku is a CLI that records plans, writes handoff terms for deliveries,
5
+ and calls delegates. Use this skill when you need to figure out which
6
+ Keiyaku skill or command to reach for.
7
+ ---
8
+
9
+ # Keiyaku
10
+
11
+ ## Model
12
+
13
+ Keiyaku is three independent pillars, not a bundle: **Task** remembers plans
14
+ and dependencies, **Contract** makes acceptance standing and auditable,
15
+ **Akuma** invokes capability. Use any one alone; combine them only when the
16
+ work calls for it. Behind every Contract in flight there is one holder of its
17
+ fulfillment loop — whoever turns intent into commissions and returns into
18
+ decisions. The flagship holds it by default, and may hand a whole Contract's
19
+ loop to one Aku in a single commission; the harness serves both styles
20
+ equally. See `keiyaku-workflow` for the loop, `keiyaku-bind` for authoring,
21
+ `keiyaku-akuma` for invocation.
22
+
23
+ ## Quick Start
24
+
25
+ ```bash
26
+ keiyaku -C <repo> task add "title"
27
+ keiyaku -C <repo> task start <task-id>
28
+ keiyaku -C <repo> bind [--task <task-id>] -
29
+ keiyaku -C <repo> status
30
+ keiyaku -C <repo> deliver [<contract>|@<contract>]
31
+ keiyaku -C <repo> review [<contract>|@<contract>] --satisfied
32
+ ```
33
+
34
+ `-C` selects the invocation cwd and therefore the World. `--repo <path>` only
35
+ selects the Contract repository; it never retargets that World. `call
36
+ --workdir <path>` selects execution cwd (relative to the effective invocation
37
+ cwd). Without it, the call uses the invocation cwd; `--contract` associates a
38
+ Contract without selecting an execution directory.
39
+
40
+ `deliver`, `review`, and `audit` may take time after their leading admission.
41
+ Their witnessed progress is ephemeral stderr output; stdout remains one final
42
+ text or JSON result. Ctrl-C asks the owned operation to stop and waits for its
43
+ truthful final receipt, so it is not evidence that an already admitted action
44
+ was rolled back.