@astrosheep/keiyaku 4.6.11 → 4.6.13

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 (138) hide show
  1. package/build/plugins/claude/skills/keiyaku/SKILL.md +3 -1
  2. package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
  3. package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +3 -2
  4. package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +9 -8
  5. package/build/plugins/codex/skills/keiyaku/SKILL.md +3 -1
  6. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
  7. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +3 -2
  8. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +9 -8
  9. package/build/plugins/opencode/skills/keiyaku/SKILL.md +3 -1
  10. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
  11. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +3 -2
  12. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +9 -8
  13. package/build/skills/keiyaku/SKILL.md +3 -1
  14. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  15. package/build/skills/keiyaku-bind/SKILL.md +3 -2
  16. package/build/skills/keiyaku-workflow/SKILL.md +9 -8
  17. package/build/src/akuma/akuma-errors.d.ts +5 -0
  18. package/build/src/akuma/akuma-errors.js +9 -0
  19. package/build/src/akuma/akuma-owner.d.ts +14 -19
  20. package/build/src/akuma/akuma-owner.js +56 -54
  21. package/build/src/akuma/akuma-selection-execution.d.ts +5 -4
  22. package/build/src/akuma/akuma-selection-execution.js +59 -17
  23. package/build/src/akuma/akuma.d.ts +1 -2
  24. package/build/src/akuma/allowed.d.ts +2 -3
  25. package/build/src/akuma/allowed.js +1 -3
  26. package/build/src/akuma/body.js +17 -7
  27. package/build/src/akuma/call-initial-tell.d.ts +18 -0
  28. package/build/src/akuma/call-initial-tell.js +18 -0
  29. package/build/src/akuma/call-request.d.ts +20 -4
  30. package/build/src/akuma/heart/facts.d.ts +13 -0
  31. package/build/src/akuma/heart/facts.js +6 -0
  32. package/build/src/akuma/heart/index.d.ts +29 -14
  33. package/build/src/akuma/heart/index.js +75 -29
  34. package/build/src/akuma/heart/rows.d.ts +9 -2
  35. package/build/src/akuma/heart/rows.js +72 -11
  36. package/build/src/akuma/heart/storage.d.ts +2 -8
  37. package/build/src/akuma/heart/storage.js +13 -13
  38. package/build/src/akuma/heart/tells.d.ts +3 -1
  39. package/build/src/akuma/heart/tells.js +18 -2
  40. package/build/src/akuma/provider.d.ts +2 -4
  41. package/build/src/akuma/provider.js +29 -6
  42. package/build/src/akuma/providers/acp/core.js +23 -21
  43. package/build/src/akuma/providers/claude/index.js +0 -8
  44. package/build/src/akuma/providers/codex-app-server/index.js +9 -8
  45. package/build/src/akuma/providers/execution-environment.d.ts +1 -1
  46. package/build/src/akuma/providers/execution-environment.js +1 -0
  47. package/build/src/akuma/providers/opencode-sdk/events.js +111 -81
  48. package/build/src/akuma/providers/opencode-sdk/index.js +179 -150
  49. package/build/src/akuma/providers/opencode-sdk/native-http.js +7 -3
  50. package/build/src/akuma/providers/opencode-sdk/session.d.ts +5 -3
  51. package/build/src/akuma/providers/opencode-sdk/session.js +32 -27
  52. package/build/src/akuma/providers/paseo/index.js +0 -2
  53. package/build/src/akuma/providers/pi/index.js +23 -20
  54. package/build/src/akuma/selection-observation.d.ts +78 -9
  55. package/build/src/akuma/selection-owner-port.d.ts +2 -1
  56. package/build/src/akuma/selection-owner-port.js +6 -1
  57. package/build/src/akuma/selection-request.d.ts +1 -1
  58. package/build/src/akuma/selection-request.js +8 -3
  59. package/build/src/akuma/turn-drive.js +79 -48
  60. package/build/src/akuma-body.js +5 -3
  61. package/build/src/cli/commands/akuma-grammar.js +2 -2
  62. package/build/src/cli/commands/akuma.js +24 -16
  63. package/build/src/cli/commands/contract-grammar.d.ts +3 -7
  64. package/build/src/cli/commands/contract-grammar.js +12 -10
  65. package/build/src/cli/commands/contract-help.d.ts +3 -13
  66. package/build/src/cli/commands/contract-help.js +7 -16
  67. package/build/src/cli/commands/contract.js +19 -35
  68. package/build/src/cli/commands/debt.js +30 -29
  69. package/build/src/cli/parse.js +0 -1
  70. package/build/src/cli/render/akuma-activity.d.ts +36 -9
  71. package/build/src/cli/render/akuma-activity.js +142 -65
  72. package/build/src/cli/render/akuma.d.ts +6 -0
  73. package/build/src/cli/render/akuma.js +67 -24
  74. package/build/src/cli/render/catalog.js +0 -1
  75. package/build/src/cli/render/contract-observation.d.ts +16 -3
  76. package/build/src/cli/render/contract-observation.js +3 -0
  77. package/build/src/cli/render/contract.d.ts +2 -2
  78. package/build/src/cli/render/contract.js +4 -4
  79. package/build/src/cli/render/delivery-preview.d.ts +7 -0
  80. package/build/src/cli/render/{audit.js → delivery-preview.js} +29 -27
  81. package/build/src/cli/render/kanshi-akuma.d.ts +3 -1
  82. package/build/src/cli/render/kanshi-akuma.js +23 -8
  83. package/build/src/cli/render/kanshi.js +4 -1
  84. package/build/src/cli/render/receipt.js +3 -3
  85. package/build/src/cli/render/refusal.js +2 -2
  86. package/build/src/cli/render/terminal.d.ts +0 -1
  87. package/build/src/cli/render/terminal.js +1 -1
  88. package/build/src/cli/square-identity.d.ts +15 -0
  89. package/build/src/cli/square-identity.js +180 -0
  90. package/build/src/contract-worktree.js +1 -1
  91. package/build/src/core/verbs/placement.d.ts +2 -1
  92. package/build/src/core/verbs/placement.js +1 -1
  93. package/build/src/debt/context.d.ts +0 -5
  94. package/build/src/debt/context.js +32 -44
  95. package/build/src/git/process.d.ts +1 -0
  96. package/build/src/git/process.js +18 -1
  97. package/build/src/git/read-observation.js +2 -1
  98. package/build/src/git/scratch.d.ts +5 -1
  99. package/build/src/git/scratch.js +41 -12
  100. package/build/src/git/target-placement.d.ts +22 -4
  101. package/build/src/git/target-placement.js +44 -20
  102. package/build/src/index.d.ts +2 -2
  103. package/build/src/kanshi/read.js +187 -105
  104. package/build/src/kanshi/report.d.ts +5 -0
  105. package/build/src/library/address.d.ts +18 -4
  106. package/build/src/library/address.js +27 -6
  107. package/build/src/library/contract-address.d.ts +6 -0
  108. package/build/src/library/contract-address.js +12 -1
  109. package/build/src/library/contract-execution.d.ts +2 -2
  110. package/build/src/library/contract-execution.js +13 -17
  111. package/build/src/library/contract-operations.d.ts +59 -94
  112. package/build/src/library/contract-operations.js +23 -19
  113. package/build/src/library/contract-outcomes.d.ts +3 -3
  114. package/build/src/library/contract-settings.d.ts +1 -0
  115. package/build/src/library/contract-settings.js +1 -1
  116. package/build/src/library/invocation.d.ts +2 -2
  117. package/build/src/library/invocation.js +1 -1
  118. package/build/src/library/keiyaku.d.ts +2 -2
  119. package/build/src/library/keiyaku.js +2 -2
  120. package/build/src/library/outcome.d.ts +148 -268
  121. package/build/src/library/outcome.js +4 -8
  122. package/build/src/library/refusal.d.ts +2 -2
  123. package/build/src/library/refusal.js +2 -2
  124. package/build/src/plugin/runtime.js +15 -19
  125. package/build/src/protocol/{audit.d.ts → delivery-preview.d.ts} +62 -97
  126. package/build/src/protocol/delivery-preview.js +167 -0
  127. package/build/src/protocol/progress.d.ts +1 -1
  128. package/build/src/runtime/proc/run.js +22 -4
  129. package/build/src/runtime/proc/windows-launch.exe +0 -0
  130. package/build/src/verification/execution.d.ts +1 -1
  131. package/build/src/verification/execution.js +5 -3
  132. package/package.json +5 -2
  133. package/skills/keiyaku/SKILL.md +3 -1
  134. package/skills/keiyaku-babysit/SKILL.md +1 -1
  135. package/skills/keiyaku-bind/SKILL.md +3 -2
  136. package/skills/keiyaku-workflow/SKILL.md +9 -8
  137. package/build/src/cli/render/audit.d.ts +0 -7
  138. package/build/src/protocol/audit.js +0 -203
