@astrosheep/keiyaku 4.0.0 → 4.0.2

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 (308) hide show
  1. package/README.md +133 -8
  2. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
  3. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
  4. package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
  5. package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
  9. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
  10. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
  11. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
  12. package/build/src/akuma/abort.d.ts +2 -0
  13. package/build/src/akuma/abort.js +50 -0
  14. package/build/src/akuma/akuma.d.ts +50 -33
  15. package/build/src/akuma/akuma.js +175 -127
  16. package/build/src/akuma/archetype.d.ts +14 -5
  17. package/build/src/akuma/archetype.js +85 -39
  18. package/build/src/akuma/body.d.ts +3 -5
  19. package/build/src/akuma/body.js +490 -183
  20. package/build/src/akuma/coordinate.d.ts +9 -0
  21. package/build/src/akuma/coordinate.js +22 -0
  22. package/build/src/akuma/heart/facts.d.ts +88 -45
  23. package/build/src/akuma/heart/facts.js +19 -8
  24. package/build/src/akuma/heart/index.d.ts +64 -55
  25. package/build/src/akuma/heart/index.js +172 -252
  26. package/build/src/akuma/heart/rows.d.ts +38 -83
  27. package/build/src/akuma/heart/rows.js +117 -155
  28. package/build/src/akuma/heart/schema.d.ts +1 -1
  29. package/build/src/akuma/heart/schema.js +61 -22
  30. package/build/src/akuma/heart/soul.d.ts +8 -0
  31. package/build/src/akuma/heart/soul.js +136 -0
  32. package/build/src/akuma/heart/storage.d.ts +47 -0
  33. package/build/src/akuma/heart/storage.js +224 -0
  34. package/build/src/akuma/heart/tells.d.ts +12 -0
  35. package/build/src/akuma/heart/tells.js +79 -0
  36. package/build/src/akuma/heart/timeline.d.ts +15 -0
  37. package/build/src/akuma/heart/timeline.js +86 -0
  38. package/build/src/akuma/identity.d.ts +2 -2
  39. package/build/src/akuma/identity.js +9 -9
  40. package/build/src/akuma/index.d.ts +10 -3
  41. package/build/src/akuma/index.js +7 -1
  42. package/build/src/akuma/projection.d.ts +176 -0
  43. package/build/src/akuma/projection.js +256 -0
  44. package/build/src/akuma/provider-recipe.d.ts +24 -0
  45. package/build/src/akuma/provider-recipe.js +100 -0
  46. package/build/src/akuma/provider.d.ts +67 -13
  47. package/build/src/akuma/provider.js +172 -105
  48. package/build/src/akuma/providers/acp/core.d.ts +19 -0
  49. package/build/src/akuma/providers/acp/core.js +159 -0
  50. package/build/src/akuma/providers/acp/events.d.ts +20 -0
  51. package/build/src/akuma/providers/acp/events.js +73 -0
  52. package/build/src/akuma/providers/acp/index.d.ts +12 -0
  53. package/build/src/akuma/providers/acp/index.js +94 -0
  54. package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
  55. package/build/src/akuma/providers/claude/events.js +238 -0
  56. package/build/src/akuma/providers/claude/index.d.ts +47 -0
  57. package/build/src/akuma/providers/claude/index.js +279 -0
  58. package/build/src/akuma/providers/claude/input.d.ts +13 -0
  59. package/build/src/akuma/providers/claude/input.js +109 -0
  60. package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
  61. package/build/src/akuma/providers/codex-app-server/events.js +15 -12
  62. package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
  63. package/build/src/akuma/providers/codex-app-server/index.js +77 -33
  64. package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
  65. package/build/src/akuma/providers/grok-build/index.js +70 -0
  66. package/build/src/akuma/providers/index.d.ts +5 -3
  67. package/build/src/akuma/providers/index.js +35 -56
  68. package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
  69. package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
  70. package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
  71. package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
  72. package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
  73. package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
  74. package/build/src/akuma/providers/pi/events.d.ts +33 -0
  75. package/build/src/akuma/providers/pi/events.js +166 -0
  76. package/build/src/akuma/providers/pi/index.d.ts +11 -0
  77. package/build/src/akuma/providers/pi/index.js +191 -0
  78. package/build/src/akuma/publication.d.ts +3 -3
  79. package/build/src/akuma/publication.js +28 -40
  80. package/build/src/akuma/requests.d.ts +9 -6
  81. package/build/src/akuma/requests.js +95 -65
  82. package/build/src/alias/index.d.ts +4 -3
  83. package/build/src/alias/index.js +12 -13
  84. package/build/src/body/decode.js +7 -1
  85. package/build/src/body/region.d.ts +2 -0
  86. package/build/src/body/region.js +77 -7
  87. package/build/src/body/render.js +2 -1
  88. package/build/src/body/shape.js +7 -1
  89. package/build/src/body/verification.js +19 -4
  90. package/build/src/cli/accepted.d.ts +18 -12
  91. package/build/src/cli/accepted.js +73 -34
  92. package/build/src/cli/actor.js +3 -3
  93. package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
  94. package/build/src/cli/commands/akuma-invoke.js +101 -52
  95. package/build/src/cli/commands/akuma.d.ts +27 -9
  96. package/build/src/cli/commands/akuma.js +151 -80
  97. package/build/src/cli/commands/contract.d.ts +155 -0
  98. package/build/src/cli/commands/contract.js +20 -0
  99. package/build/src/cli/commands/install.js +2 -0
  100. package/build/src/cli/commands/task-invoke.d.ts +19 -4
  101. package/build/src/cli/commands/task-invoke.js +65 -17
  102. package/build/src/cli/commands/task-query.d.ts +5 -0
  103. package/build/src/cli/commands/task-query.js +247 -0
  104. package/build/src/cli/commands/task.d.ts +3 -1
  105. package/build/src/cli/commands/task.js +52 -14
  106. package/build/src/cli/coordinates.d.ts +18 -0
  107. package/build/src/cli/coordinates.js +120 -0
  108. package/build/src/cli/draft.d.ts +8 -0
  109. package/build/src/cli/draft.js +96 -0
  110. package/build/src/cli/invoke.d.ts +9 -3
  111. package/build/src/cli/invoke.js +287 -108
  112. package/build/src/cli/main.js +54 -7
  113. package/build/src/cli/parse.d.ts +21 -117
  114. package/build/src/cli/parse.js +79 -84
  115. package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
  116. package/build/src/cli/render/akuma-tool-command.js +144 -0
  117. package/build/src/cli/render/akuma-tool.d.ts +4 -2
  118. package/build/src/cli/render/akuma-tool.js +35 -5
  119. package/build/src/cli/render/akuma.d.ts +3 -1
  120. package/build/src/cli/render/akuma.js +247 -212
  121. package/build/src/cli/render/audit.d.ts +3 -0
  122. package/build/src/cli/render/audit.js +104 -0
  123. package/build/src/cli/render/catalog.d.ts +2 -0
  124. package/build/src/cli/render/catalog.js +16 -0
  125. package/build/src/cli/render/contract.d.ts +3 -3
  126. package/build/src/cli/render/contract.js +200 -54
  127. package/build/src/cli/render/kanshi.js +272 -129
  128. package/build/src/cli/render/receipt.d.ts +19 -0
  129. package/build/src/cli/render/receipt.js +106 -0
  130. package/build/src/cli/render/refusal.d.ts +16 -2
  131. package/build/src/cli/render/refusal.js +88 -3
  132. package/build/src/cli/render/region.d.ts +2 -0
  133. package/build/src/cli/render/region.js +17 -0
  134. package/build/src/cli/render/task.d.ts +2 -1
  135. package/build/src/cli/render/task.js +223 -60
  136. package/build/src/cli/render/terminal.d.ts +20 -0
  137. package/build/src/cli/render/terminal.js +121 -0
  138. package/build/src/cli/render/text.js +11 -3
  139. package/build/src/cli/result.d.ts +126 -19
  140. package/build/src/cli/usage.d.ts +1 -0
  141. package/build/src/cli/usage.js +3 -0
  142. package/build/src/contract-worktree.d.ts +44 -0
  143. package/build/src/contract-worktree.js +251 -0
  144. package/build/src/coordination/durable-file.d.ts +5 -1
  145. package/build/src/coordination/durable-file.js +57 -10
  146. package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
  147. package/build/src/coordination/sqlite-transaction-lock.js +22 -5
  148. package/build/src/core/facts/codec.js +23 -4
  149. package/build/src/core/facts/eligibility.d.ts +1 -10
  150. package/build/src/core/facts/eligibility.js +0 -49
  151. package/build/src/core/facts/fold.js +1 -6
  152. package/build/src/core/facts/gate.d.ts +1 -0
  153. package/build/src/core/facts/gate.js +1 -0
  154. package/build/src/core/facts/observation.d.ts +3 -0
  155. package/build/src/core/facts/observation.js +12 -0
  156. package/build/src/core/facts/types.d.ts +10 -3
  157. package/build/src/core/subject.js +2 -2
  158. package/build/src/core/verbs/amend.d.ts +1 -1
  159. package/build/src/core/verbs/amend.js +3 -18
  160. package/build/src/core/verbs/bind.js +2 -16
  161. package/build/src/core/verbs/deliver.d.ts +1 -1
  162. package/build/src/core/verbs/deliver.js +14 -4
  163. package/build/src/core/verbs/placement.d.ts +1 -1
  164. package/build/src/core/verbs/placement.js +7 -9
  165. package/build/src/dispatch/index.d.ts +5 -3
  166. package/build/src/dispatch/index.js +30 -21
  167. package/build/src/duration.d.ts +10 -0
  168. package/build/src/duration.js +22 -0
  169. package/build/src/git/admission.d.ts +2 -2
  170. package/build/src/git/admission.js +33 -23
  171. package/build/src/git/hooks.d.ts +15 -0
  172. package/build/src/git/hooks.js +70 -18
  173. package/build/src/git/identity.d.ts +5 -1
  174. package/build/src/git/identity.js +23 -4
  175. package/build/src/git/integration.d.ts +48 -0
  176. package/build/src/git/integration.js +250 -0
  177. package/build/src/git/observe.d.ts +29 -15
  178. package/build/src/git/observe.js +185 -76
  179. package/build/src/git/read-observation.d.ts +41 -0
  180. package/build/src/git/read-observation.js +361 -0
  181. package/build/src/git/reconcile.d.ts +17 -5
  182. package/build/src/git/reconcile.js +305 -109
  183. package/build/src/git/repository.d.ts +41 -18
  184. package/build/src/git/repository.js +220 -114
  185. package/build/src/git/scratch.d.ts +17 -0
  186. package/build/src/git/scratch.js +73 -0
  187. package/build/src/git/target-placement.d.ts +92 -0
  188. package/build/src/git/target-placement.js +375 -0
  189. package/build/src/git/tender.d.ts +49 -0
  190. package/build/src/git/tender.js +63 -0
  191. package/build/src/git/terminal-seal.d.ts +24 -0
  192. package/build/src/git/terminal-seal.js +89 -0
  193. package/build/src/git/tree.d.ts +2 -2
  194. package/build/src/git/tree.js +4 -0
  195. package/build/src/git/workspace.d.ts +53 -0
  196. package/build/src/git/workspace.js +139 -0
  197. package/build/src/identity/selector.d.ts +6 -0
  198. package/build/src/identity/selector.js +19 -0
  199. package/build/src/index.d.ts +4 -2
  200. package/build/src/index.js +2 -1
  201. package/build/src/kanshi/index.d.ts +2 -2
  202. package/build/src/kanshi/index.js +1 -1
  203. package/build/src/kanshi/read.d.ts +7 -3
  204. package/build/src/kanshi/read.js +245 -45
  205. package/build/src/kanshi/report.d.ts +81 -6
  206. package/build/src/kanshi/select.d.ts +5 -0
  207. package/build/src/kanshi/select.js +33 -1
  208. package/build/src/library/address.d.ts +57 -0
  209. package/build/src/library/address.js +165 -0
  210. package/build/src/library/akuma-creation.d.ts +16 -7
  211. package/build/src/library/akuma-creation.js +96 -22
  212. package/build/src/library/audit.d.ts +18 -0
  213. package/build/src/library/audit.js +44 -0
  214. package/build/src/library/bind.d.ts +21 -0
  215. package/build/src/library/bind.js +56 -0
  216. package/build/src/library/catalog.d.ts +58 -0
  217. package/build/src/library/catalog.js +69 -0
  218. package/build/src/library/configuration.d.ts +6 -15
  219. package/build/src/library/configuration.js +14 -17
  220. package/build/src/library/contract.d.ts +23 -49
  221. package/build/src/library/contract.js +171 -185
  222. package/build/src/library/delivery.d.ts +24 -0
  223. package/build/src/library/delivery.js +21 -0
  224. package/build/src/library/fleet.d.ts +65 -0
  225. package/build/src/library/fleet.js +153 -0
  226. package/build/src/library/input.d.ts +3 -0
  227. package/build/src/library/input.js +19 -0
  228. package/build/src/library/keiyaku.d.ts +18 -3
  229. package/build/src/library/keiyaku.js +12 -1
  230. package/build/src/library/mutation.d.ts +39 -0
  231. package/build/src/library/mutation.js +37 -0
  232. package/build/src/library/reconcile.d.ts +29 -0
  233. package/build/src/library/reconcile.js +179 -0
  234. package/build/src/library/refusal.d.ts +21 -0
  235. package/build/src/library/refusal.js +29 -0
  236. package/build/src/library/region.d.ts +14 -1
  237. package/build/src/library/region.js +18 -4
  238. package/build/src/library/repo.d.ts +4 -13
  239. package/build/src/library/repo.js +14 -24
  240. package/build/src/protocol/attempt.d.ts +16 -3
  241. package/build/src/protocol/attempt.js +41 -10
  242. package/build/src/protocol/bind.d.ts +9 -2
  243. package/build/src/protocol/bind.js +48 -40
  244. package/build/src/protocol/intent.d.ts +57 -20
  245. package/build/src/protocol/intent.js +55 -79
  246. package/build/src/protocol/operations.d.ts +152 -43
  247. package/build/src/protocol/operations.js +482 -166
  248. package/build/src/protocol/outcome.d.ts +14 -3
  249. package/build/src/protocol/outcome.js +11 -3
  250. package/build/src/protocol/placement.d.ts +41 -0
  251. package/build/src/protocol/placement.js +147 -0
  252. package/build/src/protocol/read/documents.d.ts +2 -2
  253. package/build/src/protocol/read/documents.js +4 -4
  254. package/build/src/protocol/read/status.d.ts +18 -5
  255. package/build/src/protocol/read/status.js +73 -13
  256. package/build/src/protocol/run.d.ts +49 -7
  257. package/build/src/protocol/run.js +53 -25
  258. package/build/src/runtime/proc/line-rpc.d.ts +4 -8
  259. package/build/src/runtime/proc/line-rpc.js +22 -28
  260. package/build/src/runtime/proc/run.d.ts +23 -21
  261. package/build/src/runtime/proc/run.js +123 -89
  262. package/build/src/runtime/proc/stdio.d.ts +18 -0
  263. package/build/src/runtime/proc/stdio.js +58 -0
  264. package/build/src/settings.d.ts +7 -1
  265. package/build/src/settings.js +32 -17
  266. package/build/src/settlement/fence.d.ts +5 -0
  267. package/build/src/settlement/fence.js +14 -0
  268. package/build/src/settlement/holder.d.ts +35 -4
  269. package/build/src/settlement/holder.js +127 -28
  270. package/build/src/settlement/settle.d.ts +9 -1
  271. package/build/src/settlement/settle.js +74 -37
  272. package/build/src/task/board.d.ts +23 -5
  273. package/build/src/task/board.js +17 -10
  274. package/build/src/task/compose.d.ts +2 -2
  275. package/build/src/task/compose.js +18 -10
  276. package/build/src/task/context.d.ts +3 -3
  277. package/build/src/task/context.js +15 -20
  278. package/build/src/task/document.d.ts +2 -1
  279. package/build/src/task/document.js +15 -5
  280. package/build/src/task/index.d.ts +27 -15
  281. package/build/src/task/index.js +57 -35
  282. package/build/src/task/operations.d.ts +38 -13
  283. package/build/src/task/operations.js +80 -46
  284. package/build/src/task/query.d.ts +67 -0
  285. package/build/src/task/query.js +279 -0
  286. package/build/src/task/store.d.ts +5 -7
  287. package/build/src/task/store.js +43 -28
  288. package/build/src/verification/declaration.d.ts +1 -0
  289. package/build/src/verification/execution.d.ts +51 -0
  290. package/build/src/verification/execution.js +108 -0
  291. package/build/src/workspace-place.d.ts +41 -0
  292. package/build/src/workspace-place.js +386 -0
  293. package/build/src/world.d.ts +24 -0
  294. package/build/src/world.js +136 -0
  295. package/package.json +8 -4
  296. package/build/src/akuma/activity.d.ts +0 -66
  297. package/build/src/akuma/activity.js +0 -139
  298. package/build/src/akuma/providers/claude.js +0 -305
  299. package/build/src/context-root.d.ts +0 -4
  300. package/build/src/context-root.js +0 -15
  301. package/build/src/git/delivery.d.ts +0 -20
  302. package/build/src/git/delivery.js +0 -109
  303. package/build/src/git/verification.d.ts +0 -14
  304. package/build/src/git/verification.js +0 -56
  305. package/build/src/protocol/read/audit.d.ts +0 -25
  306. package/build/src/protocol/read/audit.js +0 -39
  307. package/build/src/verification/producer.d.ts +0 -23
  308. package/build/src/verification/producer.js +0 -54
