@astrosheep/keiyaku 2.9.8 → 2.9.10

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 (230) hide show
  1. package/README.md +50 -182
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/harness/control-types.js +18 -1
  4. package/build/agents/harness/index.js +2 -0
  5. package/build/agents/harness/outcome-error.js +81 -0
  6. package/build/agents/harness/projection.js +10 -7
  7. package/build/agents/harness/router.js +5 -1
  8. package/build/agents/providers/claude-agent-sdk/adapter.js +18 -4
  9. package/build/agents/providers/claude-agent-sdk/registration.js +11 -1
  10. package/build/agents/providers/claude-agent-sdk/session.js +19 -5
  11. package/build/agents/providers/codex-app-server/adapter.js +11 -6
  12. package/build/agents/providers/codex-app-server/events.js +67 -6
  13. package/build/agents/providers/codex-app-server/registration.js +11 -1
  14. package/build/agents/providers/opencode-sdk/adapter.js +8 -1
  15. package/build/agents/providers/opencode-sdk/events.js +24 -2
  16. package/build/agents/providers/opencode-sdk/registration.js +11 -1
  17. package/build/agents/providers/pi/checkpoint.js +9 -1
  18. package/build/agents/providers/pi/events.js +2 -0
  19. package/build/agents/providers/pi/registration.js +14 -1
  20. package/build/cli/commands/akuma/akuma/handler.js +1 -1
  21. package/build/cli/commands/akuma/akuma/meta.js +3 -3
  22. package/build/cli/commands/akuma/catalog.js +2 -2
  23. package/build/cli/commands/akuma/{view → show}/handler.js +5 -5
  24. package/build/cli/commands/akuma/{view → show}/meta.js +3 -3
  25. package/build/cli/commands/akuma.js +1 -1
  26. package/build/cli/commands/contract/amend/handler.js +5 -4
  27. package/build/cli/commands/contract/arc/handler.js +5 -4
  28. package/build/cli/commands/contract/audit/handler.js +2 -2
  29. package/build/cli/commands/contract/bind/handler.js +12 -3
  30. package/build/cli/commands/contract/bind/meta.js +45 -15
  31. package/build/cli/commands/contract/forfeit/handler.js +9 -5
  32. package/build/cli/commands/contract/log/handler.js +2 -2
  33. package/build/cli/commands/contract/petition/handler.js +34 -7
  34. package/build/cli/commands/contract/renew/handler.js +7 -7
  35. package/build/cli/commands/contract/renew/meta.js +3 -3
  36. package/build/cli/commands/metadata.js +10 -6
  37. package/build/cli/commands/projection/call/meta.js +1 -1
  38. package/build/cli/commands/projection/catalog.js +2 -0
  39. package/build/cli/commands/projection/history/handler.js +21 -0
  40. package/build/cli/commands/projection/history/meta.js +9 -0
  41. package/build/cli/commands/projection/shared.js +3 -4
  42. package/build/cli/commands/projection/status/handler.js +3 -3
  43. package/build/cli/commands/projection/wait/handler.js +20 -11
  44. package/build/cli/commands/task/add/handler.js +14 -5
  45. package/build/cli/commands/task/add/meta.js +2 -2
  46. package/build/cli/commands/task/catalog.js +4 -0
  47. package/build/cli/commands/task/done/handler.js +1 -4
  48. package/build/cli/commands/task/done/meta.js +1 -1
  49. package/build/cli/commands/task/drop/meta.js +1 -1
  50. package/build/cli/commands/task/hold/handler.js +3 -0
  51. package/build/cli/commands/task/hold/meta.js +8 -0
  52. package/build/cli/commands/task/log/handler.js +1 -1
  53. package/build/cli/commands/task/log/meta.js +2 -2
  54. package/build/cli/commands/task/resume/handler.js +3 -0
  55. package/build/cli/commands/task/resume/meta.js +8 -0
  56. package/build/cli/commands/task/shared.js +39 -14
  57. package/build/cli/commands/task/show/handler.js +1 -1
  58. package/build/cli/commands/task/show/meta.js +1 -1
  59. package/build/cli/commands/task/start/meta.js +1 -1
  60. package/build/cli/commands/task/stop/handler.js +1 -4
  61. package/build/cli/commands/task/stop/meta.js +1 -1
  62. package/build/cli/commands/task/update/handler.js +11 -3
  63. package/build/cli/commands/task/update/meta.js +3 -3
  64. package/build/cli/completion.js +3 -2
  65. package/build/cli/flags.js +51 -14
  66. package/build/cli/help.js +4 -1
  67. package/build/cli/index.js +40 -25
  68. package/build/cli/parse-flags.js +40 -7
  69. package/build/cli/parse-metadata.js +5 -2
  70. package/build/cli/parse-selectors.js +2 -3
  71. package/build/cli/parse.js +40 -6
  72. package/build/cli/projection-address.js +12 -10
  73. package/build/cli/render/amendment-warning.js +8 -0
  74. package/build/cli/render/arc.js +6 -2
  75. package/build/cli/render/audit.js +400 -81
  76. package/build/cli/render/kanshi.js +242 -79
  77. package/build/cli/render/lifecycle.js +56 -0
  78. package/build/cli/render/misc.js +24 -28
  79. package/build/cli/render/petition.js +5 -0
  80. package/build/cli/render/projection-activity.js +65 -29
  81. package/build/cli/render/projection-history.js +64 -0
  82. package/build/cli/render/shared.js +23 -9
  83. package/build/cli/render/status.js +13 -35
  84. package/build/cli/render/task.js +51 -26
  85. package/build/cli/render/terminal-failure.js +3 -1
  86. package/build/cli/render/wait.js +45 -69
  87. package/build/cli/subagent-guard.js +1 -1
  88. package/build/cli/types.js +1 -1
  89. package/build/config/env-keys.js +3 -1
  90. package/build/config/env.js +24 -1
  91. package/build/config/settings/schema.js +3 -1
  92. package/build/core/address-carrier.js +89 -0
  93. package/build/core/addressing.js +255 -196
  94. package/build/core/amend.js +115 -38
  95. package/build/core/amendment-criteria.js +17 -0
  96. package/build/core/amendment-warning.js +10 -0
  97. package/build/core/arc.js +184 -83
  98. package/build/core/audit/candidate.js +110 -9
  99. package/build/core/audit/coordinates.js +120 -65
  100. package/build/core/audit/evidence.js +19 -23
  101. package/build/core/audit/facade.js +34 -11
  102. package/build/core/audit/report.js +5 -5
  103. package/build/core/bind-reconciliation.js +390 -0
  104. package/build/core/bind-workspace.js +12 -20
  105. package/build/core/bind.js +242 -273
  106. package/build/core/call/call.js +1 -0
  107. package/build/core/call/context.js +46 -71
  108. package/build/core/call/prompt.js +6 -3
  109. package/build/core/context.js +49 -35
  110. package/build/core/contract-carrier-runtime.js +408 -0
  111. package/build/core/contract-carrier.js +270 -0
  112. package/build/core/contract-view.js +33 -27
  113. package/build/core/contract.js +5 -1
  114. package/build/core/derived-replay.js +207 -0
  115. package/build/core/draft.js +125 -57
  116. package/build/core/forfeit.js +113 -56
  117. package/build/core/identifier-slug.js +63 -13
  118. package/build/core/ids.js +4 -4
  119. package/build/core/lifecycle-history.js +35 -0
  120. package/build/core/lifecycle-recovery.js +117 -0
  121. package/build/core/lifecycle-runner.js +377 -0
  122. package/build/core/log.js +37 -11
  123. package/build/core/outcome-base.js +181 -0
  124. package/build/core/process-group.js +139 -0
  125. package/build/core/projection/generation/database.js +82 -7
  126. package/build/core/projection/generation/model.js +9 -36
  127. package/build/core/projection/generation/projection-generation-continuation.js +10 -22
  128. package/build/core/projection/generation/projection-generation-execution.js +13 -6
  129. package/build/core/projection/index.js +5 -4
  130. package/build/core/projection/projection-activity.js +29 -8
  131. package/build/core/projection/projection-alias.js +23 -10
  132. package/build/core/projection/projection-core.js +21 -7
  133. package/build/core/projection/projection-execution-observer.js +91 -39
  134. package/build/core/projection/projection-history.js +474 -0
  135. package/build/core/projection/projection-runner-lock.js +12 -0
  136. package/build/core/projection/projection-status-observation.js +365 -0
  137. package/build/core/projection/projection-status.js +35 -337
  138. package/build/core/projection/projection-terminal-failure.js +13 -8
  139. package/build/core/projection/projection-wait.js +7 -2
  140. package/build/core/projection/tell/launch-store.js +244 -0
  141. package/build/core/projection/tell/model.js +3 -3
  142. package/build/core/projection/tell/store.js +70 -118
  143. package/build/core/registry.js +22 -87
  144. package/build/core/renew-build.js +424 -0
  145. package/build/core/renew-plan.js +239 -0
  146. package/build/core/renew-rewrite.js +77 -0
  147. package/build/core/renew.js +295 -520
  148. package/build/core/repository-ledger/accepted-fold-read.js +19 -0
  149. package/build/core/repository-ledger/accepted-tail.js +116 -0
  150. package/build/core/repository-ledger/admission.js +38 -0
  151. package/build/core/repository-ledger/authoritative-transaction.js +1 -0
  152. package/build/core/repository-ledger/claim-evidence.js +147 -0
  153. package/build/core/repository-ledger/codec.js +297 -0
  154. package/build/core/repository-ledger/current-state-store.js +853 -0
  155. package/build/core/repository-ledger/fold-repository.js +375 -0
  156. package/build/core/repository-ledger/fold.js +248 -0
  157. package/build/core/repository-ledger/git-object-store.js +243 -0
  158. package/build/core/repository-ledger/history-read.js +15 -0
  159. package/build/core/repository-ledger/incremental-read.js +153 -0
  160. package/build/core/repository-ledger/index.js +15 -0
  161. package/build/core/repository-ledger/inventory-plan.js +75 -0
  162. package/build/core/repository-ledger/inventory.js +310 -0
  163. package/build/core/repository-ledger/publication-admission.js +125 -0
  164. package/build/core/repository-ledger/publication.js +353 -0
  165. package/build/core/repository-ledger/read-model.js +469 -0
  166. package/build/core/repository-ledger/transaction-membership.js +78 -0
  167. package/build/core/repository-ledger/traversal.js +404 -0
  168. package/build/core/repository-ledger/write-transaction.js +339 -0
  169. package/build/core/seal.js +168 -161
  170. package/build/core/settlement/claim-delivery.js +42 -215
  171. package/build/core/settlement/claim.js +235 -153
  172. package/build/core/settlement/index.js +4 -4
  173. package/build/core/settlement/petition-claim-gates.js +52 -33
  174. package/build/core/settlement/petition-forfeit.js +12 -5
  175. package/build/core/settlement/petition-head-guard.js +8 -5
  176. package/build/core/settlement/petition-preview.js +68 -56
  177. package/build/core/settlement/petition-window.js +50 -0
  178. package/build/core/settlement/petition.js +252 -131
  179. package/build/core/settlement/queue-read-model.js +72 -95
  180. package/build/core/settlement/queue-seat-allocation.js +35 -126
  181. package/build/core/settlement/queue.js +1 -1
  182. package/build/core/settlement/settlement.js +172 -80
  183. package/build/core/settlement/verdict.js +112 -66
  184. package/build/core/settlement/verification-coordination.js +305 -0
  185. package/build/core/settlement/verification-supervisor.js +275 -0
  186. package/build/core/settlement/verification.js +398 -31
  187. package/build/core/status/board.js +125 -127
  188. package/build/core/status/lifecycle.js +7 -80
  189. package/build/core/structured-query.js +23 -0
  190. package/build/core/target-ref.js +1 -1
  191. package/build/core/task/board.js +59 -24
  192. package/build/core/task/commands.js +181 -33
  193. package/build/core/task/coordinate.js +56 -0
  194. package/build/core/task/document.js +25 -9
  195. package/build/core/task/index.js +7 -4
  196. package/build/core/task/query.js +17 -27
  197. package/build/core/task/settlement-git.js +164 -179
  198. package/build/core/task/settlement-policy.js +15 -11
  199. package/build/core/task/source-board.js +31 -13
  200. package/build/core/task/task-bind-preparation.js +193 -0
  201. package/build/core/task/task-contract.js +102 -193
  202. package/build/core/task/task-file-transaction.js +171 -0
  203. package/build/core/task/task-git-runtime.js +76 -14
  204. package/build/core/task/task-git-store.js +68 -169
  205. package/build/core/task/task-store-repository.js +13 -6
  206. package/build/core/task/task-worktree.js +6 -33
  207. package/build/core/task/task.js +1 -1
  208. package/build/core/task/tree.js +3 -3
  209. package/build/core/task/validation.js +4 -3
  210. package/build/core/transcripts.js +93 -1
  211. package/build/core/worktree-bootstrap.js +44 -36
  212. package/build/core/worktree-path.js +210 -77
  213. package/build/flow-error.js +7 -7
  214. package/build/generated/version.js +2 -2
  215. package/build/git/core.js +76 -13
  216. package/build/git/refs.js +168 -46
  217. package/build/git/streaming-batch.js +73 -13
  218. package/package.json +1 -1
  219. package/skills/keiyaku/SKILL.md +1 -1
  220. package/skills/keiyaku-akuma/SKILL.md +3 -3
  221. package/skills/keiyaku-task/SKILL.md +4 -2
  222. package/skills/keiyaku-workflow/SKILL.md +88 -203
  223. package/build/core/entry.js +0 -305
  224. package/build/core/ledger-batch.js +0 -194
  225. package/build/core/ledger.js +0 -84
  226. package/build/core/projection/leash.js +0 -87
  227. package/build/core/ref-log.js +0 -119
  228. package/build/core/renew-session.js +0 -128
  229. package/build/core/status/ledger-batch.js +0 -1
  230. package/build/core/status/reconciliation.js +0 -137