@@ -152,18 +152,35 @@ async function readHolders(observation) {
152
152
  return { kind: "failed", failure: { message: diagnostic(error) } };
153
153
  }
154
154
  }
155
- function attachRoster(contracts, akuma) {
155
+ function attachRoster(contracts, akuma, dispatches) {
156
156
  if (contracts.kind !== "present")
157
157
  return contracts;
158
+ if (dispatches.kind === "failed" || akuma.kind === "failed") {
159
+ return {
160
+ kind: "present",
161
+ value: {
162
+ ...contracts.value,
163
+ rows: contracts.value.rows.map((row) => ({ ...row, roster: [], rosterUnavailable: true })),
164
+ },
165
+ };
166
+ }
167
+ if (dispatches.kind === "absent" || akuma.kind === "absent") {
168
+ return {
169
+ kind: "present",
170
+ value: { ...contracts.value, rows: contracts.value.rows.map((row) => ({ ...row, roster: [] })) },
171
+ };
172
+ }
158
173
  const attachments = new Map();
159
- if (akuma.kind === "present") {
160
- for (const row of akuma.value.rows) {
161
- if (row.contract === undefined)
162
- continue;
163
- const current = attachments.get(row.contract.id) ?? [];
164
- current.push({ id: row.id, aliases: row.aliases });
165
- attachments.set(row.contract.id, current);
166
- }
174
+ for (const row of akuma.value.rows) {
175
+ if (row.contract === undefined)
176
+ continue;
177
+ const current = attachments.get(row.contract.id) ?? [];
178
+ current.push({
179
+ id: row.id,
180
+ aliases: row.aliases,
181
+ ...(akuma.value.aliasesUnavailable === true ? { aliasesUnavailable: true } : {}),
182
+ });
183
+ attachments.set(row.contract.id, current);
167
184
  }
168
185
  return {
169
186
  kind: "present",
@@ -173,7 +190,7 @@ function attachRoster(contracts, akuma) {
173
190
  },
174
191
  };
175
192
  }
176
- function decorateContracts(contracts, holders, namespaceDebts) {
193
+ function decorateContracts(contracts, holders, dispatches, namespaceDebts) {
177
194
  if (contracts.kind !== "present")
178
195
  return contracts;
179
196
  return {
@@ -182,22 +199,17 @@ function decorateContracts(contracts, holders, namespaceDebts) {
182
199
  ...contracts.value,
183
200
  rows: contracts.value.rows.map((row) => {
184
201
  const selected = namespaceDebts?.(row.id);
185
- if (holders.kind === "failed") {
186
- return {
187
- ...row,
188
- holder: { kind: "unavailable" },
189
- roster: [],
190
- ...(selected === undefined ? {} : { namespaceDebts: selected }),
191
- };
192
- }
193
202
  const holder = holders.kind === "present" ? holders.value.get(row.id) : undefined;
194
203
  return {
195
204
  ...row,
196
205
  roster: [],
206
+ ...(dispatches.kind === "failed" ? { rosterUnavailable: true } : {}),
197
207
  ...(selected === undefined ? {} : { namespaceDebts: selected }),
198
- holder: holder?.disposition === "held"
199
- ? { kind: "held", debtId: holder.debtId }
200
- : { kind: "none" },
208
+ holder: holders.kind === "failed"
209
+ ? { kind: "unavailable" }
210
+ : holder?.disposition === "held"
211
+ ? { kind: "held", debtId: holder.debtId }
212
+ : { kind: "none" },
201
213
  };
202
214
  }),
203
215
  },
@@ -214,18 +226,26 @@ function contractEndpointObserver(contracts) {
214
226
  return "hasMore" in contracts.value ? "unavailable" : "missing";
215
227
  };
216
228
  }
217
- function joinDebts(rows, holders, observeContract) {
229
+ function joinDebts(section, holders, observeContract) {
230
+ if (section.kind !== "present")
231
+ return section;
218
232
  const associations = new Map(holders.kind === "present"
219
233
  ? [...holders.value.values()]
220
234
  .filter((holder) => holder.disposition === "held")
221
235
  .map((holder) => [holder.debtId, holder.contractId])
222
236
  : []);
223
- return rows.map((row) => {
224
- const contractId = associations.get(row.id);
225
- if (contractId === undefined)
226
- return row;
227
- return { ...row, contract: { id: contractId, observed: observeContract(contractId) } };
228
- });
237
+ return {
238
+ kind: "present",
239
+ value: {
240
+ ...section.value,
241
+ rows: section.value.rows.map((row) => {
242
+ if (holders.kind === "failed")
243
+ return { ...row, contractAssociationUnavailable: true };
244
+ const id = associations.get(row.id);
245
+ return id === undefined ? row : { ...row, contract: { id, observed: observeContract(id) } };
246
+ }),
247
+ },
248
+ };
229
249
  }
230
250
  /** Attribute a Debt board failure to the malformed document that caused it, when one is known. */
231
251
  function debtFailure(error) {
@@ -257,13 +277,38 @@ function namespaceDebtSection(board, id) {
257
277
  return undefined;
258
278
  return { kind: "present", value: board.observation.selectNamespace(contractNamespace(id)) };
259
279
  }
260
- async function readDebts(path, holders, observeContract) {
261
- if (holders.kind === "failed")
262
- return { kind: "failed", failure: holders.failure };
263
- return observeRecentDebtStatus(path, { limit: 10 }).then((recent) => ({
280
+ function debtRowsFromBoard(path, board) {
281
+ if (path === null || board.kind === "absent")
282
+ return { kind: "absent" };
283
+ if (board.kind === "failed")
284
+ return { kind: "failed", failure: board.failure };
285
+ const recent = board.observation.selectRecentStatus(10);
286
+ return {
264
287
  kind: "present",
265
- value: { root: path, hasMore: recent.hasMore, rows: joinDebts(recent.rows, holders, observeContract) },
266
- }), (error) => ({ kind: "failed", failure: debtFailure(error) }));
288
+ value: {
289
+ root: path,
290
+ hasMore: recent.hasMore,
291
+ rows: recent.rows.map((row) => {
292
+ const copy = { ...row };
293
+ delete copy.children;
294
+ return copy;
295
+ }),
296
+ },
297
+ };
298
+ }
299
+ async function readDebtRows(path) {
300
+ if (path === null)
301
+ return { kind: "absent" };
302
+ try {
303
+ const recent = await observeRecentDebtStatus(path, { limit: 10 });
304
+ return {
305
+ kind: "present",
306
+ value: { root: path, hasMore: recent.hasMore, rows: recent.rows },
307
+ };
308
+ }
309
+ catch (error) {
310
+ return { kind: "failed", failure: debtFailure(error) };
311
+ }
267
312
  }
268
313
  /**
269
314
  * Placement discharge for the observed roster snapshots: an associated Contract
@@ -285,33 +330,10 @@ async function claimedAssociatedContracts(observation, dispatches) {
285
330
  }));
286
331
  return claimed;
287
332
  }
288
- async function joinAkuma(path, observeContract, isContractClaimed, dispatches, input) {
289
- const { aliases, limit = ROSTER_VISIBLE_ROWS } = input;
290
- if (aliases.kind !== "present")
291
- return aliases;
333
+ async function readAkumaProduct(path, limit = ROSTER_VISIBLE_ROWS) {
292
334
  try {
293
335
  const source = await observeAkumaRoster(path, limit);
294
- const aliasById = new Map();
295
- for (const binding of aliases.value)
296
- aliasById.set(binding.akuId, [...(aliasById.get(binding.akuId) ?? []), binding]);
297
- const dispatchById = new Map(dispatches.map((dispatch) => [dispatch.akuId, dispatch]));
298
- const rows = source.rows.map((row) => {
299
- const dispatch = dispatchById.get(row.id);
300
- return {
301
- ...row,
302
- aliases: (aliasById.get(row.id) ?? []).map((binding) => binding.alias),
303
- ...(dispatch === undefined
304
- ? {}
305
- : {
306
- contract: {
307
- id: dispatch.contractId,
308
- observed: observeContract(dispatch.contractId),
309
- },
310
- }),
311
- };
312
- });
313
- const snapshotRows = rows.slice(0, ROSTER_SNAPSHOT_ROWS);
314
- const snapshots = new Map(await Promise.all(snapshotRows.map(async (row) => {
336
+ const snapshots = new Map(await Promise.all(source.rows.slice(0, ROSTER_SNAPSHOT_ROWS).map(async (row) => {
315
337
  try {
316
338
  return [row.id, await readAkumaTimeline(path, row.id)];
317
339
  }
@@ -323,12 +345,9 @@ async function joinAkuma(path, observeContract, isContractClaimed, dispatches, i
323
345
  kind: "present",
324
346
  value: {
325
347
  ...source,
326
- rows: rows.map((row) => {
348
+ rows: source.rows.map((row) => {
327
349
  const snapshot = snapshots.get(row.id);
328
- if (snapshot === undefined)
329
- return row;
330
- const placed = row.contract !== undefined && isContractClaimed(row.contract.id);
331
- return { ...row, snapshot: placed ? withoutReportedChanges(snapshot) : snapshot };
350
+ return snapshot === undefined ? row : { ...row, snapshot };
332
351
  }),
333
352
  },
334
353
  };
@@ -337,6 +356,43 @@ async function joinAkuma(path, observeContract, isContractClaimed, dispatches, i
337
356
  return { kind: "failed", failure: { message: diagnostic(error) } };
338
357
  }
339
358
  }
359
+ function attachAkumaAssociations(product, aliases, dispatches, observeContract, claimed) {
360
+ if (product.kind !== "present")
361
+ return product;
362
+ const aliasById = new Map();
363
+ if (aliases.kind === "present") {
364
+ for (const binding of aliases.value)
365
+ aliasById.set(binding.akuId, [...(aliasById.get(binding.akuId) ?? []), binding]);
366
+ }
367
+ const dispatchById = new Map(dispatches.kind === "present" ? dispatches.value.map((dispatch) => [dispatch.akuId, dispatch]) : []);
368
+ return {
369
+ kind: "present",
370
+ value: {
371
+ ...product.value,
372
+ ...(aliases.kind === "failed" ? { aliasesUnavailable: true } : {}),
373
+ rows: product.value.rows.map((row) => {
374
+ const dispatch = dispatchById.get(row.id);
375
+ const { snapshot } = row;
376
+ const placed = dispatch !== undefined && claimed.has(dispatch.contractId);
377
+ return {
378
+ ...row,
379
+ aliases: aliases.kind === "present" ? (aliasById.get(row.id) ?? []).map((binding) => binding.alias) : [],
380
+ ...(dispatches.kind === "failed"
381
+ ? { contractAssociationUnavailable: true }
382
+ : dispatch === undefined
383
+ ? {}
384
+ : {
385
+ contract: {
386
+ id: dispatch.contractId,
387
+ observed: observeContract(dispatch.contractId),
388
+ },
389
+ }),
390
+ ...(snapshot === undefined ? {} : { snapshot: placed ? withoutReportedChanges(snapshot) : snapshot }),
391
+ };
392
+ }),
393
+ },
394
+ };
395
+ }
340
396
  async function readAliasBindings(path) {
341
397
  try {
342
398
  return { kind: "present", value: await readAliases(path) };
@@ -356,12 +412,15 @@ async function readDispatches(observation) {
356
412
  async function observeWithoutRepo(world, region, observedAt, branch) {
357
413
  const contracts = { kind: "absent" };
358
414
  const holders = { kind: "absent" };
415
+ const dispatches = { kind: "absent" };
416
+ const [debtRows, aliases, akumaProduct] = world === null
417
+ ? [{ kind: "absent" }, { kind: "absent" }, { kind: "absent" }]
418
+ : await Promise.all([readDebtRows(world), readAliasBindings(world), readAkumaProduct(world)]);
359
419
  const observeContract = contractEndpointObserver(contracts);
360
- const debts = world === null ? { kind: "absent" } : await readDebts(world, holders, observeContract);
361
- const aliases = world === null ? { kind: "absent" } : await readAliasBindings(world);
420
+ const debts = world === null ? debtRows : joinDebts(debtRows, holders, observeContract);
362
421
  const akuma = world === null
363
- ? { kind: "absent" }
364
- : await joinAkuma(world, observeContract, () => false, [], { aliases });
422
+ ? akumaProduct
423
+ : attachAkumaAssociations(akumaProduct, aliases, dispatches, observeContract, new Set());
365
424
  return {
366
425
  report: {
367
426
  root: world,
@@ -375,8 +434,42 @@ async function observeWithoutRepo(world, region, observedAt, branch) {
375
434
  aliases,
376
435
  };
377
436
  }
437
+ /**
438
+ * The repository-observation failure view: a failed Contract and Region beside the
439
+ * independently observed Debt, Alias, and Akuma sections. Debt reports the rows
440
+ * already observed before the failure and performs the existing fallback read only
441
+ * when none were.
442
+ */
443
+ async function observeRepoFailure(input, error, akumaProduct, aliases, observedDebtRows) {
444
+ const { world, region, observedAt, branch } = input;
445
+ const failure = { kind: "failed", failure: { message: diagnostic(error) } };
446
+ const debtRows = observedDebtRows ?? (await readDebtRows(world));
447
+ const observeContract = contractEndpointObserver(failure);
448
+ return {
449
+ report: {
450
+ root: world,
451
+ observedAt,
452
+ branch,
453
+ contracts: failure,
454
+ debts: world === null ? { kind: "absent" } : joinDebts(debtRows, failure, observeContract),
455
+ akuma: world === null
456
+ ? { kind: "absent" }
457
+ : attachAkumaAssociations(akumaProduct, aliases, failure, observeContract, new Set()),
458
+ ...(region === undefined ? {} : { region: failure }),
459
+ },
460
+ aliases,
461
+ };
462
+ }
378
463
  async function observeRepo(input) {
379
464
  const { world, repo, region, contract, observedAt, branch } = input;
465
+ const [initialDebtRows, aliases, akumaProduct] = world === null
466
+ ? [{ kind: "absent" }, { kind: "absent" }, { kind: "absent" }]
467
+ : await Promise.all([
468
+ contract === undefined ? readDebtRows(world) : Promise.resolve(undefined),
469
+ readAliasBindings(world),
470
+ readAkumaProduct(world),
471
+ ]);
472
+ let observedDebtRows = initialDebtRows;
380
473
  try {
381
474
  return await withGitDecodeChannel(repo, (channel) => withGitReadObservation(repo, channel, async (observation) => {
382
475
  const [contractSection, holders, dispatches, regionSection] = await Promise.all([
@@ -389,23 +482,26 @@ async function observeRepo(input) {
389
482
  contractSection.kind === "present" &&
390
483
  contractSection.value.rows.some((row) => row.id === contract);
391
484
  const board = selectedContract ? await readDebtWorld(world) : undefined;
392
- const contracts = decorateContracts(contractSection, holders, selectedContract ? (id) => (id === contract ? namespaceDebtSection(board, id) : undefined) : undefined);
485
+ observedDebtRows =
486
+ world === null
487
+ ? { kind: "absent" }
488
+ : board === undefined
489
+ ? (initialDebtRows ?? (await readDebtRows(world)))
490
+ : debtRowsFromBoard(world, board);
491
+ const contracts = decorateContracts(contractSection, holders, dispatches, board === undefined ? undefined : (id) => (id === contract ? namespaceDebtSection(board, id) : undefined));
393
492
  const observeContract = contractEndpointObserver(contracts);
394
- const aliases = world === null ? { kind: "absent" } : await readAliasBindings(world);
395
- const debts = world === null ? { kind: "absent" } : await readDebts(world, holders, observeContract);
493
+ const debts = world === null ? observedDebtRows : joinDebts(observedDebtRows, holders, observeContract);
396
494
  const claimed = dispatches.kind === "present"
397
495
  ? await claimedAssociatedContracts(observation, dispatches.value)
398
496
  : new Set();
399
497
  const akuma = world === null
400
- ? { kind: "absent" }
401
- : dispatches.kind === "failed"
402
- ? dispatches
403
- : await joinAkuma(world, observeContract, (id) => claimed.has(id), dispatches.value, { aliases });
498
+ ? akumaProduct
499
+ : attachAkumaAssociations(akumaProduct, aliases, dispatches, observeContract, claimed);
404
500
  const assembled = {
405
501
  root: world,
406
502
  observedAt,
407
503
  branch,
408
- contracts: attachRoster(contracts, akuma),
504
+ contracts: attachRoster(contracts, akuma, dispatches),
409
505
  debts,
410
506
  akuma,
411
507
  ...(regionSection === undefined ? {} : { region: regionSection }),
@@ -423,19 +519,7 @@ async function observeRepo(input) {
423
519
  }));
424
520
  }
425
521
  catch (error) {
426
- const failure = { kind: "failed", failure: { message: diagnostic(error) } };
427
- return {
428
- report: {
429
- root: world,
430
- observedAt,
431
- branch,
432
- contracts: failure,
433
- debts: world === null ? { kind: "absent" } : failure,
434
- akuma: world === null ? { kind: "absent" } : failure,
435
- ...(region === undefined ? {} : { region: failure }),
436
- },
437
- aliases: world === null ? { kind: "absent" } : failure,
438
- };
522
+ return await observeRepoFailure(input, error, akumaProduct, aliases, observedDebtRows);
439
523
  }
440
524
  }
441
525
  export async function observeKanshi(input) {
@@ -459,25 +543,23 @@ async function observeAkumaCategory(world, repo, limit, observedAt) {
459
543
  });
460
544
  if (world === null)
461
545
  return report({ kind: "absent" });
462
- const composed = async (observation) => {
463
- const aliases = await readAliasBindings(world);
464
- if (aliases.kind !== "present")
465
- return report(aliases);
466
- if (observation === undefined)
467
- return report(await joinAkuma(world, () => "unavailable", () => false, [], { aliases, limit }));
468
- const dispatches = await readDispatches(observation);
469
- if (dispatches.kind === "failed")
470
- return report(dispatches);
471
- const claimed = await claimedAssociatedContracts(observation, dispatches.value);
472
- return report(await joinAkuma(world, () => "unavailable", (id) => claimed.has(id), dispatches.value, { aliases, limit }));
473
- };
546
+ const aliases = await readAliasBindings(world);
547
+ const product = await readAkumaProduct(world, limit);
548
+ const compose = (dispatches, claimed) => report(attachAkumaAssociations(product, aliases, dispatches, () => "unavailable", claimed));
474
549
  if (repo === undefined)
475
- return await composed();
550
+ return compose({ kind: "absent" }, new Set());
476
551
  try {
477
- return await withGitDecodeChannel(repo, (channel) => withGitReadObservation(repo, channel, composed));
552
+ return await withGitDecodeChannel(repo, (channel) => withGitReadObservation(repo, channel, async (observation) => {
553
+ const dispatches = await readDispatches(observation);
554
+ const claimed = dispatches.kind === "present"
555
+ ? await claimedAssociatedContracts(observation, dispatches.value)
556
+ : new Set();
557
+ return compose(dispatches, claimed);
558
+ }));
478
559
  }
479
560
  catch (error) {
480
- return report({ kind: "failed", failure: { message: diagnostic(error) } });
561
+ const failure = { kind: "failed", failure: { message: diagnostic(error) } };
562
+ return compose(failure, new Set());
481
563
  }
482
564
  }
483
565
  async function observeContractCategory(world, repo, limit, observedAt) {
@@ -493,7 +575,7 @@ async function observeContractCategory(world, repo, limit, observedAt) {
493
575
  readContracts(observation, undefined, limit),
494
576
  readHolders(observation),
495
577
  ]);
496
- return report(decorateContracts(contracts, holders));
578
+ return report(decorateContracts(contracts, holders, { kind: "absent" }));
497
579
  }));
498
580
  }
499
581
  catch (error) {
@@ -33,11 +33,13 @@ export type ContractHolderObservation = Readonly<{
33
33
  export type ContractRosterAttachment = Readonly<{
34
34
  id: string;
35
35
  aliases: readonly AkumaAlias[];
36
+ aliasesUnavailable?: true;
36
37
  }>;
37
38
  export type ContractKanshiRow = ContractBoard["rows"][number] & Readonly<{
38
39
  phase: ContractPhase;
39
40
  holder: ContractHolderObservation;
40
41
  roster: readonly ContractRosterAttachment[];
42
+ rosterUnavailable?: true;
41
43
  namespaceDebts?: Section<readonly DebtRow[]>;
42
44
  issue?: CurrentPhysicalIssue;
43
45
  }>;
@@ -50,6 +52,7 @@ export type DebtKanshiRow = DebtRow & Readonly<{
50
52
  id: string;
51
53
  observed: ContractEndpointObservation;
52
54
  }>;
55
+ contractAssociationUnavailable?: true;
53
56
  blockers?: readonly DebtRef[];
54
57
  }>;
55
58
  export type DebtKanshiWorld = BoundedList<DebtKanshiRow> & Readonly<{
@@ -61,10 +64,12 @@ export type AkumaKanshiRow = (AkumaListRow | UnbornAkumaListRow) & Readonly<{
61
64
  id: string;
62
65
  observed: ContractEndpointObservation;
63
66
  }>;
67
+ contractAssociationUnavailable?: true;
64
68
  snapshot?: ActivitySnapshot;
65
69
  }>;
66
70
  export type AkumaKanshiWorld = Omit<AkumaList, "rows"> & Readonly<{
67
71
  rows: readonly AkumaKanshiRow[];
72
+ aliasesUnavailable?: true;
68
73
  }>;
69
74
  export type KanshiRegionSelection = Readonly<{
70
75
  kind: "declarations";
@@ -3,8 +3,9 @@ import { type AliasBinding } from "../alias/index.js";
3
3
  import { type AkuId } from "../akuma/identity.js";
4
4
  import { contractId } from "../core/facts/types.js";
5
5
  import { type AkumaAlias } from "../identity/selector.js";
6
+ import type { Section } from "../kanshi/index.js";
7
+ import type { ContractRow } from "../protocol/read/status.js";
6
8
  import { type WorldRoot } from "../world.js";
7
- import type { KanshiReport, Section } from "../kanshi/index.js";
8
9
  import { type Repo } from "./repo.js";
9
10
  export type AkumaAddressInput = Readonly<{
10
11
  akuma: string;
@@ -46,11 +47,24 @@ export type NamedAddress = Readonly<{
46
47
  kind: "akuma";
47
48
  id: AkuId;
48
49
  }>;
49
- export type NamedAddressInput = Readonly<{
50
- selector: string;
51
- report: KanshiReport;
50
+ /** The frozen authority a named selector is adjudicated against. */
51
+ export type NamedAddressAuthority = Readonly<{
52
+ contracts: Section<readonly ContractRow[]>;
52
53
  aliases: Section<readonly AliasBinding[]>;
53
54
  }>;
55
+ export type NamedAddressInput = NamedAddressAuthority & Readonly<{
56
+ selector: string;
57
+ }>;
58
+ /**
59
+ * Freeze the one complete Contract candidate observation and the Alias
60
+ * observation a named selector is judged against. The complete candidate set is
61
+ * the Contract owner's board, so display-age bounds never decide membership. An
62
+ * absent Repo is a World without a Contract family, not a failed observation.
63
+ */
64
+ export declare function observeNamedAddress(input: Readonly<{
65
+ world: WorldRoot | null;
66
+ repo: Repo | null;
67
+ }>): Promise<NamedAddressAuthority>;
54
68
  export declare function resolveNamedAddress(input: NamedAddressInput): NamedAddress;
55
69
  type AddressedAkuma = Readonly<{
56
70
  path: WorldRoot;
@@ -7,7 +7,7 @@ import { contractId } from "../core/facts/types.js";
7
7
  import { readDispatches } from "../dispatch/index.js";
8
8
  import { matchesAkumaGlob, parseReadableAkumaAlias, parseAkumaGlob, } from "../identity/selector.js";
9
9
  import { World } from "../world.js";
10
- import { matchContractCandidates } from "./contract-address.js";
10
+ import { matchContractCandidates, readCompleteContractCandidates } from "./contract-address.js";
11
11
  import { requireInput } from "./input.js";
12
12
  import { scopeForRepo } from "./repo.js";
13
13
  export class AkumaAddressError extends Error {
@@ -63,6 +63,27 @@ async function directId(path, selector) {
63
63
  }
64
64
  return parseAddressId(selector).id;
65
65
  }
66
+ async function observe(read) {
67
+ try {
68
+ return { kind: "present", value: await read() };
69
+ }
70
+ catch (error) {
71
+ return { kind: "failed", failure: { message: error instanceof Error ? error.message : String(error) } };
72
+ }
73
+ }
74
+ /**
75
+ * Freeze the one complete Contract candidate observation and the Alias
76
+ * observation a named selector is judged against. The complete candidate set is
77
+ * the Contract owner's board, so display-age bounds never decide membership. An
78
+ * absent Repo is a World without a Contract family, not a failed observation.
79
+ */
80
+ export async function observeNamedAddress(input) {
81
+ const { world, repo } = input;
82
+ return {
83
+ contracts: repo === null ? { kind: "absent" } : await observe(() => readCompleteContractCandidates(repo)),
84
+ aliases: world === null ? { kind: "absent" } : await observe(() => readAliases(world)),
85
+ };
86
+ }
66
87
  export function resolveNamedAddress(input) {
67
88
  const selector = nonblank(input.selector, "selector");
68
89
  if (selector.startsWith("kei/"))
@@ -70,7 +91,9 @@ export function resolveNamedAddress(input) {
70
91
  if (selector.startsWith("aku/"))
71
92
  return { kind: "akuma", id: parseAddressId(selector).id };
72
93
  const alias = parseAddressAlias(selector);
73
- const contractMatches = matchContractCandidates(input.report.contracts.kind === "present" ? input.report.contracts.value.rows : [], { selector: alias });
94
+ const contractMatches = matchContractCandidates(input.contracts.kind === "present" ? input.contracts.value : [], {
95
+ selector: alias,
96
+ });
74
97
  const aliasId = input.aliases.kind === "present"
75
98
  ? (input.aliases.value.find((binding) => binding.alias === alias)?.akuId ?? null)
76
99
  : null;
@@ -84,12 +107,10 @@ export function resolveNamedAddress(input) {
84
107
  return { kind: "contract", id: contractMatches[0].id };
85
108
  if (contractMatches.length > 1)
86
109
  throw new TypeError(`ambiguous Contract selector: ${selector}`);
87
- if (input.report.contracts.kind === "failed") {
110
+ if (input.contracts.kind === "failed")
88
111
  throw new TypeError("cannot resolve a named selector while the Contract world is failed");
89
- }
90
- if (input.aliases.kind === "failed") {
112
+ if (input.aliases.kind === "failed")
91
113
  throw new TypeError("cannot resolve a named selector while Alias authority is failed");
92
- }
93
114
  throw new AkumaAddressError({ kind: "akuma-alias-not-found", alias });
94
115
  }
95
116
  /**
@@ -1,9 +1,15 @@
1
1
  import type { ContractRow } from "../protocol/read/status.js";
2
2
  import type { ContractResolution, ContractResolveInput } from "./contract-types.js";
3
+ import { type Repo } from "./repo.js";
3
4
  /** Pure Contract membership shared with mixed Address; no cross-family judgment. */
4
5
  export declare function matchContractCandidates(rows: readonly ContractRow[], selection: Readonly<{
5
6
  selector: string;
6
7
  }> | Readonly<{
7
8
  cwd: string;
8
9
  }>): readonly ContractRow[];
10
+ /**
11
+ * The complete live Contract candidates a named selection judges membership
12
+ * against. No display bound applies, so age never decides which names exist.
13
+ */
14
+ export declare function readCompleteContractCandidates(repo: Repo): Promise<readonly ContractRow[]>;
9
15
  export declare function resolveContract(input: ContractResolveInput): Promise<ContractResolution>;
@@ -15,6 +15,17 @@ export function matchContractCandidates(rows, selection) {
15
15
  ? `@${row.id.slice("kei/".length)}` === selection.selector
16
16
  : normalize(row.worktreePath) === selection.cwd));
17
17
  }
18
+ /** The complete live Contract board: the Contract owner's own candidate set, never a display catalogue. */
19
+ function completeBoard(scope) {
20
+ return withGitDecodeChannel(scope, (channel) => contractsOperation({ scope, channel }));
21
+ }
22
+ /**
23
+ * The complete live Contract candidates a named selection judges membership
24
+ * against. No display bound applies, so age never decides which names exist.
25
+ */
26
+ export async function readCompleteContractCandidates(repo) {
27
+ return (await completeBoard(scopeForRepo(repo))).rows;
28
+ }
18
29
  export async function resolveContract(input) {
19
30
  const values = requireInput(input, "Keiyaku.with().resolve input", ["repo", "selector", "cwd"]);
20
31
  const scope = scopeForRepo(values.repo);
@@ -54,7 +65,7 @@ export async function resolveContract(input) {
54
65
  };
55
66
  }
56
67
  }
57
- const board = await readContractValue(() => withGitDecodeChannel(scope, (channel) => contractsOperation({ scope, channel })));
68
+ const board = await readContractValue(() => completeBoard(scope));
58
69
  const candidates = matchContractCandidates(board.rows, selector === undefined ? { cwd } : { selector });
59
70
  if (candidates.length === 1)
60
71
  return { kind: "resolved", id: candidates[0].id };
@@ -1,7 +1,7 @@
1
1
  import { type ExecutionContext } from "../akuma/requests.js";
2
2
  import { type ContractId } from "../core/facts/types.js";
3
3
  import { type RepositoryScope } from "../protocol/operations.js";
4
- import type { AbandonOutcome, AmendOutcome, ArcOutcome, AuditInput, AuditOutcome, DeliverOutcome, MutationObservation, ReviewOutcome } from "./contract-outcomes.js";
4
+ import type { AbandonOutcome, AmendOutcome, ArcOutcome, DeliveryPreviewInput, DeliveryPreviewOutcome, DeliverOutcome, MutationObservation, ReviewOutcome } from "./contract-outcomes.js";
5
5
  import { type LocalContractCompositionCapture } from "./contract-settings.js";
6
6
  import type { AbandonInput, AmendInput, ArcInput, DeliverInput, ReviewInput } from "./contract-types.js";
7
7
  export declare class ContractExecution {
@@ -23,7 +23,7 @@ export declare class ContractExecution {
23
23
  review(input: ReviewInput, options?: MutationObservation): Promise<ReviewOutcome>;
24
24
  abandon(input?: AbandonInput): Promise<AbandonOutcome>;
25
25
  arc(input: ArcInput): Promise<ArcOutcome>;
26
- audit(input?: AuditInput, options?: MutationObservation): Promise<AuditOutcome>;
26
+ previewDelivery(input?: DeliveryPreviewInput, options?: MutationObservation): Promise<DeliveryPreviewOutcome>;
27
27
  /** One accumulator before the first admission-capable await, one projector after teardown. */
28
28
  private local;
29
29
  private conclude;