@@ -1,5 +1,15 @@
1
- import type { AuditReport, ChangeId, ContractId, Fact, PlacementStop, ReconcileReport, RegionOverlap, SettlementReport, SnapshotId, VerificationStop } from "../index.js";
1
+ import type { AuditReport, ContractId, Fact, MutationResult, PlacementStop, ReconcileReport, Review, VerificationReuse, VerificationStop } from "../index.js";
2
2
  import type { KanshiReport } from "../kanshi/index.js";
3
+ import type { RegionRead, Section } from "../kanshi/index.js";
4
+ import type { Catalog } from "../index.js";
5
+ import type { RegionObservation } from "../library/region.js";
6
+ export type BindDraftReceipt = Readonly<{
7
+ path: string;
8
+ warning?: string;
9
+ } | {
10
+ path?: never;
11
+ warning: string;
12
+ }>;
3
13
  export type Effect = ReconcileReport["effects"][number];
4
14
  export type AcceptedFact = Readonly<{
5
15
  contract: ContractId;
@@ -7,34 +17,117 @@ export type AcceptedFact = Readonly<{
7
17
  kind: Fact["kind"];
8
18
  }>;
9
19
  export type Lag = ReconcileReport["lag"][number];
10
- export type DiffUnavailable = Readonly<{
11
- reason: "git-unavailable";
12
- snapshotId: SnapshotId;
13
- changeId: ChangeId;
14
- }>;
15
- export type AcceptedResult = Readonly<{
20
+ type MutationEnvelope = Pick<MutationResult<unknown>, "head" | "effects" | "settlement">;
21
+ export type AcceptedEnvelope = Readonly<{
16
22
  kind: "accepted";
17
- verb: string;
18
23
  contract: ContractId;
19
- head: string | null;
24
+ head: MutationEnvelope["head"];
20
25
  facts: readonly AcceptedFact[];
21
- effects: readonly Effect[];
22
- settlement: SettlementReport;
23
- target?: string | null;
26
+ effects: MutationEnvelope["effects"];
27
+ settlement: MutationEnvelope["settlement"];
28
+ lag?: readonly [Lag, ...Lag[]];
29
+ }>;
30
+ export type AcceptedBindResult = AcceptedEnvelope & Readonly<{
31
+ verb: "bind";
32
+ target: string | null;
33
+ verification?: never;
34
+ verificationReuse?: never;
35
+ placement?: never;
36
+ cleanup?: never;
37
+ leak?: never;
38
+ report?: never;
39
+ workspace?: never;
40
+ diff?: never;
41
+ }> & RegionObservation;
42
+ export type AcceptedAmendResult = AcceptedEnvelope & Readonly<{
43
+ verb: "amend";
44
+ diff: string;
45
+ target?: never;
46
+ verification?: never;
47
+ verificationReuse?: never;
48
+ placement?: never;
49
+ cleanup?: never;
50
+ leak?: never;
51
+ report?: never;
52
+ workspace?: never;
53
+ }> & RegionObservation;
54
+ export type AcceptedDeliverResult = AcceptedEnvelope & Readonly<{
55
+ verb: "deliver";
24
56
  verification?: VerificationStop;
57
+ verificationReuse?: VerificationReuse;
25
58
  placement?: PlacementStop;
26
- leak?: NonNullable<AuditReport["leak"]>;
27
- overlaps?: readonly RegionOverlap[];
28
- overlapFailure?: string;
29
- report?: AuditReport;
30
- diff?: string | DiffUnavailable;
31
- lag?: readonly Lag[];
59
+ cleanup?: MutationResult<unknown>["cleanup"];
60
+ leak?: MutationResult<unknown>["leak"];
61
+ target?: never;
62
+ overlaps?: never;
63
+ overlapFailure?: never;
64
+ report?: never;
65
+ workspace?: never;
66
+ diff?: never;
67
+ }>;
68
+ export type AcceptedReviewResult = AcceptedEnvelope & Readonly<{
69
+ verb: "review";
70
+ placement?: PlacementStop;
71
+ workspace?: Review["workspace"];
72
+ target?: never;
73
+ verification?: never;
74
+ verificationReuse?: never;
75
+ cleanup?: never;
76
+ leak?: never;
77
+ overlaps?: never;
78
+ overlapFailure?: never;
79
+ report?: never;
80
+ diff?: never;
81
+ }>;
82
+ export type AcceptedArcResult = AcceptedEnvelope & Readonly<{
83
+ verb: "arc";
84
+ target?: never;
85
+ verification?: never;
86
+ verificationReuse?: never;
87
+ placement?: never;
88
+ cleanup?: never;
89
+ leak?: never;
90
+ overlaps?: never;
91
+ overlapFailure?: never;
92
+ report?: never;
93
+ workspace?: never;
94
+ diff?: never;
32
95
  }>;
96
+ export type AcceptedAbandonResult = AcceptedEnvelope & Readonly<{
97
+ verb: "abandon";
98
+ target?: never;
99
+ verification?: never;
100
+ verificationReuse?: never;
101
+ placement?: never;
102
+ cleanup?: never;
103
+ leak?: never;
104
+ overlaps?: never;
105
+ overlapFailure?: never;
106
+ report?: never;
107
+ workspace?: never;
108
+ diff?: never;
109
+ }>;
110
+ export type AcceptedAuditResult = AcceptedEnvelope & Readonly<{
111
+ verb: "audit";
112
+ report: AuditReport;
113
+ cleanup?: MutationResult<unknown>["cleanup"];
114
+ leak?: MutationResult<unknown>["leak"];
115
+ target?: never;
116
+ verification?: never;
117
+ verificationReuse?: never;
118
+ placement?: never;
119
+ overlaps?: never;
120
+ overlapFailure?: never;
121
+ workspace?: never;
122
+ diff?: never;
123
+ }>;
124
+ export type AcceptedResult = AcceptedBindResult | AcceptedAmendResult | AcceptedDeliverResult | AcceptedReviewResult | AcceptedArcResult | AcceptedAbandonResult | AcceptedAuditResult;
33
125
  export type RefusedResult = Readonly<{
34
126
  kind: "refused";
35
127
  verb: string;
36
128
  contract?: ContractId;
37
129
  refusal: unknown;
130
+ draft?: BindDraftReceipt;
38
131
  }>;
39
132
  export type RetryResult = Readonly<{
40
133
  kind: "retry";
@@ -47,9 +140,23 @@ export type ObservationResult = Readonly<{
47
140
  command: string;
48
141
  [key: string]: unknown;
49
142
  }>;
143
+ export type GuidanceResult = Readonly<{
144
+ kind: "guidance";
145
+ contract: ContractId;
146
+ guidance: string;
147
+ }>;
50
148
  export type StatusResult = Readonly<{
51
149
  kind: "status";
52
150
  report: KanshiReport;
53
151
  selection: "world" | "contract";
54
152
  }>;
55
- export type InvocationResult = AcceptedResult | RefusedResult | RetryResult | ObservationResult | StatusResult;
153
+ export type RegionResult = Readonly<{
154
+ kind: "region";
155
+ region: Section<RegionRead>;
156
+ }>;
157
+ export type CatalogResult = Readonly<{
158
+ kind: "catalog";
159
+ catalog: Catalog;
160
+ }>;
161
+ export type InvocationResult = AcceptedResult | RefusedResult | RetryResult | ObservationResult | GuidanceResult | StatusResult | RegionResult | CatalogResult;
162
+ export {};
@@ -3,4 +3,5 @@ export declare class CliUsageError extends Error {
3
3
  readonly projection?: string | undefined;
4
4
  constructor(diagnostic: string, projection?: string | undefined);
5
5
  }
6
+ export declare function isBlankInput(value: string): boolean;
6
7
  export declare function usageLine(usage: string): string;
@@ -8,6 +8,9 @@ export class CliUsageError extends Error {
8
8
  this.name = "CliUsageError";
9
9
  }
10
10
  }
11
+ export function isBlankInput(value) {
12
+ return value.trim().length === 0;
13
+ }
11
14
  export function usageLine(usage) {
12
15
  return usage.split("\n").map((line, index) => {
13
16
  if (index === 0)
@@ -0,0 +1,44 @@
1
+ import { type DerivedFileAction } from "./coordination/durable-file.js";
2
+ import { type ContractId, type ContractState } from "./core/facts/types.js";
3
+ import { type GitRepository } from "./git/repository.js";
4
+ import { type PlaceRegister } from "./workspace-place.js";
5
+ export declare function renderContractGuidance(state: ContractState): string;
6
+ export type ContractFileEffect = Readonly<{
7
+ kind: "contract-file";
8
+ path: string;
9
+ action: DerivedFileAction | "removed";
10
+ }>;
11
+ export type ContractFileLag = Readonly<{
12
+ kind: "contract-file-failed";
13
+ worktree: string;
14
+ path: string;
15
+ diagnostic: string;
16
+ }>;
17
+ export type ContractWorktreeResult = Readonly<{
18
+ effects: readonly ContractFileEffect[];
19
+ lag: readonly ContractFileLag[];
20
+ }>;
21
+ export type ContractAppointment = Readonly<{
22
+ kind: "absent";
23
+ path: string;
24
+ }> | Readonly<{
25
+ kind: "appointed";
26
+ path: string;
27
+ contract: ContractId;
28
+ }> | Readonly<{
29
+ kind: "invalid";
30
+ path: string;
31
+ }>;
32
+ export declare function readContractAppointment(repository: GitRepository): Promise<ContractAppointment>;
33
+ export type ContractReservation = Readonly<{
34
+ kind: "reserved";
35
+ path: string;
36
+ }> | Exclude<ContractAppointment, Readonly<{
37
+ kind: "absent";
38
+ path: string;
39
+ }>>;
40
+ export declare function reserveContractWorktree(repository: GitRepository, contract: ContractId): Promise<ContractReservation>;
41
+ export declare function withContractWorktreeAppointment<T>(repository: GitRepository, action: () => T | Promise<T>): Promise<T>;
42
+ export declare function releaseContractWorktree(repository: GitRepository, contract: ContractId): Promise<void>;
43
+ export declare function removeContractWorktreeAppointment(repository: GitRepository, contract: ContractId): Promise<void>;
44
+ export declare function projectContractWorktree(repository: GitRepository, state: ContractState | null, register?: PlaceRegister): Promise<ContractWorktreeResult>;
@@ -0,0 +1,251 @@
1
+ import { chmod, lstat, readFile, unlink } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { acquireSqliteTransactionLock } from "./coordination/sqlite-transaction-lock.js";
4
+ import { createFileDurablyExclusive, repairDerivedFile, } from "./coordination/durable-file.js";
5
+ import { contractId } from "./core/facts/types.js";
6
+ import { GitPlumbingError, runGit, worktreeGitDirectory, worktreeRoot, } from "./git/repository.js";
7
+ import { worktreePath } from "./git/workspace.js";
8
+ import { appointmentFor, placeRegisterPath, readPlaceRegister, } from "./workspace-place.js";
9
+ const IGNORE_BYTES = ".gitignore\nKEIYAKU.md\n";
10
+ const APPOINTMENT_DESCRIPTION = "This is a read-only projection. Do not edit manually.";
11
+ function appointmentBytes(contract) {
12
+ return `---\ncontract: ${contract}\ndescription: ${APPOINTMENT_DESCRIPTION}\n---\n`;
13
+ }
14
+ function appointedContract(bytes) {
15
+ const lines = bytes.split(/\r?\n/u);
16
+ if (lines[0] !== "---")
17
+ return undefined;
18
+ const close = lines.indexOf("---", 1);
19
+ if (close !== 2 && close !== 3)
20
+ return undefined;
21
+ const identity = lines[1];
22
+ const description = lines[2];
23
+ if (identity === undefined || !identity.startsWith("contract: "))
24
+ return undefined;
25
+ if (close === 3 && (description === undefined || !description.startsWith("description: ")))
26
+ return undefined;
27
+ try {
28
+ return contractId(identity.slice("contract: ".length));
29
+ }
30
+ catch {
31
+ return undefined;
32
+ }
33
+ }
34
+ function renderArc(arc) {
35
+ return [
36
+ "## Arc", "", "### Sequence", "", String(arc.seq), "", "### Title", "", arc.title.trimEnd(), "",
37
+ "### Objective", "", arc.objective.trimEnd(), "", "### Brief", "", arc.brief.trimEnd(),
38
+ ].join("\n");
39
+ }
40
+ const FULFILLMENT = [
41
+ "## Fulfillment", "", "### Appointment", "",
42
+ "Each commission names exactly one seat: Deliverer or Reviewer.",
43
+ "If no seat was named, stop and ask the caller. Never infer it.", "",
44
+ "### Worktree", "",
45
+ "This file is a derived view of the journal-authoritative Contract. Never edit it to change the Contract.",
46
+ "Treat the directory containing `.keiyaku/KEIYAKU.md` as the Contract worktree root.",
47
+ "Read the complete Contract before acting and keep work inside that worktree.", "",
48
+ "### Deliverer", "",
49
+ "Implement and verify the Objective under the Design, Region, and Criteria in this Contract.",
50
+ "When an Arc is active, stay within that current chapter.",
51
+ "Leave lifecycle decisions to the caller; report the candidate, verification performed, and any unmet term.", "",
52
+ "### Reviewer", "",
53
+ "Review this Contract worktree against the complete Contract.",
54
+ "Review the complete current worktree snapshot, not a named candidate commit.",
55
+ "Do not modify it; report covered Criteria, findings, and missing evidence.",
56
+ ].join("\n");
57
+ export function renderContractGuidance(state) {
58
+ return [
59
+ appointmentBytes(state.id).trimEnd(),
60
+ state.terms.document.bytes.trimEnd(),
61
+ ...(state.currentArc === undefined ? [] : [renderArc(state.currentArc.data)]),
62
+ FULFILLMENT,
63
+ ].join("\n\n").concat("\n");
64
+ }
65
+ async function isTracked(repository, relativePath) {
66
+ try {
67
+ await runGit(repository, ["ls-files", "--error-unmatch", "--", relativePath]);
68
+ return true;
69
+ }
70
+ catch (error) {
71
+ if (error instanceof GitPlumbingError && error.status === 1)
72
+ return false;
73
+ throw error;
74
+ }
75
+ }
76
+ function generatedPath(worktree, name) {
77
+ return join(worktree, ".keiyaku", name);
78
+ }
79
+ export async function readContractAppointment(repository) {
80
+ const path = generatedPath(await worktreeRoot(repository), "KEIYAKU.md");
81
+ const stat = await lstat(path).catch((error) => {
82
+ if (error.code === "ENOENT")
83
+ return undefined;
84
+ throw error;
85
+ });
86
+ if (stat === undefined)
87
+ return { kind: "absent", path };
88
+ if (!stat.isFile() || stat.isSymbolicLink())
89
+ return { kind: "invalid", path };
90
+ const contract = appointedContract(await readFile(path, "utf8"));
91
+ return contract === undefined ? { kind: "invalid", path } : { kind: "appointed", path, contract };
92
+ }
93
+ export async function reserveContractWorktree(repository, contract) {
94
+ const worktree = await worktreeRoot(repository);
95
+ const scoped = { ...repository, effectiveCwd: worktree };
96
+ const ignore = generatedPath(worktree, ".gitignore");
97
+ if (await isTracked(scoped, ".keiyaku/.gitignore"))
98
+ throw new Error(`generated path is tracked by Git: ${ignore}`);
99
+ await repairDerivedFile(ignore, IGNORE_BYTES);
100
+ const path = generatedPath(worktree, "KEIYAKU.md");
101
+ if (await isTracked(scoped, ".keiyaku/KEIYAKU.md"))
102
+ throw new Error(`generated path is tracked by Git: ${path}`);
103
+ if (await createFileDurablyExclusive(path, appointmentBytes(contract), 0o444))
104
+ return { kind: "reserved", path };
105
+ const appointment = await readContractAppointment(repository);
106
+ return appointment.kind === "absent" ? { kind: "invalid", path } : appointment;
107
+ }
108
+ export async function withContractWorktreeAppointment(repository, action) {
109
+ const root = await worktreeRoot(repository);
110
+ const lock = await acquireSqliteTransactionLock({
111
+ path: join(await worktreeGitDirectory(repository, root), "keiyaku", "contract-worktree.sqlite"),
112
+ mode: "immediate",
113
+ });
114
+ try {
115
+ return await action();
116
+ }
117
+ finally {
118
+ lock.close();
119
+ }
120
+ }
121
+ export async function releaseContractWorktree(repository, contract) {
122
+ const appointment = await readContractAppointment(repository);
123
+ if (appointment.kind !== "appointed" || appointment.contract !== contract)
124
+ return;
125
+ if (await readFile(appointment.path, "utf8") !== appointmentBytes(contract))
126
+ return;
127
+ try {
128
+ await unlink(appointment.path);
129
+ }
130
+ catch { /* reservation cleanup is best effort */ }
131
+ }
132
+ export async function removeContractWorktreeAppointment(repository, contract) {
133
+ const appointment = await readContractAppointment(repository);
134
+ if (appointment.kind !== "appointed" || appointment.contract !== contract)
135
+ return;
136
+ await unlink(appointment.path);
137
+ }
138
+ async function repair(repository, worktree, relativePath, bytes) {
139
+ const path = join(worktree, relativePath);
140
+ if (await isTracked(repository, relativePath))
141
+ throw new Error(`generated path is tracked by Git: ${path}`);
142
+ const action = await repairDerivedFile(path, bytes);
143
+ if (relativePath === ".keiyaku/KEIYAKU.md") {
144
+ try {
145
+ await chmod(path, 0o444);
146
+ }
147
+ catch { /* advisory protection only */ }
148
+ }
149
+ return { kind: "contract-file", path, action };
150
+ }
151
+ async function materialize(repository, worktree, guidance) {
152
+ const stat = await lstat(worktree).catch((error) => {
153
+ if (error.code === "ENOENT")
154
+ return undefined;
155
+ throw error;
156
+ });
157
+ if (stat === undefined || !stat.isDirectory()) {
158
+ return {
159
+ effects: [],
160
+ lag: [{
161
+ kind: "contract-file-failed",
162
+ worktree,
163
+ path: generatedPath(worktree, "KEIYAKU.md"),
164
+ diagnostic: "Contract worktree is unavailable",
165
+ }],
166
+ };
167
+ }
168
+ const scoped = { ...repository, effectiveCwd: worktree };
169
+ const effects = [];
170
+ for (const [relativePath, bytes] of [
171
+ [".keiyaku/.gitignore", IGNORE_BYTES],
172
+ [".keiyaku/KEIYAKU.md", guidance],
173
+ ]) {
174
+ try {
175
+ effects.push(await repair(scoped, worktree, relativePath, bytes));
176
+ }
177
+ catch (error) {
178
+ return {
179
+ effects,
180
+ lag: [{
181
+ kind: "contract-file-failed",
182
+ worktree,
183
+ path: join(worktree, relativePath),
184
+ diagnostic: error instanceof Error ? error.message : String(error),
185
+ }],
186
+ };
187
+ }
188
+ }
189
+ return { effects, lag: [] };
190
+ }
191
+ async function here(repository, state, guidance) {
192
+ const worktree = await worktreeRoot(repository);
193
+ const appointment = await readContractAppointment(repository);
194
+ if (appointment.kind === "appointed" && appointment.contract === state.id) {
195
+ return await materialize(repository, worktree, guidance);
196
+ }
197
+ const diagnostic = appointment.kind === "appointed"
198
+ ? `here worktree is appointed to ${appointment.contract}`
199
+ : `here Contract appointment is ${appointment.kind}`;
200
+ return {
201
+ effects: [],
202
+ lag: [{ kind: "contract-file-failed", worktree, path: appointment.path, diagnostic }],
203
+ };
204
+ }
205
+ async function removeHere(repository, contract) {
206
+ const worktree = await worktreeRoot(repository);
207
+ const appointment = await readContractAppointment(repository);
208
+ if (appointment.kind === "absent" || (appointment.kind === "appointed" && appointment.contract !== contract)) {
209
+ return { effects: [], lag: [] };
210
+ }
211
+ if (appointment.kind === "invalid") {
212
+ return { effects: [], lag: [{
213
+ kind: "contract-file-failed", worktree, path: appointment.path, diagnostic: "here Contract appointment is invalid",
214
+ }] };
215
+ }
216
+ try {
217
+ await unlink(appointment.path);
218
+ return { effects: [{ kind: "contract-file", path: appointment.path, action: "removed" }], lag: [] };
219
+ }
220
+ catch (error) {
221
+ return { effects: [], lag: [{
222
+ kind: "contract-file-failed",
223
+ worktree,
224
+ path: appointment.path,
225
+ diagnostic: error instanceof Error ? error.message : String(error),
226
+ }] };
227
+ }
228
+ }
229
+ export async function projectContractWorktree(repository, state, register) {
230
+ if (state === null || state.terminal) {
231
+ return state?.coordinates.workspace === "here"
232
+ ? await removeHere(repository, state.id)
233
+ : { effects: [], lag: [] };
234
+ }
235
+ if (state.coordinates.workspace === "here") {
236
+ return await here(repository, state, renderContractGuidance(state));
237
+ }
238
+ const appointed = appointmentFor(register ?? await readPlaceRegister(repository), state.id);
239
+ if (appointed === undefined) {
240
+ return {
241
+ effects: [],
242
+ lag: [{
243
+ kind: "contract-file-failed",
244
+ worktree: repository.primaryWorktree,
245
+ path: placeRegisterPath(repository),
246
+ diagnostic: "managed Contract is unappointed",
247
+ }],
248
+ };
249
+ }
250
+ return await materialize(repository, worktreePath(repository, appointed.place), renderContractGuidance(state));
251
+ }
@@ -1 +1,5 @@
1
- export declare function replaceFileDurably(path: string, bytes: string | Uint8Array): void;
1
+ export declare function syncDirectory(path: string): void;
2
+ export declare function replaceFileDurably(path: string, bytes: string | Uint8Array): Promise<void>;
3
+ export type DerivedFileAction = "created" | "updated" | "unchanged";
4
+ export declare function createFileDurablyExclusive(path: string, bytes: string | Uint8Array, mode?: number): Promise<boolean>;
5
+ export declare function repairDerivedFile(path: string, bytes: string | Uint8Array): Promise<DerivedFileAction>;
@@ -1,7 +1,19 @@
1
1
  import { randomBytes } from "node:crypto";
2
- import { closeSync, fsyncSync, openSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { closeSync, fsyncSync, openSync, renameSync, writeFileSync, } from "node:fs";
3
+ import { lstat, mkdir, readFile, unlink } from "node:fs/promises";
3
4
  import { dirname, resolve } from "node:path";
4
- export function replaceFileDurably(path, bytes) {
5
+ export function syncDirectory(path) {
6
+ if (process.platform === "win32")
7
+ return;
8
+ const directory = openSync(path, "r");
9
+ try {
10
+ fsyncSync(directory);
11
+ }
12
+ finally {
13
+ closeSync(directory);
14
+ }
15
+ }
16
+ export async function replaceFileDurably(path, bytes) {
5
17
  const parent = dirname(path);
6
18
  for (;;) {
7
19
  const temporary = resolve(parent, `.tmp-${randomBytes(8).toString("hex")}`);
@@ -13,20 +25,14 @@ export function replaceFileDurably(path, bytes) {
13
25
  closeSync(descriptor);
14
26
  descriptor = undefined;
15
27
  renameSync(temporary, path);
16
- const directory = openSync(parent, "r");
17
- try {
18
- fsyncSync(directory);
19
- }
20
- finally {
21
- closeSync(directory);
22
- }
28
+ syncDirectory(parent);
23
29
  return;
24
30
  }
25
31
  catch (error) {
26
32
  if (descriptor !== undefined)
27
33
  closeSync(descriptor);
28
34
  try {
29
- unlinkSync(temporary);
35
+ await unlink(temporary);
30
36
  }
31
37
  catch { /* renamed, absent, or best-effort cleanup */ }
32
38
  if (error.code !== "EEXIST")
@@ -34,3 +40,44 @@ export function replaceFileDurably(path, bytes) {
34
40
  }
35
41
  }
36
42
  }
43
+ export async function createFileDurablyExclusive(path, bytes, mode = 0o600) {
44
+ const parent = dirname(path);
45
+ await mkdir(parent, { recursive: true });
46
+ let descriptor;
47
+ try {
48
+ descriptor = openSync(path, "wx", mode);
49
+ writeFileSync(descriptor, bytes);
50
+ fsyncSync(descriptor);
51
+ closeSync(descriptor);
52
+ descriptor = undefined;
53
+ syncDirectory(parent);
54
+ return true;
55
+ }
56
+ catch (error) {
57
+ if (descriptor !== undefined)
58
+ closeSync(descriptor);
59
+ if (error.code === "EEXIST")
60
+ return false;
61
+ try {
62
+ await unlink(path);
63
+ }
64
+ catch { /* absent or best-effort cleanup */ }
65
+ throw error;
66
+ }
67
+ }
68
+ export async function repairDerivedFile(path, bytes) {
69
+ const expected = Buffer.from(bytes);
70
+ await mkdir(dirname(path), { recursive: true });
71
+ const stat = await lstat(path).catch((error) => {
72
+ if (error.code === "ENOENT")
73
+ return undefined;
74
+ throw error;
75
+ });
76
+ if (stat !== undefined && (!stat.isFile() || stat.isSymbolicLink())) {
77
+ throw new Error(`derived file is not a regular file: ${path}`);
78
+ }
79
+ if (stat !== undefined && (await readFile(path)).equals(expected))
80
+ return "unchanged";
81
+ await replaceFileDurably(path, expected);
82
+ return stat === undefined ? "created" : "updated";
83
+ }
@@ -12,3 +12,7 @@ export declare function acquireSqliteTransactionLock(input: {
12
12
  timeoutMs?: number;
13
13
  signal?: AbortSignal;
14
14
  }): Promise<HeldSqliteTransactionLock>;
15
+ export declare function tryAcquireSqliteTransactionLock(input: {
16
+ path: string;
17
+ mode: SqliteTransactionLockMode;
18
+ }): Promise<HeldSqliteTransactionLock | null>;
@@ -1,5 +1,5 @@
1
1
  import { randomInt } from "node:crypto";
2
- import { lstatSync, mkdirSync } from "node:fs";
2
+ import { lstat, mkdir } from "node:fs/promises";
3
3
  import { dirname } from "node:path";
4
4
  import { DatabaseSync } from "node:sqlite";
5
5
  const SQLITE_BUSY = 5;
@@ -41,13 +41,17 @@ function closeDatabase(database) {
41
41
  }
42
42
  return failure;
43
43
  }
44
- function openLock(path, mode) {
44
+ async function openLock(path, mode) {
45
45
  try {
46
- const stat = lstatSync(path, { throwIfNoEntry: false });
46
+ const stat = await lstat(path).catch((error) => {
47
+ if (error.code === "ENOENT")
48
+ return undefined;
49
+ throw error;
50
+ });
47
51
  if (stat && (!stat.isFile() || stat.isSymbolicLink())) {
48
52
  throw new SqliteTransactionLockError(`SQLite lock is not a regular file: ${path}`, "invalid");
49
53
  }
50
- mkdirSync(dirname(path), { recursive: true });
54
+ await mkdir(dirname(path), { recursive: true });
51
55
  }
52
56
  catch (error) {
53
57
  if (error instanceof SqliteTransactionLockError)
@@ -101,7 +105,7 @@ export async function acquireSqliteTransactionLock(input) {
101
105
  for (;;) {
102
106
  input.signal?.throwIfAborted();
103
107
  try {
104
- return openLock(input.path, input.mode);
108
+ return await openLock(input.path, input.mode);
105
109
  }
106
110
  catch (error) {
107
111
  if (!isBusy(error))
@@ -117,3 +121,16 @@ export async function acquireSqliteTransactionLock(input) {
117
121
  }
118
122
  }
119
123
  }
124
+ export async function tryAcquireSqliteTransactionLock(input) {
125
+ if (input.path.length === 0) {
126
+ throw new SqliteTransactionLockError("SQLite lock path must be valid", "invalid");
127
+ }
128
+ try {
129
+ return await openLock(input.path, input.mode);
130
+ }
131
+ catch (error) {
132
+ if (isBusy(error))
133
+ return null;
134
+ throw error;
135
+ }
136
+ }