@astrosheep/keiyaku 4.6.4 → 4.6.6

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 (191) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +43 -8
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +7 -8
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
  4. package/build/src/akuma/akuma-observe.d.ts +18 -15
  5. package/build/src/akuma/akuma-observe.js +75 -16
  6. package/build/src/akuma/akuma-wait.d.ts +4 -3
  7. package/build/src/akuma/akuma-wait.js +75 -53
  8. package/build/src/akuma/akuma.d.ts +6 -4
  9. package/build/src/akuma/akuma.js +4 -0
  10. package/build/src/akuma/call-initial-tell.d.ts +2 -2
  11. package/build/src/akuma/call-initial-tell.js +1 -1
  12. package/build/src/akuma/call-request.d.ts +2 -2
  13. package/build/src/akuma/heart/index.d.ts +7 -2
  14. package/build/src/akuma/heart/index.js +50 -5
  15. package/build/src/akuma/heart/tells.d.ts +33 -2
  16. package/build/src/akuma/heart/tells.js +24 -18
  17. package/build/src/akuma/heart/timeline.d.ts +23 -1
  18. package/build/src/akuma/heart/timeline.js +28 -21
  19. package/build/src/akuma/projection.d.ts +10 -10
  20. package/build/src/akuma/providers/pi/index.js +72 -39
  21. package/build/src/akuma/selection-observation.d.ts +20 -20
  22. package/build/src/akuma-body.js +1 -0
  23. package/build/src/alias/index.d.ts +0 -1
  24. package/build/src/alias/index.js +0 -4
  25. package/build/src/body/amend.d.ts +0 -4
  26. package/build/src/body/amend.js +0 -3
  27. package/build/src/body/region.d.ts +0 -1
  28. package/build/src/body/region.js +0 -3
  29. package/build/src/body/verification.d.ts +0 -1
  30. package/build/src/cli/commands/akuma-grammar.js +23 -66
  31. package/build/src/cli/commands/akuma.js +17 -30
  32. package/build/src/cli/commands/contract-grammar.d.ts +14 -1
  33. package/build/src/cli/commands/contract-grammar.js +54 -21
  34. package/build/src/cli/commands/contract-help.d.ts +9 -8
  35. package/build/src/cli/commands/contract-help.js +14 -7
  36. package/build/src/cli/commands/contract.js +57 -117
  37. package/build/src/cli/commands/install.d.ts +5 -5
  38. package/build/src/cli/commands/install.js +1 -4
  39. package/build/src/cli/commands/task-grammar.js +10 -66
  40. package/build/src/cli/commands/task.d.ts +0 -1
  41. package/build/src/cli/commands/task.js +34 -53
  42. package/build/src/cli/coordinates.d.ts +1 -2
  43. package/build/src/cli/coordinates.js +1 -4
  44. package/build/src/cli/parse.d.ts +2 -3
  45. package/build/src/cli/parse.js +24 -66
  46. package/build/src/cli/render/akuma.d.ts +3 -16
  47. package/build/src/cli/render/akuma.js +1 -13
  48. package/build/src/cli/render/audit.js +1 -1
  49. package/build/src/cli/render/contract.js +34 -32
  50. package/build/src/cli/render/kanshi-akuma.d.ts +8 -2
  51. package/build/src/cli/render/kanshi-akuma.js +14 -7
  52. package/build/src/cli/render/kanshi.d.ts +3 -1
  53. package/build/src/cli/render/kanshi.js +44 -32
  54. package/build/src/cli/render/receipt.js +6 -1
  55. package/build/src/cli/render/task.d.ts +1 -1
  56. package/build/src/cli/render/task.js +3 -27
  57. package/build/src/cli/render/terminal.d.ts +6 -2
  58. package/build/src/cli/render/terminal.js +8 -2
  59. package/build/src/cli/runtime.js +3 -16
  60. package/build/src/cli/scan.d.ts +26 -0
  61. package/build/src/cli/scan.js +82 -0
  62. package/build/src/cli/streams.d.ts +5 -0
  63. package/build/src/cli/streams.js +11 -0
  64. package/build/src/contract-worktree.js +38 -21
  65. package/build/src/core/facts/codec.d.ts +1 -2
  66. package/build/src/core/facts/codec.js +5 -11
  67. package/build/src/core/facts/types.d.ts +16 -2
  68. package/build/src/core/facts/types.js +15 -0
  69. package/build/src/core/verbs/abandon.js +3 -9
  70. package/build/src/core/verbs/amend.js +2 -9
  71. package/build/src/core/verbs/arc.js +6 -13
  72. package/build/src/core/verbs/attestation.js +2 -9
  73. package/build/src/core/verbs/bind.js +2 -9
  74. package/build/src/core/verbs/deliver.js +2 -9
  75. package/build/src/core/verbs/placement.d.ts +1 -1
  76. package/build/src/core/verbs/placement.js +2 -9
  77. package/build/src/core/verbs/reintegrate.d.ts +1 -1
  78. package/build/src/core/verbs/reintegrate.js +2 -9
  79. package/build/src/dispatch/index.d.ts +2 -2
  80. package/build/src/dispatch/index.js +33 -11
  81. package/build/src/git/hooks.d.ts +2 -4
  82. package/build/src/git/hooks.js +0 -12
  83. package/build/src/git/integration.d.ts +5 -3
  84. package/build/src/git/integration.js +36 -25
  85. package/build/src/git/nuke.js +4 -4
  86. package/build/src/git/observe.d.ts +4 -4
  87. package/build/src/git/observe.js +5 -5
  88. package/build/src/git/process.d.ts +1 -4
  89. package/build/src/git/process.js +1 -11
  90. package/build/src/git/read-observation.js +1 -1
  91. package/build/src/git/reconcile.d.ts +1 -1
  92. package/build/src/git/reconcile.js +15 -13
  93. package/build/src/git/repository.d.ts +2 -6
  94. package/build/src/git/repository.js +18 -31
  95. package/build/src/git/scratch.d.ts +6 -6
  96. package/build/src/git/scratch.js +110 -46
  97. package/build/src/git/target-placement.d.ts +5 -5
  98. package/build/src/git/target-placement.js +18 -33
  99. package/build/src/git/tender.d.ts +6 -2
  100. package/build/src/git/tender.js +19 -12
  101. package/build/src/git/terminal-reconcile.js +24 -13
  102. package/build/src/git/terminal-seal.d.ts +2 -5
  103. package/build/src/git/terminal-seal.js +5 -3
  104. package/build/src/git/workspace.d.ts +17 -13
  105. package/build/src/git/workspace.js +58 -41
  106. package/build/src/kanshi/index.d.ts +2 -2
  107. package/build/src/kanshi/index.js +1 -1
  108. package/build/src/kanshi/read.d.ts +8 -1
  109. package/build/src/kanshi/read.js +72 -7
  110. package/build/src/kanshi/report.d.ts +12 -0
  111. package/build/src/library/akuma-creation.d.ts +4 -4
  112. package/build/src/library/bind.d.ts +1 -63
  113. package/build/src/library/bind.js +3 -9
  114. package/build/src/library/contract-creation.js +2 -30
  115. package/build/src/library/contract-execution.d.ts +0 -1
  116. package/build/src/library/contract-execution.js +9 -34
  117. package/build/src/library/contract-operations.d.ts +5 -1
  118. package/build/src/library/contract-operations.js +7 -3
  119. package/build/src/library/contract-types.d.ts +1 -1
  120. package/build/src/library/delivery.d.ts +91 -93
  121. package/build/src/library/delivery.js +2 -1
  122. package/build/src/library/input.d.ts +0 -2
  123. package/build/src/library/input.js +0 -4
  124. package/build/src/library/invocation.d.ts +0 -1
  125. package/build/src/library/invocation.js +3 -25
  126. package/build/src/library/outcome.d.ts +651 -602
  127. package/build/src/library/outcome.js +4 -4
  128. package/build/src/library/reconcile.d.ts +6 -0
  129. package/build/src/library/reconcile.js +31 -1
  130. package/build/src/library/repo.d.ts +0 -1
  131. package/build/src/library/selection.d.ts +1 -10
  132. package/build/src/library/selection.js +14 -15
  133. package/build/src/protocol/abandon.d.ts +1 -1
  134. package/build/src/protocol/abandon.js +3 -10
  135. package/build/src/protocol/amend.js +2 -5
  136. package/build/src/protocol/arc.d.ts +1 -1
  137. package/build/src/protocol/arc.js +2 -9
  138. package/build/src/protocol/attempt.d.ts +3 -20
  139. package/build/src/protocol/attempt.js +6 -5
  140. package/build/src/protocol/audit.d.ts +1 -0
  141. package/build/src/protocol/audit.js +10 -11
  142. package/build/src/protocol/completion.d.ts +129 -55
  143. package/build/src/protocol/completion.js +62 -73
  144. package/build/src/protocol/deliver.d.ts +7 -5
  145. package/build/src/protocol/deliver.js +74 -44
  146. package/build/src/protocol/execution-observation.d.ts +2 -4
  147. package/build/src/protocol/execution-observation.js +3 -7
  148. package/build/src/protocol/intent.d.ts +1 -1
  149. package/build/src/protocol/intent.js +1 -0
  150. package/build/src/protocol/operations.d.ts +24 -12
  151. package/build/src/protocol/operations.js +36 -15
  152. package/build/src/protocol/placement.d.ts +2 -1
  153. package/build/src/protocol/placement.js +21 -5
  154. package/build/src/protocol/progress.d.ts +1 -1
  155. package/build/src/protocol/read/status.js +58 -41
  156. package/build/src/protocol/reintegrate.d.ts +1 -1
  157. package/build/src/protocol/reintegrate.js +10 -19
  158. package/build/src/protocol/review.d.ts +3 -28
  159. package/build/src/protocol/review.js +10 -37
  160. package/build/src/protocol/run.d.ts +19 -7
  161. package/build/src/protocol/run.js +19 -9
  162. package/build/src/runtime/proc/windows-launch.exe +0 -0
  163. package/build/src/settlement/holder.d.ts +2 -4
  164. package/build/src/settlement/holder.js +3 -6
  165. package/build/src/task/board.d.ts +6 -0
  166. package/build/src/task/board.js +30 -1
  167. package/build/src/task/catalog.js +1 -4
  168. package/build/src/task/compose.d.ts +0 -1
  169. package/build/src/task/compose.js +0 -1
  170. package/build/src/task/context.d.ts +0 -1
  171. package/build/src/task/context.js +0 -3
  172. package/build/src/task/created-observation.d.ts +5 -1
  173. package/build/src/task/created-observation.js +12 -5
  174. package/build/src/task/index.d.ts +1 -1
  175. package/build/src/task/index.js +7 -6
  176. package/build/src/task/input.d.ts +0 -6
  177. package/build/src/task/input.js +2 -14
  178. package/build/src/task/mutation.d.ts +3 -4
  179. package/build/src/task/mutation.js +11 -39
  180. package/build/src/task/operations.d.ts +2 -7
  181. package/build/src/task/operations.js +37 -49
  182. package/build/src/task/query.d.ts +0 -1
  183. package/build/src/task/query.js +1 -4
  184. package/build/src/task/store.d.ts +0 -2
  185. package/build/src/task/store.js +27 -11
  186. package/build/src/verification/declaration.js +3 -2
  187. package/build/src/verification/execution.d.ts +3 -2
  188. package/build/src/verification/execution.js +10 -6
  189. package/build/src/workspace-place.d.ts +0 -1
  190. package/build/src/workspace-place.js +0 -11
  191. package/package.json +7 -3
