@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
@@ -1,7 +1,7 @@
1
1
  import { observeActiveContractWorld, observeContractsForAdmissionInObservationAt, observeDeliveryTargetAt, withContractReadObservationAt, } from "../../git/observe.js";
2
- import { decodeContractDocument, verificationDefinition } from "../../body/decode.js";
2
+ import { decodeContractDocument } from "../../body/decode.js";
3
3
  import { dependencyKeys } from "../../core/subject.js";
4
- import { observeTargetLag, observeWorkspace, conflictHandoffFor, conflictRecovery, worktreePath, } from "../../git/workspace.js";
4
+ import { observeTargetLag, observeWorkspace, readConflictHandoffs, conflictRecovery, worktreePath, } from "../../git/workspace.js";
5
5
  import { appointmentFor, readPlaceRegister } from "../../workspace-place.js";
6
6
  import { gateReports, latestCurrentAttestations } from "../../core/facts/gate.js";
7
7
  import { gate, } from "../../core/facts/types.js";
@@ -26,12 +26,10 @@ function phaseFor(state) {
26
26
  return "abandoned";
27
27
  return "bound";
28
28
  }
29
- function verificationFor(state, document) {
30
- if (document === undefined)
31
- return undefined;
32
- if (verificationDefinition(document) === null)
33
- return { kind: "undeclared" };
29
+ function verificationFor(state) {
34
30
  const verifiedGate = gate("verified");
31
+ if (!state.terms.gates.includes(verifiedGate))
32
+ return { kind: "undeclared" };
35
33
  const current = latestCurrentAttestations(state, new Set([verifiedGate])).get(verifiedGate);
36
34
  if (current !== undefined) {
37
35
  const snapshot = dependencyKeys(current.data.subject).find((key) => key.kind === "snapshot")?.value;
@@ -53,20 +51,26 @@ export function lastJournalAtFor(entries) {
53
51
  throw new Error("present Contract journal is empty");
54
52
  return last.at;
55
53
  }
56
- async function managedWorkspaceFacts(repository, state, register, targetObservation) {
54
+ function appointedWorkspace(repository, register, state) {
57
55
  const appointed = appointmentFor(register, state.id);
56
+ return appointed === undefined
57
+ ? undefined
58
+ : { contractId: state.id, place: appointed.place, workspace: worktreePath(repository, appointed.place) };
59
+ }
60
+ async function readSelectedHandoffs(observation, workspaces) {
61
+ return await readConflictHandoffs(observation.repository, observation.readBlobs, workspaces.flatMap((workspace) => (workspace === undefined ? [] : [workspace])));
62
+ }
63
+ async function managedWorkspaceFacts(repository, state, appointed, targetObservation, handoff) {
58
64
  if (appointed === undefined) {
59
65
  return {
60
- appointed,
61
66
  workspaceObservation: { kind: "unappointed" },
62
67
  targetLag: state.coordinates.target === undefined ? { kind: "none" } : { kind: "unknown" },
63
68
  };
64
69
  }
65
- const path = worktreePath(repository, appointed.place);
66
- const [workspaceObservation, targetLag, handoff] = await Promise.all([
70
+ const path = appointed.workspace;
71
+ const [workspaceObservation, targetLag] = await Promise.all([
67
72
  observeWorkspace(repository, { kind: "worktree", path }, path),
68
73
  observeTargetLag(repository, path, targetObservation?.head),
69
- conflictHandoffFor(repository, { contractId: state.id, place: appointed.place, workspace: path }),
70
74
  ]);
71
75
  const projectedWorkspaceObservation = handoff !== undefined &&
72
76
  (workspaceObservation.kind === "clean" || workspaceObservation.kind === "dirty") &&
@@ -80,7 +84,7 @@ async function managedWorkspaceFacts(repository, state, register, targetObservat
80
84
  },
81
85
  }
82
86
  : workspaceObservation;
83
- return { appointed, workspaceObservation: projectedWorkspaceObservation, targetLag };
87
+ return { workspaceObservation: projectedWorkspaceObservation, targetLag };
84
88
  }
85
89
  function afterEndpoint(state) {
86
90
  if (state === undefined || state === null)
@@ -104,12 +108,11 @@ function reverseDependents(id, rows) {
104
108
  .sort((left, right) => left.contractId.localeCompare(right.contractId));
105
109
  }
106
110
  async function rowFor(input) {
107
- const { repository, state, bindAt, lastJournalAt, targetObservation, register, after, dependents } = input;
108
- const workspace = state.coordinates.workspace;
111
+ const { repository, state, bindAt, lastJournalAt, targetObservation, workspace, handoff, after, dependents } = input;
109
112
  const gates = gateReports(state);
110
113
  const document = documentFor(state);
111
- const verification = verificationFor(state, document);
112
- const { appointed, workspaceObservation, targetLag } = await managedWorkspaceFacts(repository, state, register, targetObservation);
114
+ const verification = verificationFor(state);
115
+ const facts = await managedWorkspaceFacts(repository, state, workspace, targetObservation, handoff);
113
116
  return {
114
117
  id: state.id,
115
118
  title: titleFor(document),
@@ -117,11 +120,11 @@ async function rowFor(input) {
117
120
  phaseAt: phaseAtFor(state, bindAt),
118
121
  lastJournalAt,
119
122
  disposition: state.terminal === null ? "active" : "terminal",
120
- workspace,
121
- worktreePath: appointed === undefined ? null : worktreePath(repository, appointed.place),
122
- workspaceObservation,
123
+ workspace: state.coordinates.workspace,
124
+ worktreePath: workspace?.workspace ?? null,
125
+ workspaceObservation: facts.workspaceObservation,
123
126
  target: state.coordinates.target ?? null,
124
- targetLag,
127
+ targetLag: facts.targetLag,
125
128
  delivery: state.delivery === null || state.currentIntegration === null
126
129
  ? null
127
130
  : { ...state.delivery.data, integration: state.currentIntegration },
@@ -163,23 +166,27 @@ export async function readContractBoard(observation, include) {
163
166
  }
164
167
  }
165
168
  const register = await readPlaceRegister(observation.repository);
166
- const projected = await Promise.all([...contracts.values()].flatMap((value) => {
167
- if (value.state === null)
168
- return [];
169
- const state = value.state;
170
- return [
171
- observeDeliveryTargetAt(observation, state).then((target) => rowFor({
172
- repository: observation.repository,
173
- state,
174
- bindAt: value.entries[0].at,
175
- lastJournalAt: lastJournalAtFor(value.entries),
176
- targetObservation: target,
177
- register,
178
- after: afterEdges(state, endpoints),
179
- dependents: [],
180
- })),
181
- ];
182
- }));
169
+ const selected = [...contracts.values()].flatMap((value) => value.state === null
170
+ ? []
171
+ : [
172
+ {
173
+ ...value,
174
+ state: value.state,
175
+ workspace: appointedWorkspace(observation.repository, register, value.state),
176
+ },
177
+ ]);
178
+ const handoffs = await readSelectedHandoffs(observation, selected.map(({ workspace }) => workspace));
179
+ const projected = await Promise.all(selected.map(async ({ state, entries, workspace }) => await rowFor({
180
+ repository: observation.repository,
181
+ state,
182
+ bindAt: entries[0].at,
183
+ lastJournalAt: lastJournalAtFor(entries),
184
+ targetObservation: await observeDeliveryTargetAt(observation, state),
185
+ workspace,
186
+ handoff: handoffs.get(state.id),
187
+ after: afterEdges(state, endpoints),
188
+ dependents: [],
189
+ })));
183
190
  const rows = projected.map((row) => ({ ...row, dependents: reverseDependents(row.id, projected) }));
184
191
  return {
185
192
  root: observation.repository.primaryWorktree,
@@ -218,13 +225,19 @@ export async function readContractCatalogue(observation, limit) {
218
225
  const afterIds = selected.rows.flatMap(({ state }) => state.terms.after);
219
226
  const endpoints = await afterEndpointMap(observation, new Map(observed.eligibility), afterIds);
220
227
  const register = await readPlaceRegister(observation.repository);
221
- const rows = await Promise.all(selected.rows.map(async ({ state, bindAt, lastJournalAt }) => await rowFor({
228
+ const selectedWorkspaces = selected.rows.map((value) => ({
229
+ ...value,
230
+ workspace: appointedWorkspace(observation.repository, register, value.state),
231
+ }));
232
+ const handoffs = await readSelectedHandoffs(observation, selectedWorkspaces.map(({ workspace }) => workspace));
233
+ const rows = await Promise.all(selectedWorkspaces.map(async ({ state, bindAt, lastJournalAt, workspace }) => await rowFor({
222
234
  repository: observation.repository,
223
235
  state,
224
236
  bindAt,
225
237
  lastJournalAt,
226
238
  targetObservation: await observeDeliveryTargetAt(observation, state),
227
- register,
239
+ workspace,
240
+ handoff: handoffs.get(state.id),
228
241
  after: afterEdges(state, endpoints),
229
242
  dependents: reverseDependentsFromStates(state.id, active),
230
243
  })));
@@ -257,6 +270,9 @@ export async function readContractObservation(observation, id) {
257
270
  if (state === null)
258
271
  return { kind: "missing", id };
259
272
  const endpoints = await afterEndpointMap(observation, new Map([[id, state]]), state.terms.after);
273
+ const register = await readPlaceRegister(observation.repository);
274
+ const workspace = appointedWorkspace(observation.repository, register, state);
275
+ const handoffs = await readSelectedHandoffs(observation, [workspace]);
260
276
  return {
261
277
  kind: "present",
262
278
  row: await rowFor({
@@ -265,7 +281,8 @@ export async function readContractObservation(observation, id) {
265
281
  bindAt: record.entries[0].at,
266
282
  lastJournalAt: lastJournalAtFor(record.entries),
267
283
  targetObservation: await observeDeliveryTargetAt(observation, state),
268
- register: await readPlaceRegister(observation.repository),
284
+ workspace,
285
+ handoff: handoffs.get(state.id),
269
286
  after: afterEdges(state, endpoints),
270
287
  dependents: [],
271
288
  }),
@@ -11,7 +11,7 @@ type TargetMissing = Readonly<{
11
11
  kind: "target-missing";
12
12
  contractId: ContractId;
13
13
  }>;
14
- export type ReintegrationRefusal = ReintegrateRefusal | TargetMissing | IntegrationPreparationRefusal;
14
+ type ReintegrationRefusal = ReintegrateRefusal | TargetMissing | IntegrationPreparationRefusal;
15
15
  export type ReintegrationResult = (AcceptedAdmission & Readonly<{
16
16
  value: ReintegratedData;
17
17
  }>) | Readonly<{
@@ -1,11 +1,11 @@
1
1
  import { contractState } from "../core/facts/observation.js";
2
2
  import { decideReintegrate } from "../core/verbs/reintegrate.js";
3
- import { materializeReintegrationSnapshot, persistedTender, planIntegration, } from "../git/integration.js";
3
+ import { materializeReintegrationSnapshot, persistedTender, planIntegration, reusableIntegrationSnapshot, } from "../git/integration.js";
4
4
  import { observeContractsForAdmissionAt } from "../git/observe.js";
5
5
  import { appendPrivateStateSeatClose, mergePrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
6
6
  import { admitDecidedOffer, mintAttempts } from "./attempt.js";
7
- import { timestamp } from "./operations.js";
8
- import { contractStateWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
7
+ import { recordedIntegrationSnapshots, timestamp } from "./operations.js";
8
+ import { externalPreparation, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
9
9
  import { runUnderTargetPlacementFence } from "./placement.js";
10
10
  function reintegrationResultWithSeatClose(outcome) {
11
11
  return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
@@ -16,23 +16,16 @@ function reintegrationResultWithSeatClose(outcome) {
16
16
  }
17
17
  /** Plan and materialize the target-specific reintegration artifacts outside the publication seat. */
18
18
  async function prepareExternalReintegration(input) {
19
- const observation = await observeContractsForAdmissionAt(input.repository, input.channel, [input.contractId]);
20
- const state = contractState(observation.decision, input.contractId);
21
- if (state === null)
22
- return { kind: "unavailable" };
23
- return {
24
- kind: "artifacts",
25
- witness: contractStateWitness(state),
26
- artifacts: await planReintegrationArtifacts(input, state),
27
- };
19
+ return await externalPreparation({ ...input, scope: input.repository }, (observation, state) => planReintegrationArtifacts(input, state, recordedIntegrationSnapshots(observation.journals.get(state.id)?.entries ?? [])));
28
20
  }
29
- async function planReintegrationArtifacts(input, state) {
21
+ async function planReintegrationArtifacts(input, state, recordedIntegrations) {
30
22
  if (state.delivery === null || state.currentIntegration === null)
31
23
  return { kind: "defer" };
32
24
  const planned = await planIntegration(input.repository, { contractId: input.contractId, coordinates: state.coordinates }, await persistedTender(input.repository, state.delivery.data.tenderSnapshot), state.delivery.data.policy.requireBranchesToBeUpToDate);
33
25
  if (planned.kind === "refused")
34
26
  return { kind: "refused", refusal: planned.refusal };
35
- const snapshot = await materializeReintegrationSnapshot(input.repository, planned.data.tree, planned.data.predecessor, state.delivery.data.integration.snapshot);
27
+ const snapshot = (await reusableIntegrationSnapshot(input.repository, planned.data.tree, planned.data.predecessor, recordedIntegrations)) ??
28
+ (await materializeReintegrationSnapshot(input.repository, planned.data.tree, planned.data.predecessor, state.delivery.data.integration.snapshot));
36
29
  return {
37
30
  kind: "prepared",
38
31
  data: { predecessor: planned.data.predecessor, snapshot },
@@ -80,14 +73,12 @@ async function runReintegration(input) {
80
73
  if (decision.kind === "refused")
81
74
  return { kind: "refused", refusal: decision.refusal };
82
75
  const admitted = await admitDecidedOffer({
83
- channel: input.channel,
84
- repository: input.repository,
76
+ ...input,
77
+ scope: input.repository,
85
78
  seat,
86
- decisionObservation: observation,
79
+ observation,
87
80
  attempt,
88
81
  offer: decision.offer,
89
- primaryContract: input.contractId,
90
- ...(input.progress === undefined ? {} : { progress: input.progress }),
91
82
  ...(assembled.kind === "prepared" ? { assertions: [assembled.assertion] } : {}),
92
83
  });
93
84
  if (admitted.kind === "accepted") {
@@ -1,8 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { type ActiveContractRefusal } from "../core/facts/observation.js";
3
- import type { AttestationData, ContractState, DeliverData } from "../core/facts/types.js";
3
+ import type { AttestationData } from "../core/facts/types.js";
4
4
  import type { LeadingOutcome } from "./outcome.js";
5
- import type { MutationOperationInput, RepositoryScope } from "./operations.js";
5
+ import type { MutationOperationInput } from "./operations.js";
6
6
  type ReviewPreparationRefusal = Readonly<{
7
7
  kind: "worktree-missing";
8
8
  contractId: import("../core/facts/types.js").ContractId;
@@ -12,18 +12,6 @@ type ReviewOperationInput = MutationOperationInput & Readonly<{
12
12
  verdict: AttestationData["verdict"];
13
13
  summary?: string;
14
14
  }>;
15
- declare const reviewWorkspaceEvidenceSchema: z.ZodObject<{
16
- staged: z.ZodReadonly<z.ZodArray<z.ZodString>>;
17
- unstaged: z.ZodReadonly<z.ZodArray<z.ZodString>>;
18
- untracked: z.ZodReadonly<z.ZodArray<z.ZodString>>;
19
- shortStat: z.ZodObject<{
20
- filesChanged: z.ZodNumber;
21
- insertions: z.ZodNumber;
22
- deletions: z.ZodNumber;
23
- }, z.core.$strict>;
24
- unmergedPaths: z.ZodReadonly<z.ZodArray<z.ZodString>>;
25
- }, z.core.$strict>;
26
- type ReviewWorkspaceEvidence = z.infer<typeof reviewWorkspaceEvidenceSchema>;
27
15
  export declare const reviewAdmissionValueSchema: z.ZodObject<{
28
16
  workspace: z.ZodOptional<z.ZodObject<{
29
17
  staged: z.ZodReadonly<z.ZodArray<z.ZodString>>;
@@ -37,19 +25,6 @@ export declare const reviewAdmissionValueSchema: z.ZodObject<{
37
25
  unmergedPaths: z.ZodReadonly<z.ZodArray<z.ZodString>>;
38
26
  }, z.core.$strict>>;
39
27
  }, z.core.$strict>;
40
- export type ReviewAdmissionValue = z.infer<typeof reviewAdmissionValueSchema>;
41
- export declare function prepareReview(repository: RepositoryScope, stage: Readonly<{
42
- contractId: import("../core/facts/types.js").ContractId;
43
- coordinates: ContractState["coordinates"];
44
- }>): Promise<{
45
- kind: "prepared";
46
- data: Readonly<{
47
- changeId: DeliverData["integration"]["changeId"];
48
- workspace?: ReviewWorkspaceEvidence;
49
- }>;
50
- } | {
51
- kind: "refused";
52
- refusal: ReviewPreparationRefusal;
53
- }>;
28
+ type ReviewAdmissionValue = z.infer<typeof reviewAdmissionValueSchema>;
54
29
  export declare function admitReviewOperation(input: ReviewOperationInput): Promise<LeadingOutcome<ReviewAdmissionValue, ReviewRefusal>>;
55
30
  export {};
@@ -4,7 +4,7 @@ import { worktreeChangeId } from "../git/integration.js";
4
4
  import { captureTender, dirtyTenderDelta, dirtyTenderRefusal } from "../git/tender.js";
5
5
  import { observeContractsForAdmissionAt } from "../git/observe.js";
6
6
  import { unmergedWorkspacePaths, worktreePath } from "../git/workspace.js";
7
- import { contractStateWitness, privateStateSeatAttempt, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
7
+ import { externalPreparation, privateStateSeatAttempt, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
8
8
  import { dependencyKeySet } from "../core/subject.js";
9
9
  import { contractState } from "../core/facts/observation.js";
10
10
  import { gate } from "../core/facts/types.js";
@@ -51,18 +51,6 @@ async function captureReviewableWorktree(repository, stage) {
51
51
  },
52
52
  };
53
53
  }
54
- export async function prepareReview(repository, stage) {
55
- const prepared = await captureReviewableWorktree(repository, stage);
56
- if (prepared.kind === "refused")
57
- return prepared;
58
- return {
59
- kind: "prepared",
60
- data: {
61
- changeId: prepared.data.changeId,
62
- ...(prepared.data.workspace === undefined ? {} : { workspace: prepared.data.workspace }),
63
- },
64
- };
65
- }
66
54
  function preparedReviewCapture(input, state, changeId) {
67
55
  return {
68
56
  kind: "prepared",
@@ -95,25 +83,19 @@ async function recaptureReviewWorktree(input, state) {
95
83
  }
96
84
  /** Capture the reviewable worktree from one non-authoritative private-state read. */
97
85
  async function prepareExternalReview(input) {
98
- const observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
99
- const state = contractState(observation.decision, input.contractId);
100
- if (state === null)
101
- return { kind: "unavailable" };
102
- const prepared = await captureReviewableWorktree(input.scope, {
103
- contractId: state.id,
104
- coordinates: state.coordinates,
105
- });
106
- return {
107
- kind: "artifacts",
108
- witness: contractStateWitness(state),
109
- artifacts: prepared.kind === "refused"
86
+ return await externalPreparation(input, async (_, state) => {
87
+ const prepared = await captureReviewableWorktree(input.scope, {
88
+ contractId: state.id,
89
+ coordinates: state.coordinates,
90
+ });
91
+ return prepared.kind === "refused"
110
92
  ? { kind: "refused", refusal: prepared.refusal }
111
93
  : {
112
94
  kind: "captured",
113
95
  ...(prepared.data.workspace === undefined ? {} : { workspace: prepared.data.workspace }),
114
96
  worktree: reviewWorktreeInput(prepared),
115
- },
116
- };
97
+ };
98
+ });
117
99
  }
118
100
  /** Assemble the in-custody attestation input from the fresh Contract and validated artifacts. */
119
101
  async function assembleReviewAttempt(input, observation, external) {
@@ -149,16 +131,7 @@ async function decideAndAdmitReview(input, attempt, seat, observation, assembled
149
131
  });
150
132
  if (decision.kind === "refused")
151
133
  return { kind: "refused", refusal: decision.refusal };
152
- const admission = await admitDecidedOffer({
153
- channel: input.channel,
154
- repository: input.scope,
155
- seat,
156
- decisionObservation: observation,
157
- attempt,
158
- offer: decision.offer,
159
- primaryContract: input.contractId,
160
- ...(input.progress === undefined ? {} : { progress: input.progress }),
161
- });
134
+ const admission = await admitDecidedOffer({ ...input, seat, observation, attempt, offer: decision.offer });
162
135
  if (admission.kind !== "accepted")
163
136
  return admission;
164
137
  return {
@@ -7,7 +7,7 @@ import type { GitRepository } from "../git/process.js";
7
7
  import { type GitRefAssertion } from "../git/repository.js";
8
8
  import type { AttemptContext, DecideInput, OfferDecision } from "../core/decide.js";
9
9
  import type { Offer, TreeUpdate } from "../core/facts/offer.js";
10
- import type { ChangeId, ContractHead, ContractId, SnapshotId } from "../core/facts/types.js";
10
+ import type { ChangeId, ContractHead, ContractId, ContractState, SnapshotId } from "../core/facts/types.js";
11
11
  import type { GitObjectId } from "../git/identity.js";
12
12
  import { type AcceptedAdmission, type AttemptTerminal } from "./attempt.js";
13
13
  export declare const STALE_PRIVATE_STATE_PREPARATION: {
@@ -104,14 +104,14 @@ type ProtocolAdmission<Input extends Readonly<{
104
104
  observationSelection?: GitTreeSelection;
105
105
  }>;
106
106
  /** An intent whose invocation is already its decision input. */
107
- export type DirectRunProtocolInput<Seed extends Readonly<{
107
+ type DirectRunProtocolInput<Seed extends Readonly<{
108
108
  contractId: ContractId;
109
109
  }>, Refusal> = ProtocolAdmission<Seed, Refusal> & Readonly<{
110
110
  input: Seed;
111
111
  preparation?: undefined;
112
112
  }>;
113
113
  /** An intent whose repeatable preparation runs outside custody and is assembled inside it. */
114
- export type SplitRunProtocolInput<Input extends Readonly<{
114
+ type SplitRunProtocolInput<Input extends Readonly<{
115
115
  contractId: ContractId;
116
116
  }>, Refusal, Seed extends Readonly<{
117
117
  contractId: ContractId;
@@ -124,7 +124,7 @@ export type RunProtocolInput<Input extends Readonly<{
124
124
  }>, Refusal, Seed extends Readonly<{
125
125
  contractId: ContractId;
126
126
  }> = Input, Prepared = Seed> = DirectRunProtocolInput<Seed, Refusal> | SplitRunProtocolInput<Input, Refusal, Seed, Prepared>;
127
- export type PreparedProtocolAttempt<Refusal> = Readonly<{
127
+ type PreparedProtocolAttempt<Refusal> = Readonly<{
128
128
  kind: "stale";
129
129
  }> | Readonly<{
130
130
  kind: "refused";
@@ -143,7 +143,6 @@ export type PreparedProtocolAttempt<Refusal> = Readonly<{
143
143
  export type ContractStateWitness = Readonly<{
144
144
  head: ContractHead | null;
145
145
  }>;
146
- export declare function contractStateWitness(state: ContractStateWitness): ContractStateWitness;
147
146
  /**
148
147
  * A physical worktree capture carried across custody as a witness, never as authority.
149
148
  *
@@ -162,8 +161,21 @@ export type WorktreeWitness = Readonly<{
162
161
  changeId: ChangeId;
163
162
  }>;
164
163
  export declare function sameWorktreeWitness(prepared: WorktreeWitness | undefined, fresh: WorktreeWitness | undefined): boolean;
165
- export declare function privateStateAssertionsMatch(repository: GitRepository, assertions: readonly GitRefAssertion[]): Promise<boolean>;
166
- export declare function publicationFailedFromSeatError(error: unknown): AttemptTerminal;
164
+ /**
165
+ * The repeatable outside-custody preamble shared by prepared operations: one non-authoritative
166
+ * observation of the invoked Contract, and the artifacts its fresh state justifies.
167
+ */
168
+ export declare function externalPreparation<Artifacts>(input: Readonly<{
169
+ scope: GitRepository;
170
+ channel: GitDecodeChannel;
171
+ contractId: ContractId;
172
+ }>, artifacts: (observation: GitDecisionObservation, state: ContractState) => Promise<Artifacts>): Promise<Readonly<{
173
+ kind: "unavailable";
174
+ }> | Readonly<{
175
+ kind: "artifacts";
176
+ witness: ContractStateWitness;
177
+ artifacts: Artifacts;
178
+ }>>;
167
179
  export declare function privateStateSeatAttempt<T>(repository: GitRepository, action: (seat: PrivateStatePublicationSeat) => Promise<T>, wrap: (outcome: PrivateStateSeatOutcome<T>) => T): Promise<T | AttemptTerminal>;
168
180
  /** Form one decided offer without admitting or reinterpreting it. */
169
181
  export declare function prepareProtocolAttempt<Input extends Readonly<{
@@ -3,6 +3,7 @@ import { publicationFailedSchema } from "../git/admission.js";
3
3
  import { extendAdmissionPathsAt, observeContractsForAdmissionAt } from "../git/observe.js";
4
4
  import { appendPrivateStateSeatClose, isPrivateStateSeatContention, mergePrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
5
5
  import { GIT_REF, readRefs } from "../git/repository.js";
6
+ import { contractState } from "../core/facts/observation.js";
6
7
  import { admitDecidedOffer } from "./attempt.js";
7
8
  export const STALE_PRIVATE_STATE_PREPARATION = {
8
9
  kind: "stale",
@@ -26,7 +27,7 @@ export async function runBoundedAttempts(attempts, attempt) {
26
27
  }
27
28
  return { kind: "exhausted" };
28
29
  }
29
- export function contractStateWitness(state) {
30
+ function contractStateWitness(state) {
30
31
  return { head: state.head };
31
32
  }
32
33
  export function sameWorktreeWitness(prepared, fresh) {
@@ -38,17 +39,28 @@ export function sameWorktreeWitness(prepared, fresh) {
38
39
  prepared.dirty === fresh.dirty &&
39
40
  prepared.changeId === fresh.changeId);
40
41
  }
41
- export async function privateStateAssertionsMatch(repository, assertions) {
42
+ async function privateStateAssertionsMatch(repository, assertions) {
42
43
  if (assertions.length === 0)
43
44
  return true;
44
45
  const refs = await readRefs(repository, [GIT_REF, ...assertions.map((assertion) => assertion.ref)]);
45
46
  return assertions.every((assertion) => refs.get(assertion.ref) === assertion.oid);
46
47
  }
47
- export function publicationFailedFromSeatError(error) {
48
+ function publicationFailedFromSeatError(error) {
48
49
  if (isPrivateStateSeatContention(error))
49
50
  return { kind: "publication-failed", diagnostic: error.message };
50
51
  throw error;
51
52
  }
53
+ /**
54
+ * The repeatable outside-custody preamble shared by prepared operations: one non-authoritative
55
+ * observation of the invoked Contract, and the artifacts its fresh state justifies.
56
+ */
57
+ export async function externalPreparation(input, artifacts) {
58
+ const observation = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
59
+ const state = contractState(observation.decision, input.contractId);
60
+ if (state === null)
61
+ return { kind: "unavailable" };
62
+ return { kind: "artifacts", witness: contractStateWitness(state), artifacts: await artifacts(observation, state) };
63
+ }
52
64
  export async function privateStateSeatAttempt(repository, action, wrap) {
53
65
  try {
54
66
  return wrap(await withPrivateStatePublicationSeat(repository, action));
@@ -100,16 +112,14 @@ async function admitDecidedProtocolOffer(admission, primaryContract, seat, decis
100
112
  if (decided.kind === "refused")
101
113
  return decided;
102
114
  return await admitDecidedOffer({
103
- channel: admission.channel,
104
- repository: admission.repository,
115
+ ...admission,
116
+ scope: admission.repository,
117
+ contractId: primaryContract,
105
118
  seat,
106
- decisionObservation: decided.observation,
119
+ observation: decided.observation,
107
120
  attempt: decided.attempt,
108
121
  offer: decided.offer,
109
- primaryContract,
110
- ...(admission.progress === undefined ? {} : { progress: admission.progress }),
111
122
  assertions: decided.assertions,
112
- ...(admission.validateAdmission === undefined ? {} : { validateAdmission: admission.validateAdmission }),
113
123
  });
114
124
  }
115
125
  function protocolAttemptWithSeatClose(outcome) {
@@ -26,10 +26,9 @@ type TaskHolderAdmission<T extends AdmissionOutcome> = Readonly<{
26
26
  taskId: TaskId;
27
27
  diagnostic: string;
28
28
  }>;
29
- export declare function finishTaskHolderAdmission<T extends AdmissionOutcome>(taskId: TaskId, result: T, close: () => void): TaskHolderAdmission<T>;
30
- export declare function claimTaskHolderWithFence<T extends AdmissionOutcome>(repository: GitRepository, taskId: TaskId, action: () => T | Promise<T>): Promise<TaskHolderAdmission<T>>;
29
+ export declare function admitWithTaskHolderFence<T extends AdmissionOutcome>(repository: GitRepository, taskId: TaskId, action: () => T | Promise<T>): Promise<TaskHolderAdmission<T>>;
31
30
  export declare function releaseTaskHolder(channel: GitDecodeChannel, observation: GitDecisionObservation, owner: ContractId): Promise<TreeUpdate | null>;
32
- export type TaskHolderReleasePublication = Readonly<{
31
+ type TaskHolderReleasePublication = Readonly<{
33
32
  kind: "released";
34
33
  }> | Readonly<{
35
34
  kind: "not-held";
@@ -40,7 +39,6 @@ export type TaskHolderReleasePublication = Readonly<{
40
39
  /** Publish the released holder against the same frozen observation that decided the release. */
41
40
  export declare function publishTaskHolderRelease(repository: GitRepository, channel: GitDecodeChannel, observation: GitDecisionObservation, owner: ContractId, seat: PrivateStatePublicationSeat): Promise<TaskHolderReleasePublication>;
42
41
  export declare function readTaskHolderProjectionFromDecision(channel: GitDecodeChannel, observation: GitDecisionObservation): Promise<TaskHolderProjection>;
43
- export declare function observeTaskHolderProjection(repository: GitRepository, channel: GitDecodeChannel): Promise<TaskHolderProjection>;
44
42
  export declare function releaseTaskHolderWithFence<T extends AdmissionOutcome>(repository: GitRepository, channel: GitDecodeChannel, owner: ContractId, action: () => T | Promise<T>): Promise<TaskHolderAdmission<T>>;
45
43
  export declare function readTaskHoldersAt(observation: Pick<GitReadObservation, "snapshot" | "readBlobs">): Promise<readonly TaskHolder[]>;
46
44
  export declare function readTaskHolderProjectionAt(observation: GitReadObservation): Promise<TaskHolderProjection>;
@@ -87,7 +87,7 @@ export function claimTaskHolder(taskId, owner) {
87
87
  function detail(error) {
88
88
  return error instanceof Error ? error.message : String(error);
89
89
  }
90
- export function finishTaskHolderAdmission(taskId, result, close) {
90
+ function finishTaskHolderAdmission(taskId, result, close) {
91
91
  try {
92
92
  close();
93
93
  return { kind: "completed", result };
@@ -98,7 +98,7 @@ export function finishTaskHolderAdmission(taskId, result, close) {
98
98
  return { kind: "accepted-release-failed", result, taskId, diagnostic: detail(error) };
99
99
  }
100
100
  }
101
- async function admitWithTaskHolderFence(repository, taskId, action) {
101
+ export async function admitWithTaskHolderFence(repository, taskId, action) {
102
102
  const held = await acquireTaskSettlementFence(repository, taskId);
103
103
  let result;
104
104
  try {
@@ -115,9 +115,6 @@ async function admitWithTaskHolderFence(repository, taskId, action) {
115
115
  }
116
116
  return finishTaskHolderAdmission(taskId, result, () => held.close());
117
117
  }
118
- export function claimTaskHolderWithFence(repository, taskId, action) {
119
- return admitWithTaskHolderFence(repository, taskId, action);
120
- }
121
118
  export async function releaseTaskHolder(channel, observation, owner) {
122
119
  const current = (await readTaskHolderProjectionFromDecision(channel, observation)).get(owner) ?? null;
123
120
  return current === null || current.disposition !== "held" ? null : update({ ...current, disposition: "released" });
@@ -180,7 +177,7 @@ export async function readTaskHolderProjectionFromDecision(channel, observation)
180
177
  };
181
178
  return projectTaskHolders(await readTaskHoldersAt(read));
182
179
  }
183
- export function observeTaskHolderProjection(repository, channel) {
180
+ function observeTaskHolderProjection(repository, channel) {
184
181
  return withGitTargetedReadObservation(repository, channel, taskHolderObservationSelection(), readTaskHolderProjectionAt);
185
182
  }
186
183
  async function heldTaskForContract(repository, channel, owner) {
@@ -118,6 +118,12 @@ export declare function projectOwnedDetailFacts(board: TaskBoard, id: TaskId): T
118
118
  export declare function projectDetailFacts(board: TaskBoard, id: TaskId, relations: TaskRelationProjection): TaskDetailFacts | null;
119
119
  export declare function projectTaskRow(board: TaskBoard, relations: TaskRelationProjection, task: TaskDocument): TaskRow;
120
120
  export declare function projectRows(board: TaskBoard, relations: TaskRelationProjection, scope: readonly string[] | null, selection: "active" | "closed" | "all"): readonly TaskRow[];
121
+ /**
122
+ * Rows for the identities that created work, grouped by creator. Only documents a
123
+ * requested identity created reach row projection, and each group keeps the
124
+ * established row order.
125
+ */
126
+ export declare function projectCreatedByRows(board: TaskBoard, relations: TaskRelationProjection, createdByIds: readonly string[]): ReadonlyMap<string, readonly TaskRow[]>;
121
127
  export declare function projectBlocked(board: TaskBoard, scope: readonly string[] | null, relations: TaskRelationProjection): readonly BlockedTaskRow[];
122
128
  export declare function projectStatusRows(board: TaskBoard, relations: TaskRelationProjection, scope: readonly string[] | null): ({
123
129
  id: `task/${string}`;
@@ -142,7 +142,36 @@ export function projectRows(board, relations, scope, selection) {
142
142
  .filter((task) => inScope(task, scope))
143
143
  .filter((task) => selection === "all" || (selection === "closed") === terminal(task.state))
144
144
  .map((task) => projectTaskRow(board, relations, task))
145
- .sort((a, b) => a.priority - b.priority || Buffer.compare(Buffer.from(a.id), Buffer.from(b.id)));
145
+ .sort(compareTaskRows);
146
+ }
147
+ /** The established Task row order: priority first, then canonical identity bytes. */
148
+ function compareTaskRows(left, right) {
149
+ return left.priority - right.priority || Buffer.compare(Buffer.from(left.id), Buffer.from(right.id));
150
+ }
151
+ /**
152
+ * Rows for the identities that created work, grouped by creator. Only documents a
153
+ * requested identity created reach row projection, and each group keeps the
154
+ * established row order.
155
+ */
156
+ export function projectCreatedByRows(board, relations, createdByIds) {
157
+ const requested = new Set(createdByIds);
158
+ const attributed = [];
159
+ for (const task of board.tasks.values()) {
160
+ const createdBy = task.createdBy;
161
+ if (createdBy === undefined || !requested.has(createdBy))
162
+ continue;
163
+ attributed.push({ createdBy, row: projectTaskRow(board, relations, task) });
164
+ }
165
+ attributed.sort((left, right) => compareTaskRows(left.row, right.row));
166
+ const grouped = new Map();
167
+ for (const { createdBy, row } of attributed) {
168
+ const rows = grouped.get(createdBy);
169
+ if (rows === undefined)
170
+ grouped.set(createdBy, [row]);
171
+ else
172
+ rows.push(row);
173
+ }
174
+ return grouped;
146
175
  }
147
176
  export function projectBlocked(board, scope, relations) {
148
177
  return projectRows(board, relations, scope, "active").flatMap((row) => {