@@ -0,0 +1,404 @@
1
+ import { classifyRepositoryLedgerSubject, evidenceObjectId, parseRepositoryLedgerMessage, } from "./codec.js";
2
+ import { transactionMembershipError } from "./transaction-membership.js";
3
+ import { assertReadableCommitClosure, assertReadableCommit, deriveHostGitCoordinates, openRepositoryCommitReader, RepositoryObjectError, } from "./git-object-store.js";
4
+ import { assertHonestClaimEvidence, assertHonestClaimEvidenceClosure, ClaimEvidenceMismatchError, ClaimEvidenceOperationalError, repositoryObjectDirectory } from "./claim-evidence.js";
5
+ /** Ledger topology excludes lifecycle causality and evidence ancestry. */
6
+ export function ledgerTopologyParents(node) {
7
+ if (node.type === "transaction" || node.type === "join")
8
+ return node.ledgerParents;
9
+ if (node.type === "disease" && (node.boundary === "transaction" || node.boundary === "join")) {
10
+ return node.ledgerParents;
11
+ }
12
+ return [];
13
+ }
14
+ function topologyFor(record, parents, objectId) {
15
+ if (record.kind === "join") {
16
+ if (parents.length !== 2 || parents[0] === parents[1])
17
+ throw new Error("structural join must have exactly two distinct ledger parents");
18
+ return { type: "join", objectId, join: record, ledgerParents: [parents[0], parents[1]], evidenceParent: null };
19
+ }
20
+ if (record.kind === "transaction") {
21
+ const predecessorCount = record.predecessor === "p1" ? 1 : 0;
22
+ if (parents.length <= predecessorCount)
23
+ throw new Error("transaction must link at least one introduced lifecycle entry");
24
+ const ledgerParents = parents.slice(0, predecessorCount);
25
+ const entryObjectIds = parents.slice(predecessorCount);
26
+ if (new Set(parents).size !== parents.length)
27
+ throw new Error("transaction parents must be distinct");
28
+ return {
29
+ type: "transaction",
30
+ objectId,
31
+ transaction: record,
32
+ ledgerParents,
33
+ entryObjectIds,
34
+ contract: "",
35
+ finalEntryObjectId: entryObjectIds.at(-1),
36
+ evidenceParent: null,
37
+ };
38
+ }
39
+ const evidence = evidenceObjectId(record);
40
+ if (evidence !== null) {
41
+ if (parents.length !== 2)
42
+ throw new Error(`${record.kind} requires lifecycle p1 and evidence p2`);
43
+ if (parents[1] !== evidence)
44
+ throw new Error(`${record.kind} evidence p2 does not match ${evidence}`);
45
+ return { type: "lifecycle", objectId, entry: record, ledgerParents: [parents[0]], evidenceParent: evidence };
46
+ }
47
+ if (parents.length > 1)
48
+ throw new Error(`${record.kind} may have at most one lifecycle parent and no evidence parent`);
49
+ if (parents.length === 0 && record.kind !== "bind")
50
+ throw new Error("the parentless lifecycle root must be bind");
51
+ return {
52
+ type: "lifecycle",
53
+ objectId,
54
+ entry: record,
55
+ ledgerParents: parents.length === 0 ? [] : [parents[0]],
56
+ evidenceParent: null,
57
+ };
58
+ }
59
+ function recoverDiseasedTopology(message, parents) {
60
+ const subject = message === undefined ? { type: "unknown" } : classifyRepositoryLedgerSubject(message);
61
+ if (subject.type === "join")
62
+ return { boundary: "join", ledgerParents: parents.slice(0, 2) };
63
+ if (subject.type === "transaction")
64
+ return { boundary: "transaction", ledgerParents: parents.slice(0, 1) };
65
+ if (subject.type === "lifecycle")
66
+ return { boundary: "lifecycle", contract: subject.contract, ledgerParents: parents.slice(0, 1) };
67
+ return { boundary: "unknown", ledgerParents: [] };
68
+ }
69
+ function decodeCommitMessage(bytes) {
70
+ try {
71
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
72
+ }
73
+ catch (error) {
74
+ throw new Error("commit message is not valid UTF-8", { cause: error });
75
+ }
76
+ }
77
+ function throwIfAborted(error) {
78
+ if (error instanceof Error && error.name === "AbortError")
79
+ throw error;
80
+ }
81
+ function readableLawfulTransactionContract(node, nodes) {
82
+ const entries = [];
83
+ for (const entryObjectId of node.entryObjectIds) {
84
+ const entryNode = nodes.get(entryObjectId);
85
+ if (entryNode?.type !== "lifecycle")
86
+ return undefined;
87
+ entries.push(entryNode.entry);
88
+ }
89
+ if (transactionMembershipError(node.transaction.verb, entries))
90
+ return undefined;
91
+ for (let index = 0; index < node.entryObjectIds.length; index += 1) {
92
+ const entryNode = nodes.get(node.entryObjectIds[index]);
93
+ const causalParent = entryNode.ledgerParents[0];
94
+ if (index === 0) {
95
+ if (entryNode.entry.kind === "bind" ? causalParent !== undefined : causalParent === undefined)
96
+ return undefined;
97
+ }
98
+ else if (causalParent !== node.entryObjectIds[index - 1]) {
99
+ return undefined;
100
+ }
101
+ }
102
+ return entries[0]?.contract;
103
+ }
104
+ function hasDisease(diseases, objectId, code) {
105
+ return diseases.some((disease) => disease.objectId === objectId && disease.code === code);
106
+ }
107
+ export function transactionEntryBoundaryError(node, nodes, wasAcceptedBefore) {
108
+ const entries = [];
109
+ for (const entryObjectId of node.entryObjectIds) {
110
+ if (wasAcceptedBefore(entryObjectId))
111
+ return "transaction links a lifecycle entry already reachable from its predecessor";
112
+ const entryNode = nodes.get(entryObjectId);
113
+ if (entryNode?.type !== "lifecycle")
114
+ return "transaction entry link is not a readable lifecycle node";
115
+ entries.push(entryNode.entry);
116
+ }
117
+ const membership = transactionMembershipError(node.transaction.verb, entries);
118
+ if (membership)
119
+ return membership;
120
+ for (let index = 0; index < node.entryObjectIds.length; index += 1) {
121
+ const entryNode = nodes.get(node.entryObjectIds[index]);
122
+ const causalParent = entryNode.ledgerParents[0];
123
+ if (index === 0) {
124
+ if (entryNode.entry.kind === "bind") {
125
+ if (causalParent !== undefined)
126
+ return "bind transaction entry must be causally parentless";
127
+ }
128
+ else if (causalParent === undefined || !wasAcceptedBefore(causalParent)) {
129
+ return "first transaction entry must continue lifecycle causality reachable from the predecessor";
130
+ }
131
+ }
132
+ else if (causalParent !== node.entryObjectIds[index - 1]) {
133
+ return "transaction entries do not form one ordered lifecycle causal tail";
134
+ }
135
+ }
136
+ node.contract = entries[0].contract;
137
+ return null;
138
+ }
139
+ function transactionBoundaryError(node, nodes, acceptedEntryIntroductions) {
140
+ if (node.transaction.predecessor === "none") {
141
+ if (node.ledgerParents.length !== 0)
142
+ return "root transaction unexpectedly has a predecessor";
143
+ if (node.transaction.verb !== "bind")
144
+ return "the root transaction must be bind";
145
+ }
146
+ else if (node.ledgerParents.length !== 1) {
147
+ return "non-root transaction must have exactly one ledger predecessor";
148
+ }
149
+ const predecessor = node.ledgerParents[0];
150
+ if (predecessor !== undefined) {
151
+ const predecessorNode = nodes.get(predecessor);
152
+ if (!predecessorNode || predecessorNode.type === "lifecycle" || (predecessorNode.type === "disease" && predecessorNode.boundary === "lifecycle")) {
153
+ return "transaction predecessor is not a complete typed ledger node";
154
+ }
155
+ }
156
+ return transactionEntryBoundaryError(node, nodes, (entryObjectId) => {
157
+ const introduction = acceptedEntryIntroductions.get(entryObjectId);
158
+ return introduction !== undefined
159
+ && predecessor !== undefined
160
+ && isTypedLedgerAncestor({ nodes }, introduction, predecessor);
161
+ });
162
+ }
163
+ export async function traverseRepositoryLedger(cwd, head, signal, options = {}) {
164
+ const coordinates = await deriveHostGitCoordinates(cwd, signal);
165
+ let completeObservedClosure = true;
166
+ try {
167
+ await assertReadableCommitClosure(cwd, head, signal);
168
+ }
169
+ catch (error) {
170
+ if (error instanceof RepositoryObjectError && error.reason === "incomplete-commit-closure") {
171
+ completeObservedClosure = false;
172
+ }
173
+ else {
174
+ throw error;
175
+ }
176
+ }
177
+ const reader = openRepositoryCommitReader(cwd, coordinates, signal);
178
+ let objectDirectory;
179
+ const nodes = new Map();
180
+ const diseases = [];
181
+ const order = [];
182
+ const visiting = new Set();
183
+ const visited = new Set();
184
+ const acceptedEntryIntroductions = new Map();
185
+ const visit = async (objectId) => {
186
+ if (visited.has(objectId))
187
+ return;
188
+ if (visiting.has(objectId)) {
189
+ diseases.push({ objectId, code: "cycle", detail: "typed repository ancestry contains a cycle" });
190
+ return;
191
+ }
192
+ visiting.add(objectId);
193
+ let raw;
194
+ try {
195
+ raw = await reader.read(objectId);
196
+ }
197
+ catch (error) {
198
+ throwIfAborted(error);
199
+ diseases.push({ objectId, code: "unreadable-node", detail: error instanceof Error ? error.message : String(error) });
200
+ visiting.delete(objectId);
201
+ visited.add(objectId);
202
+ return;
203
+ }
204
+ let message;
205
+ let record;
206
+ try {
207
+ message = decodeCommitMessage(raw.messageBytes);
208
+ record = parseRepositoryLedgerMessage(message, coordinates.objectFormat);
209
+ }
210
+ catch (error) {
211
+ const diseased = recoverDiseasedTopology(message ?? raw.subjectHint, raw.parents);
212
+ diseases.push({ objectId, code: "invalid-codec", detail: error instanceof Error ? error.message : String(error), ...(diseased.contract ? { contract: diseased.contract } : {}) });
213
+ nodes.set(objectId, { type: "disease", objectId, ...diseased, evidenceParent: null });
214
+ for (const parent of diseased.ledgerParents)
215
+ await visit(parent);
216
+ order.push(objectId);
217
+ visiting.delete(objectId);
218
+ visited.add(objectId);
219
+ return;
220
+ }
221
+ if (raw.tree !== coordinates.emptyTree) {
222
+ const diseased = recoverDiseasedTopology(message, raw.parents);
223
+ diseases.push({ objectId, code: "wrong-tree", detail: `expected empty tree ${coordinates.emptyTree}, found ${raw.tree}`, ...(diseased.contract ? { contract: diseased.contract } : {}) });
224
+ nodes.set(objectId, { type: "disease", objectId, ...diseased, evidenceParent: null });
225
+ for (const parent of diseased.ledgerParents)
226
+ await visit(parent);
227
+ order.push(objectId);
228
+ visiting.delete(objectId);
229
+ visited.add(objectId);
230
+ return;
231
+ }
232
+ let node;
233
+ try {
234
+ node = topologyFor(record, raw.parents, objectId);
235
+ }
236
+ catch (error) {
237
+ const diseased = recoverDiseasedTopology(message, raw.parents);
238
+ diseases.push({ objectId, code: "invalid-parent-topology", detail: error instanceof Error ? error.message : String(error), ...(diseased.contract ? { contract: diseased.contract } : {}) });
239
+ nodes.set(objectId, { type: "disease", objectId, ...diseased, evidenceParent: null });
240
+ for (const parent of diseased.ledgerParents)
241
+ await visit(parent);
242
+ order.push(objectId);
243
+ visiting.delete(objectId);
244
+ visited.add(objectId);
245
+ return;
246
+ }
247
+ nodes.set(objectId, node);
248
+ const dependencies = node.type === "transaction"
249
+ ? [...node.ledgerParents, ...node.entryObjectIds]
250
+ : [...node.ledgerParents];
251
+ for (const parent of dependencies)
252
+ await visit(parent);
253
+ const unreadableLedgerParent = node.ledgerParents.find((parent) => hasDisease(diseases, parent, "unreadable-node") ||
254
+ (node.type === "transaction" && hasDisease(diseases, parent, "unreadable-ledger-closure")));
255
+ if ((node.type === "transaction" || node.type === "join") && unreadableLedgerParent !== undefined) {
256
+ const contract = node.type === "transaction"
257
+ ? readableLawfulTransactionContract(node, nodes)
258
+ : undefined;
259
+ const closureDisease = {
260
+ objectId,
261
+ code: "unreadable-ledger-closure",
262
+ detail: `ledger predecessor ${unreadableLedgerParent} is not completely readable`,
263
+ ...(contract === undefined ? {} : { contract }),
264
+ };
265
+ const predecessorDiseaseIndex = diseases.findIndex((disease) => disease.objectId === unreadableLedgerParent && disease.code === "unreadable-node");
266
+ if (predecessorDiseaseIndex < 0)
267
+ diseases.push(closureDisease);
268
+ else
269
+ diseases.splice(predecessorDiseaseIndex, 0, closureDisease);
270
+ nodes.set(objectId, {
271
+ type: "disease",
272
+ objectId,
273
+ boundary: node.type,
274
+ ...(contract === undefined ? {} : { contract }),
275
+ ledgerParents: [...node.ledgerParents],
276
+ evidenceParent: null,
277
+ });
278
+ order.push(objectId);
279
+ visiting.delete(objectId);
280
+ visited.add(objectId);
281
+ return;
282
+ }
283
+ if (node.type === "lifecycle" && node.evidenceParent !== null) {
284
+ try {
285
+ if (node.entry.kind === "claim") {
286
+ if (options.historicalSemanticEvidence !== false) {
287
+ objectDirectory ??= await repositoryObjectDirectory(cwd, signal);
288
+ await assertHonestClaimEvidence(cwd, node.entry.data, { coordinates, reader, objectDirectory, signal });
289
+ }
290
+ else {
291
+ await reader.read(node.evidenceParent);
292
+ }
293
+ if (!completeObservedClosure)
294
+ await assertHonestClaimEvidenceClosure(cwd, node.evidenceParent);
295
+ }
296
+ else {
297
+ await reader.read(node.evidenceParent);
298
+ if (!completeObservedClosure)
299
+ await assertReadableCommit(cwd, coordinates, node.evidenceParent);
300
+ }
301
+ }
302
+ catch (error) {
303
+ throwIfAborted(error);
304
+ if (node.entry.kind === "claim" && !(error instanceof ClaimEvidenceMismatchError)) {
305
+ if (error instanceof ClaimEvidenceOperationalError)
306
+ throw error;
307
+ throw new ClaimEvidenceOperationalError("cannot read claim evidence for verification", { cause: error });
308
+ }
309
+ const code = node.entry.kind === "claim" ? "invalid-evidence" : "unreadable-evidence";
310
+ diseases.push({ objectId, code, detail: error instanceof Error ? error.message : String(error), contract: node.entry.contract });
311
+ nodes.set(objectId, { type: "disease", objectId, boundary: "lifecycle", contract: node.entry.contract, ledgerParents: [...node.ledgerParents], evidenceParent: null });
312
+ }
313
+ }
314
+ if (node.type === "transaction") {
315
+ const diseasedMembers = node.entryObjectIds
316
+ .map((entryObjectId) => nodes.get(entryObjectId))
317
+ .filter((entryNode) => entryNode?.type === "disease");
318
+ if (diseasedMembers.length > 0) {
319
+ const contracts = new Set(diseasedMembers.flatMap((member) => member.contract === undefined ? [] : [member.contract]));
320
+ const evidenceDiseaseOnly = node.entryObjectIds.every((entryObjectId) => diseases.some((disease) => disease.objectId === entryObjectId &&
321
+ (disease.code === "invalid-evidence" || disease.code === "unreadable-evidence")));
322
+ if (!evidenceDiseaseOnly) {
323
+ diseases.push({
324
+ objectId,
325
+ code: "invalid-transaction-boundary",
326
+ detail: "transaction contains a diseased lifecycle member",
327
+ ...(contracts.size === 1 ? { contract: [...contracts][0] } : {}),
328
+ });
329
+ }
330
+ nodes.set(objectId, {
331
+ type: "disease",
332
+ objectId,
333
+ boundary: "transaction",
334
+ ...(contracts.size === 1 ? { contract: [...contracts][0] } : {}),
335
+ ledgerParents: [...node.ledgerParents],
336
+ evidenceParent: null,
337
+ });
338
+ }
339
+ else {
340
+ const detail = transactionBoundaryError(node, nodes, acceptedEntryIntroductions);
341
+ if (detail) {
342
+ diseases.push({ objectId, code: "invalid-transaction-boundary", detail });
343
+ nodes.set(objectId, { type: "disease", objectId, boundary: "transaction", ledgerParents: [...node.ledgerParents], evidenceParent: null });
344
+ }
345
+ else {
346
+ for (const entryObjectId of node.entryObjectIds)
347
+ acceptedEntryIntroductions.set(entryObjectId, node.objectId);
348
+ }
349
+ }
350
+ }
351
+ order.push(objectId);
352
+ visiting.delete(objectId);
353
+ visited.add(objectId);
354
+ };
355
+ try {
356
+ await visit(head);
357
+ const headNode = nodes.get(head);
358
+ if (headNode?.type === "lifecycle") {
359
+ diseases.push({ objectId: head, code: "invalid-transaction-boundary", detail: "repository ledger head is a lifecycle entry rather than a transaction or join" });
360
+ nodes.set(head, { type: "disease", objectId: head, boundary: "lifecycle", contract: headNode.entry.contract, ledgerParents: [...headNode.ledgerParents], evidenceParent: null });
361
+ }
362
+ return { head, coordinates, nodes, order, diseases };
363
+ }
364
+ finally {
365
+ await reader.close();
366
+ }
367
+ }
368
+ export function isTypedLedgerAncestor(ledger, ancestor, descendant) {
369
+ if (ancestor === descendant)
370
+ return true;
371
+ const pending = [descendant];
372
+ const seen = new Set();
373
+ while (pending.length > 0) {
374
+ const objectId = pending.pop();
375
+ if (seen.has(objectId))
376
+ continue;
377
+ seen.add(objectId);
378
+ const node = ledger.nodes.get(objectId);
379
+ if (!node)
380
+ continue;
381
+ for (const parent of ledgerTopologyParents(node)) {
382
+ if (parent === ancestor)
383
+ return true;
384
+ pending.push(parent);
385
+ }
386
+ }
387
+ return false;
388
+ }
389
+ export function isLifecycleCausalAncestor(ledger, ancestor, descendant) {
390
+ if (ancestor === descendant)
391
+ return true;
392
+ let current = ledger.nodes.get(descendant);
393
+ const seen = new Set();
394
+ while (current?.type === "lifecycle" && current.ledgerParents.length === 1) {
395
+ const parent = current.ledgerParents[0];
396
+ if (parent === ancestor)
397
+ return true;
398
+ if (seen.has(parent))
399
+ return false;
400
+ seen.add(parent);
401
+ current = ledger.nodes.get(parent);
402
+ }
403
+ return false;
404
+ }