@@ -2,8 +2,9 @@ import { z } from "zod";
2
2
  import type { ContractId, SnapshotId } from "../core/facts/types.js";
3
3
  import { type GitObjectId } from "./identity.js";
4
4
  import { type GitRepository } from "./process.js";
5
+ import type { GitReadObservation } from "./read-observation.js";
5
6
  import type { ContractWorkspaceLocation } from "../workspace-place.js";
6
- export type WorkspaceChanges = Readonly<{
7
+ type WorkspaceChanges = Readonly<{
7
8
  staged: readonly string[];
8
9
  unstaged: readonly string[];
9
10
  untracked: readonly string[];
@@ -19,7 +20,7 @@ export type WorkspaceTree = Readonly<{
19
20
  export declare function worktreePath(repository: GitRepository, place: string): string;
20
21
  /** Check out a captured candidate tree in the appointed detached worktree. */
21
22
  export declare function checkoutDetachedSnapshot(repository: GitRepository, workspace: string, snapshot: SnapshotId): Promise<void>;
22
- export type DependentWorktreeFollow = Readonly<{
23
+ type DependentWorktreeFollow = Readonly<{
23
24
  kind: "followed";
24
25
  before: SnapshotId;
25
26
  after: SnapshotId;
@@ -42,7 +43,7 @@ export declare function workspaceMergeHead(repository: GitRepository, workspace:
42
43
  export declare function workspaceMergeStatePresent(repository: GitRepository, workspace: string): Promise<boolean>;
43
44
  /** Sorted unique unmerged index paths from porcelain status. */
44
45
  export declare function unmergedWorkspacePaths(repository: GitRepository, workspace: string): Promise<readonly string[]>;
45
- export type WorkspaceChangeCounts = Readonly<{
46
+ type WorkspaceChangeCounts = Readonly<{
46
47
  staged: number;
47
48
  unstaged: number;
48
49
  untracked: number;
@@ -55,7 +56,7 @@ export declare const conflictRecoverySchema: z.ZodObject<{
55
56
  }, z.core.$strict>;
56
57
  type ConflictRecovery = z.infer<typeof conflictRecoverySchema>;
57
58
  export declare const conflictRecovery: ConflictRecovery;
58
- export type ContractWorkspaceMerge = Readonly<{
59
+ type ContractWorkspaceMerge = Readonly<{
59
60
  head: SnapshotId;
60
61
  unmergedPaths: readonly string[];
61
62
  handoffBase?: SnapshotId;
@@ -100,7 +101,16 @@ export declare function observeWorkspace(repository: GitRepository, location: Co
100
101
  export declare function observeTargetLag(repository: GitRepository, workspace: string, head: SnapshotId | null | undefined): Promise<ContractTargetLag>;
101
102
  /** Capture tracked and untracked workspace bytes without changing its real index. */
102
103
  export declare function captureWorkspaceTree(repository: GitRepository, workspace: string): Promise<WorkspaceTree>;
103
- export type HandoffRetirement = Readonly<{
104
+ export type HandoffReceiptCoordinate = Readonly<{
105
+ contractId: ContractId;
106
+ place: string;
107
+ workspace: string;
108
+ }>;
109
+ export type ConflictHandoff = Readonly<{
110
+ base: SnapshotId;
111
+ mergeHead: SnapshotId;
112
+ }>;
113
+ type HandoffRetirement = Readonly<{
104
114
  kind: "absent" | "active" | "orphan-retired" | "retired";
105
115
  }> | Readonly<{
106
116
  kind: "retained";
@@ -113,14 +123,8 @@ export declare function recordConflictHandoff(repository: GitRepository, input:
113
123
  head: SnapshotId;
114
124
  mergeHead: SnapshotId;
115
125
  }>): Promise<void>;
116
- export declare function conflictHandoffFor(repository: GitRepository, input: Readonly<{
117
- contractId: ContractId;
118
- place: string;
119
- workspace: string;
120
- }>): Promise<Readonly<{
121
- base: SnapshotId;
122
- mergeHead: SnapshotId;
123
- }> | undefined>;
126
+ /** Read selected handoff refs once and decode their receipts through the call's blob channel. */
127
+ export declare function readConflictHandoffs(repository: GitRepository, readBlobs: GitReadObservation["readBlobs"], coordinates: readonly HandoffReceiptCoordinate[]): Promise<ReadonlyMap<ContractId, ConflictHandoff>>;
124
128
  export declare function retireConflictHandoff(repository: GitRepository, input: Readonly<{
125
129
  contractId: ContractId;
126
130
  place: string;
@@ -2,20 +2,21 @@ import { z } from "zod";
2
2
  import { access, mkdtemp, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join, resolve } from "node:path";
5
+ import { AuthorityCorruptionError } from "../core/facts/errors.js";
5
6
  import { contractPhysicalName, gitObjectId, mintSnapshotId } from "./identity.js";
6
- import { GitPlumbingError, runGit, runGitWithEnvironment } from "./process.js";
7
- import { HANDOFF_RECEIPT_REF_NAMESPACE, readBlob, readRef, worktreeGitDirectory, writeBlob } from "./repository.js";
7
+ import { executeGit, GitPlumbingError } from "./process.js";
8
+ import { HANDOFF_RECEIPT_REF_NAMESPACE, readBlob, readRef, readRefs, worktreeGitDirectory, writeBlob, } from "./repository.js";
8
9
  const WORKTREE_DIRECTORY = [".keiyaku", "wt"];
9
10
  export function worktreePath(repository, place) {
10
11
  return resolve(repository.primaryWorktree, ...WORKTREE_DIRECTORY, place);
11
12
  }
12
13
  /** Check out a captured candidate tree in the appointed detached worktree. */
13
14
  export async function checkoutDetachedSnapshot(repository, workspace, snapshot) {
14
- await runGit(repository, ["-C", workspace, "checkout", "--quiet", "--force", "--detach", gitObjectId(snapshot)]);
15
+ await executeGit(repository, ["-C", workspace, "checkout", "--quiet", "--force", "--detach", gitObjectId(snapshot)]);
15
16
  }
16
17
  async function workspaceRevision(repository, workspace, revision) {
17
18
  try {
18
- const value = (await runGit(repository, ["-C", workspace, "rev-parse", "--verify", "--quiet", revision]))
19
+ const value = (await executeGit(repository, ["-C", workspace, "rev-parse", "--verify", "--quiet", revision]))
19
20
  .toString("utf8")
20
21
  .trim();
21
22
  return value.length === 0 ? null : mintSnapshotId(value);
@@ -37,7 +38,7 @@ async function workspaceOperationState(repository, workspace, gitDirectory) {
37
38
  return false;
38
39
  }
39
40
  }));
40
- const unmerged = (await runGit(repository, ["-C", workspace, "ls-files", "--unmerged", "-z"])).length > 0;
41
+ const unmerged = (await executeGit(repository, ["-C", workspace, "ls-files", "--unmerged", "-z"])).length > 0;
41
42
  return { other: other.some(Boolean), unmerged };
42
43
  }
43
44
  /** Follow a dependency baseline only through a clean, detached fast-forward. */
@@ -58,7 +59,7 @@ export async function followDependentManagedWorktree(repository, workspace, targ
58
59
  ...status.unmergedPaths,
59
60
  ]),
60
61
  ].sort();
61
- const attached = await runGit(repository, ["-C", workspace, "symbolic-ref", "--quiet", "HEAD"]).then(() => true, (error) => {
62
+ const attached = await executeGit(repository, ["-C", workspace, "symbolic-ref", "--quiet", "HEAD"]).then(() => true, (error) => {
62
63
  if (error instanceof GitPlumbingError && error.status === 1)
63
64
  return false;
64
65
  throw error;
@@ -72,7 +73,7 @@ export async function followDependentManagedWorktree(repository, workspace, targ
72
73
  return { kind: "unchanged" };
73
74
  let ancestor = false;
74
75
  try {
75
- await runGit(repository, ["merge-base", "--is-ancestor", gitObjectId(head), gitObjectId(target)]);
76
+ await executeGit(repository, ["merge-base", "--is-ancestor", gitObjectId(head), gitObjectId(target)]);
76
77
  ancestor = true;
77
78
  }
78
79
  catch (error) {
@@ -81,17 +82,26 @@ export async function followDependentManagedWorktree(repository, workspace, targ
81
82
  }
82
83
  if (!ancestor)
83
84
  return { kind: "retained", head, reason: "head-moved", paths };
84
- await runGit(repository, ["-C", workspace, "checkout", "--quiet", "--detach", gitObjectId(target)]);
85
+ await executeGit(repository, ["-C", workspace, "checkout", "--quiet", "--detach", gitObjectId(target)]);
85
86
  return { kind: "followed", before: head, after: target };
86
87
  }
87
88
  export async function withPrivateGitIndex(action) {
88
89
  const directory = await mkdtemp(join(tmpdir(), "keiyaku-v4-index-"));
90
+ let value;
89
91
  try {
90
- return await action({ GIT_INDEX_FILE: join(directory, "index") });
92
+ value = await action({ GIT_INDEX_FILE: join(directory, "index") });
91
93
  }
92
- finally {
93
- await rm(directory, { recursive: true, force: true });
94
+ catch (error) {
95
+ try {
96
+ await rm(directory, { recursive: true, force: true });
97
+ }
98
+ catch (cleanup) {
99
+ throw new AggregateError([error, cleanup], "Private Git index capture and cleanup failed");
100
+ }
101
+ throw error;
94
102
  }
103
+ await rm(directory, { recursive: true, force: true });
104
+ return value;
95
105
  }
96
106
  function fields(record, count) {
97
107
  const result = [];
@@ -107,15 +117,7 @@ function fields(record, count) {
107
117
  return result;
108
118
  }
109
119
  async function workspaceStatus(repository, workspace) {
110
- const records = (await runGit(repository, [
111
- "-C",
112
- workspace,
113
- "status",
114
- "--porcelain=v2",
115
- "-z",
116
- "--untracked-files=all",
117
- "--ignore-submodules=none",
118
- ]))
120
+ const records = (await executeGit(repository, ["-C", workspace, "status", "--porcelain=v2", "-z", "--untracked-files=all", "--ignore-submodules=none"], undefined, { GIT_OPTIONAL_LOCKS: "0" }))
119
121
  .toString("utf8")
120
122
  .split("\0");
121
123
  const staged = new Set();
@@ -172,7 +174,7 @@ async function workspaceChanges(repository, workspace) {
172
174
  /** Observe MERGE_HEAD in an appointed workspace, or undefined when absent. */
173
175
  export async function workspaceMergeHead(repository, workspace) {
174
176
  try {
175
- return mintSnapshotId((await runGit(repository, ["-C", workspace, "rev-parse", "-q", "--verify", "MERGE_HEAD"]))
177
+ return mintSnapshotId((await executeGit(repository, ["-C", workspace, "rev-parse", "-q", "--verify", "MERGE_HEAD"]))
176
178
  .toString("utf8")
177
179
  .trim());
178
180
  }
@@ -250,7 +252,7 @@ export async function observeTargetLag(repository, workspace, head) {
250
252
  if (head === null)
251
253
  return { kind: "unknown", subject };
252
254
  try {
253
- const text = (await runGit(repository, ["-C", workspace, "rev-list", "--count", `HEAD..${head}`]))
255
+ const text = (await executeGit(repository, ["-C", workspace, "rev-list", "--count", `HEAD..${head}`]))
254
256
  .toString("utf8")
255
257
  .trim();
256
258
  if (!/^[0-9]+$/u.test(text))
@@ -265,7 +267,7 @@ export async function observeTargetLag(repository, workspace, head) {
265
267
  }
266
268
  /** Capture tracked and untracked workspace bytes without changing its real index. */
267
269
  export async function captureWorkspaceTree(repository, workspace) {
268
- const identities = (await runGit(repository, ["-C", workspace, "show", "-s", "--format=%H%n%T%n%cI", "HEAD"]))
270
+ const identities = (await executeGit(repository, ["-C", workspace, "show", "-s", "--format=%H%n%T%n%cI", "HEAD"]))
269
271
  .toString("utf8")
270
272
  .split("\n");
271
273
  if (identities.length !== 4 ||
@@ -285,10 +287,10 @@ export async function captureWorkspaceTree(repository, workspace) {
285
287
  if (!dirty)
286
288
  return { tree, head, at, dirty, changes };
287
289
  return await withPrivateGitIndex(async (environment) => {
288
- await runGitWithEnvironment(repository, ["-C", workspace, "read-tree", "HEAD"], undefined, environment);
289
- await runGitWithEnvironment(repository, ["-C", workspace, "add", "--all"], undefined, environment);
290
+ await executeGit(repository, ["-C", workspace, "-c", "core.splitIndex=false", "read-tree", gitObjectId(head)], undefined, environment);
291
+ await executeGit(repository, ["-C", workspace, "-c", "core.splitIndex=false", "add", "--all"], undefined, environment);
290
292
  return {
291
- tree: gitObjectId((await runGitWithEnvironment(repository, ["-C", workspace, "write-tree"], undefined, environment))
293
+ tree: gitObjectId((await executeGit(repository, ["-C", workspace, "-c", "core.splitIndex=false", "write-tree"], undefined, environment))
292
294
  .toString("utf8")
293
295
  .trim(), "workspace tree"),
294
296
  head,
@@ -320,6 +322,11 @@ function receiptFor(value) {
320
322
  mergeHead: mintSnapshotId(record.mergeHead),
321
323
  };
322
324
  }
325
+ function receiptMatches(receipt, coordinate) {
326
+ return (receipt.contractId === coordinate.contractId &&
327
+ receipt.place === coordinate.place &&
328
+ receipt.workspace === resolve(coordinate.workspace));
329
+ }
323
330
  async function storedHandoffReceipt(repository, contractId, place) {
324
331
  const ref = handoffRefFor(contractId, place);
325
332
  const oid = await readRef(repository, ref);
@@ -329,7 +336,7 @@ async function storedHandoffReceipt(repository, contractId, place) {
329
336
  return { receipt, ref, oid };
330
337
  }
331
338
  async function removeHandoffReceipt(repository, stored) {
332
- await runGit(repository, ["update-ref", "--no-deref", "-d", stored.ref, stored.oid]);
339
+ await executeGit(repository, ["update-ref", "--no-deref", "-d", stored.ref, stored.oid]);
333
340
  }
334
341
  export async function recordConflictHandoff(repository, input) {
335
342
  const ref = handoffRefFor(input.contractId, input.place);
@@ -345,27 +352,37 @@ export async function recordConflictHandoff(repository, input) {
345
352
  mergeHead: input.mergeHead,
346
353
  };
347
354
  const oid = await writeBlob(repository, `${JSON.stringify(receipt)}\n`);
348
- await runGit(repository, ["update-ref", "--no-deref", ref, oid, "0".repeat(oid.length)]);
355
+ await executeGit(repository, ["update-ref", "--no-deref", ref, oid, "0".repeat(oid.length)]);
349
356
  }
350
- export async function conflictHandoffFor(repository, input) {
351
- const stored = await storedHandoffReceipt(repository, input.contractId, input.place);
352
- if (stored === null)
353
- return undefined;
354
- if (stored.receipt.contractId !== input.contractId ||
355
- stored.receipt.place !== input.place ||
356
- stored.receipt.workspace !== resolve(input.workspace)) {
357
- return undefined;
357
+ /** Read selected handoff refs once and decode their receipts through the call's blob channel. */
358
+ export async function readConflictHandoffs(repository, readBlobs, coordinates) {
359
+ const byRef = new Map();
360
+ for (const coordinate of coordinates)
361
+ byRef.set(handoffRefFor(coordinate.contractId, coordinate.place), coordinate);
362
+ if (byRef.size === 0)
363
+ return new Map();
364
+ const resolved = await readRefs(repository, [...byRef.keys()]);
365
+ const present = [...resolved].flatMap(([ref, oid]) => (oid === null ? [] : [{ ref, oid }]));
366
+ const blobs = await readBlobs(present.map(({ oid }) => oid));
367
+ const handoffs = new Map();
368
+ for (const { ref, oid } of present) {
369
+ const result = blobs.get(oid);
370
+ if (result?.kind !== "present")
371
+ throw new AuthorityCorruptionError(`Git handoff receipt is missing: ${ref}`);
372
+ const receipt = receiptFor(JSON.parse(result.bytes.toString("utf8")));
373
+ const coordinate = byRef.get(ref);
374
+ if (!receiptMatches(receipt, coordinate))
375
+ continue;
376
+ handoffs.set(coordinate.contractId, { base: receipt.head, mergeHead: receipt.mergeHead });
358
377
  }
359
- return { base: stored.receipt.head, mergeHead: stored.receipt.mergeHead };
378
+ return handoffs;
360
379
  }
361
380
  export async function retireConflictHandoff(repository, input) {
362
381
  const stored = await storedHandoffReceipt(repository, input.contractId, input.place);
363
382
  if (stored === null)
364
383
  return { kind: "absent" };
365
384
  const { receipt } = stored;
366
- if (receipt.contractId !== input.contractId ||
367
- receipt.place !== input.place ||
368
- receipt.workspace !== resolve(input.workspace)) {
385
+ if (!receiptMatches(receipt, input)) {
369
386
  return { kind: "retained", reason: "receipt-mismatch" };
370
387
  }
371
388
  const gitDirectory = await worktreeGitDirectory(repository, input.workspace);
@@ -389,7 +406,7 @@ export async function retireConflictHandoff(repository, input) {
389
406
  }
390
407
  if (!input.consume)
391
408
  return { kind: "active" };
392
- await runGit(repository, ["-C", input.workspace, "merge", "--quit"]);
409
+ await executeGit(repository, ["-C", input.workspace, "merge", "--quit"]);
393
410
  await removeHandoffReceipt(repository, stored);
394
411
  return { kind: "retired" };
395
412
  }
@@ -1,5 +1,5 @@
1
- export { kanshi, observeKanshi } from "./read.js";
1
+ export { kanshi, kanshiCategory, observeKanshi } from "./read.js";
2
2
  export { selectKanshi, selectRegion } from "./select.js";
3
3
  export type { KanshiInput } from "./read.js";
4
- export type { AkumaKanshiRow, AkumaKanshiWorld, ContractEndpointObservation, ContractHolderObservation, ContractKanshiBoard, ContractKanshiRow, KanshiReport, Section, TaskKanshiRow, TaskKanshiWorld, KanshiRegionSelection, RegionDeclaration, RegionOverlap, RegionRead, } from "./report.js";
4
+ export type { AkumaKanshiRow, AkumaKanshiWorld, ContractEndpointObservation, ContractHolderObservation, ContractKanshiBoard, ContractKanshiRow, KanshiCategoryReport, KanshiReport, Section, TaskKanshiRow, TaskKanshiWorld, KanshiRegionSelection, RegionDeclaration, RegionOverlap, RegionRead, } from "./report.js";
5
5
  export type { KanshiSelection } from "./select.js";
@@ -1,2 +1,2 @@
1
- export { kanshi, observeKanshi } from "./read.js";
1
+ export { kanshi, kanshiCategory, observeKanshi } from "./read.js";
2
2
  export { selectKanshi, selectRegion } from "./select.js";
@@ -2,7 +2,7 @@ import { type AliasBinding } from "../alias/index.js";
2
2
  import { Repo } from "../library/repo.js";
3
3
  import type { ContractBoard } from "../protocol/read/status.js";
4
4
  import type { WorldRoot } from "../world.js";
5
- import type { KanshiRegionSelection, KanshiReport, Section } from "./report.js";
5
+ import type { KanshiCategoryReport, KanshiRegionSelection, KanshiReport, Section } from "./report.js";
6
6
  export type KanshiInput = Readonly<{
7
7
  world: WorldRoot | null;
8
8
  repo?: Repo;
@@ -15,3 +15,10 @@ export type KanshiObservation = Readonly<{
15
15
  }>;
16
16
  export declare function observeKanshi(input: KanshiInput): Promise<KanshiObservation>;
17
17
  export declare function kanshi(input: KanshiInput): Promise<KanshiReport>;
18
+ export type KanshiCategoryInput = Readonly<{
19
+ world: WorldRoot | null;
20
+ repo?: Repo;
21
+ category: KanshiCategoryReport["category"];
22
+ limit?: number;
23
+ }>;
24
+ export declare function kanshiCategory(input: KanshiCategoryInput): Promise<KanshiCategoryReport>;
@@ -1,5 +1,5 @@
1
1
  import { withoutReportedChanges } from "../akuma/projection.js";
2
- import { readAkumaRoster, readAkumaTimeline } from "../akuma/akuma.js";
2
+ import { observeAkumaRoster, readAkumaTimeline } from "../akuma/akuma.js";
3
3
  import { readAliases } from "../alias/index.js";
4
4
  import { decodeContractDocument } from "../body/decode.js";
5
5
  import { assertRegionPattern } from "../body/region.js";
@@ -16,6 +16,7 @@ import { observeRecentTaskStatus, TaskAuthorityCorruptionError } from "../task/i
16
16
  import { observeTaskBoard } from "../task/operations.js";
17
17
  import { ROSTER_SNAPSHOT_ROWS, ROSTER_VISIBLE_ROWS } from "./roster.js";
18
18
  import { selectKanshi, selectRegion } from "./select.js";
19
+ const WORLD_CONTRACT_ROWS = 10;
19
20
  function diagnostic(error) {
20
21
  let source;
21
22
  if (error instanceof Error)
@@ -128,12 +129,12 @@ async function readBranch(repo) {
128
129
  return null;
129
130
  }
130
131
  }
131
- async function readContracts(observation, include) {
132
+ async function readContracts(observation, include, limit = WORLD_CONTRACT_ROWS) {
132
133
  try {
133
134
  return {
134
135
  kind: "present",
135
136
  value: include === undefined
136
- ? await readContractCatalogue(observation, 10)
137
+ ? await readContractCatalogue(observation, limit)
137
138
  : await readContractBoard(observation, include),
138
139
  };
139
140
  }
@@ -282,11 +283,12 @@ async function claimedAssociatedContracts(observation, dispatches) {
282
283
  }));
283
284
  return claimed;
284
285
  }
285
- async function joinAkuma(path, observeContract, isContractClaimed, dispatches, aliases) {
286
+ async function joinAkuma(path, observeContract, isContractClaimed, dispatches, input) {
287
+ const { aliases, limit = ROSTER_VISIBLE_ROWS } = input;
286
288
  if (aliases.kind !== "present")
287
289
  return aliases;
288
290
  try {
289
- const source = await readAkumaRoster(path, { limit: ROSTER_VISIBLE_ROWS });
291
+ const source = await observeAkumaRoster(path, limit);
290
292
  const aliasById = new Map();
291
293
  for (const binding of aliases.value)
292
294
  aliasById.set(binding.akuId, [...(aliasById.get(binding.akuId) ?? []), binding]);
@@ -355,7 +357,9 @@ async function observeWithoutRepo(world, region, observedAt, branch) {
355
357
  const observeContract = contractEndpointObserver(contracts);
356
358
  const tasks = world === null ? { kind: "absent" } : await readTasks(world, holders, observeContract);
357
359
  const aliases = world === null ? { kind: "absent" } : await readAliasBindings(world);
358
- const akuma = world === null ? { kind: "absent" } : await joinAkuma(world, observeContract, () => false, [], aliases);
360
+ const akuma = world === null
361
+ ? { kind: "absent" }
362
+ : await joinAkuma(world, observeContract, () => false, [], { aliases });
359
363
  return {
360
364
  report: {
361
365
  root: world,
@@ -394,7 +398,7 @@ async function observeRepo(input) {
394
398
  ? { kind: "absent" }
395
399
  : dispatches.kind === "failed"
396
400
  ? dispatches
397
- : await joinAkuma(world, observeContract, (id) => claimed.has(id), dispatches.value, aliases);
401
+ : await joinAkuma(world, observeContract, (id) => claimed.has(id), dispatches.value, { aliases });
398
402
  const assembled = {
399
403
  root: world,
400
404
  observedAt,
@@ -443,6 +447,67 @@ export async function observeKanshi(input) {
443
447
  export async function kanshi(input) {
444
448
  return (await observeKanshi(input)).report;
445
449
  }
450
+ /** Category observations reuse owner rows without reading the Task board. */
451
+ async function observeAkumaCategory(world, repo, limit, observedAt) {
452
+ const report = (akuma) => ({
453
+ category: "akuma",
454
+ root: world,
455
+ observedAt,
456
+ akuma,
457
+ });
458
+ if (world === null)
459
+ return report({ kind: "absent" });
460
+ const composed = async (observation) => {
461
+ const aliases = await readAliasBindings(world);
462
+ if (aliases.kind !== "present")
463
+ return report(aliases);
464
+ if (observation === undefined)
465
+ return report(await joinAkuma(world, () => "unavailable", () => false, [], { aliases, limit }));
466
+ const dispatches = await readDispatches(observation);
467
+ if (dispatches.kind === "failed")
468
+ return report(dispatches);
469
+ const claimed = await claimedAssociatedContracts(observation, dispatches.value);
470
+ return report(await joinAkuma(world, () => "unavailable", (id) => claimed.has(id), dispatches.value, { aliases, limit }));
471
+ };
472
+ if (repo === undefined)
473
+ return await composed();
474
+ try {
475
+ return await withGitDecodeChannel(repo, (channel) => withGitReadObservation(repo, channel, composed));
476
+ }
477
+ catch (error) {
478
+ return report({ kind: "failed", failure: { message: diagnostic(error) } });
479
+ }
480
+ }
481
+ async function observeContractCategory(world, repo, limit, observedAt) {
482
+ const report = (contracts) => ({
483
+ category: "contract",
484
+ root: world,
485
+ observedAt,
486
+ contracts,
487
+ });
488
+ try {
489
+ return await withGitDecodeChannel(repo, (channel) => withGitReadObservation(repo, channel, async (observation) => {
490
+ const [contracts, holders] = await Promise.all([
491
+ readContracts(observation, undefined, limit),
492
+ readHolders(observation),
493
+ ]);
494
+ return report(decorateContracts(contracts, holders));
495
+ }));
496
+ }
497
+ catch (error) {
498
+ return report({ kind: "failed", failure: { message: diagnostic(error) } });
499
+ }
500
+ }
501
+ export async function kanshiCategory(input) {
502
+ const observedAt = new Date().toISOString();
503
+ const { world, repo, category, limit = 10 } = input;
504
+ if (category === "contract") {
505
+ if (repo === undefined)
506
+ throw new TypeError("kanshi contract category requires a Repo");
507
+ return await observeContractCategory(world, scopeForRepo(repo), limit, observedAt);
508
+ }
509
+ return await observeAkumaCategory(world, repo === undefined ? undefined : scopeForRepo(repo), limit, observedAt);
510
+ }
446
511
  async function attachSelectedIssue(observation, contracts, selected) {
447
512
  if (contracts.kind !== "present")
448
513
  return contracts;
@@ -100,4 +100,16 @@ export type KanshiReport = Readonly<{
100
100
  akuma: Section<AkumaKanshiWorld>;
101
101
  region?: Section<RegionRead>;
102
102
  }>;
103
+ /** Internal category observation retains only the requested owner section. */
104
+ export type KanshiCategoryReport = Readonly<{
105
+ category: "akuma";
106
+ root: WorldRoot | null;
107
+ observedAt: string;
108
+ akuma: Section<AkumaKanshiWorld>;
109
+ }> | Readonly<{
110
+ category: "contract";
111
+ root: WorldRoot | null;
112
+ observedAt: string;
113
+ contracts: Section<ContractKanshiBoard>;
114
+ }>;
103
115
  export type { CurrentPhysicalIssue };
@@ -15,8 +15,7 @@ import type { Settings } from "../settings.js";
15
15
  import { type WorldRoot } from "../world.js";
16
16
  import type { Keiyaku } from "./keiyaku.js";
17
17
  import { type Repo } from "./repo.js";
18
- export type { AkumaStatus } from "../akuma/akuma.js";
19
- export type IntegrationFailure = Readonly<{
18
+ type IntegrationFailure = Readonly<{
20
19
  kind: "authority-corruption" | "infrastructure";
21
20
  diagnostic: string;
22
21
  }>;
@@ -30,7 +29,7 @@ export type DispatchStage = Readonly<{
30
29
  kind: "failed";
31
30
  failure: DispatchFailure | IntegrationFailure;
32
31
  }>;
33
- export type AliasStage = Readonly<{
32
+ type AliasStage = Readonly<{
34
33
  kind: "none";
35
34
  }> | Readonly<{
36
35
  kind: "aliased";
@@ -47,7 +46,7 @@ export type CallWaitHead = Readonly<{
47
46
  dispatch: DispatchStage;
48
47
  alias: AliasStage;
49
48
  }>;
50
- export type CallWaitObserver = Readonly<{
49
+ type CallWaitObserver = Readonly<{
51
50
  admitted?: (tell: TellResult, id: AkumaStatus["id"], head: CallWaitHead) => void | Promise<void>;
52
51
  observe?: AskObserver["observe"];
53
52
  }>;
@@ -117,3 +116,4 @@ export declare function callAkumas(input: CallInput & Readonly<{
117
116
  export declare function forkAkumas(input: ForkInput & Readonly<{
118
117
  path: WorldRoot;
119
118
  }>): Promise<ForkResult>;
119
+ export {};
@@ -1,45 +1,11 @@
1
1
  import { decodeContractDocument } from "../body/decode.js";
2
2
  import { type ActorId, type ContractId } from "../core/facts/types.js";
3
3
  import type { GitDecodeChannel } from "../git/read-observation.js";
4
- import { bindOperation, type BindTargetSelection } from "../protocol/bind.js";
4
+ import { type BindTargetSelection } from "../protocol/bind.js";
5
5
  import { type IntentOutcome, type RepositoryScope } from "../protocol/operations.js";
6
6
  import type { ProtocolProgress } from "../protocol/progress.js";
7
7
  import type { TaskId } from "../task/identity.js";
8
- import type { VerificationDeclarationPreparation } from "../verification/declaration.js";
9
8
  import type { ForkSourceRefusal, OperationRefusals } from "./refusal.js";
10
- type BindAttemptInput = Readonly<{
11
- scope: RepositoryScope;
12
- channel: GitDecodeChannel;
13
- title: string;
14
- terms: Parameters<typeof bindOperation>[0]["terms"];
15
- verification: VerificationDeclarationPreparation;
16
- workspace: "worktree";
17
- targetSelection?: BindTargetSelection;
18
- coordinates?: Readonly<{
19
- start: import("../core/facts/types.js").SnapshotId;
20
- }>;
21
- source?: Parameters<typeof bindOperation>[0]["source"];
22
- task?: TaskId;
23
- progress?: ProtocolProgress;
24
- actor?: ActorId;
25
- }>;
26
- export declare function admitBindWithAppointment(input: BindAttemptInput): Promise<IntentOutcome<Readonly<{
27
- contractId: ContractId;
28
- }>, {
29
- kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
30
- contractId: ContractId;
31
- } | {
32
- kind: "verification-declaration-invalid";
33
- contractId?: ContractId | undefined;
34
- } | {
35
- kind: "fork-source-moved";
36
- contractId: ContractId;
37
- } | {
38
- kind: "unborn-head" | "target-missing" | "invalid-target";
39
- } | {
40
- kind: "fork-source-missing" | "fork-source-unavailable";
41
- contractId: ContractId;
42
- }>>;
43
9
  type ForkBindAdmission = Readonly<{
44
10
  kind: "document";
45
11
  document: ReturnType<typeof decodeContractDocument>;
@@ -62,34 +28,6 @@ export declare function admitForkBindWithAppointment(input: Readonly<{
62
28
  kind: "refused";
63
29
  refusal: ForkSourceRefusal;
64
30
  }> | ForkBindAdmission>;
65
- export declare function admitMarkdownBind(input: Readonly<{
66
- scope: RepositoryScope;
67
- channel: GitDecodeChannel;
68
- title: string;
69
- terms: Parameters<typeof bindOperation>[0]["terms"];
70
- verification: VerificationDeclarationPreparation;
71
- workspace: "worktree";
72
- targetSelection?: BindTargetSelection;
73
- task?: TaskId;
74
- progress?: ProtocolProgress;
75
- actor?: ActorId;
76
- }>): Promise<IntentOutcome<Readonly<{
77
- contractId: ContractId;
78
- }>, {
79
- kind: "contract-exists" | "invalid-after" | "unknown-prerequisite";
80
- contractId: ContractId;
81
- } | {
82
- kind: "verification-declaration-invalid";
83
- contractId?: ContractId | undefined;
84
- } | {
85
- kind: "fork-source-moved";
86
- contractId: ContractId;
87
- } | {
88
- kind: "unborn-head" | "target-missing" | "invalid-target";
89
- } | {
90
- kind: "fork-source-missing" | "fork-source-unavailable";
91
- contractId: ContractId;
92
- }>>;
93
31
  export declare function prepareMarkdownBind(input: Readonly<{
94
32
  scope: RepositoryScope;
95
33
  channel: GitDecodeChannel;
@@ -7,7 +7,7 @@ import { mintIdentitySegment } from "../identity/mint.js";
7
7
  import { fitIdentityStemWords, normalizeIdentityStem } from "../identity/normalize.js";
8
8
  import { bindOperation } from "../protocol/bind.js";
9
9
  import { stateOperation } from "../protocol/operations.js";
10
- import { claimTaskHolder, claimTaskHolderWithFence } from "../settlement/holder.js";
10
+ import { admitWithTaskHolderFence, claimTaskHolder } from "../settlement/holder.js";
11
11
  import { KeiyakuError } from "./outcome.js";
12
12
  import { contractTerms, documentDerivation } from "./input.js";
13
13
  const CONTRACT_ID_CODE_POINTS = 32;
@@ -48,9 +48,6 @@ async function attemptCandidates(input) {
48
48
  collision: (result) => result.kind === "refused" && result.refusal.kind === "contract-exists",
49
49
  });
50
50
  }
51
- export async function admitBindWithAppointment(input) {
52
- return await attemptCandidates(input);
53
- }
54
51
  /**
55
52
  * A legally non-forkable source is an expected refusal; corrupt persisted authority for a source that
56
53
  * does exist is exceptional and names that source Contract.
@@ -119,12 +116,9 @@ export async function admitForkBindWithAppointment(input) {
119
116
  });
120
117
  return { kind: "document", admission, document };
121
118
  }
122
- export async function admitMarkdownBind(input) {
123
- return await admitBindWithAppointment(input);
124
- }
125
119
  export async function prepareMarkdownBind(input) {
126
120
  const terms = contractTerms(input.document, input.gates, input.after);
127
- const admitCandidate = () => admitMarkdownBind({
121
+ const admitCandidate = () => attemptCandidates({
128
122
  scope: input.scope,
129
123
  channel: input.channel,
130
124
  title: input.document.title,
@@ -136,6 +130,6 @@ export async function prepareMarkdownBind(input) {
136
130
  ...(input.actor === undefined ? {} : { actor: input.actor }),
137
131
  ...(input.progress === undefined ? {} : { progress: input.progress }),
138
132
  });
139
- const admission = input.task === undefined ? null : await claimTaskHolderWithFence(input.scope, input.task, admitCandidate);
133
+ const admission = input.task === undefined ? null : await admitWithTaskHolderFence(input.scope, input.task, admitCandidate);
140
134
  return { admission, result: admission === null ? await admitCandidate() : admission.result };
141
135
  }