@astrosheep/square 0.3.62 → 0.3.64

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 (168) hide show
  1. package/claude-plugin/.claude-plugin/plugin.json +3 -2
  2. package/claude-plugin/hooks/hooks.json +1 -22
  3. package/claude-plugin/hooks/register.js +119 -0
  4. package/claude-plugin/types.d.ts +7 -0
  5. package/codex-plugin/.codex-plugin/plugin.json +1 -1
  6. package/dist/activity-feed.d.ts +1 -10
  7. package/dist/activity-feed.js +1 -27
  8. package/dist/activity.js +57 -25
  9. package/dist/artifact.js +12 -24
  10. package/dist/attention-presentation.js +1 -0
  11. package/dist/automatic-session.d.ts +3 -1
  12. package/dist/automatic-session.js +21 -34
  13. package/dist/boundary-presentation.js +4 -13
  14. package/dist/canonical-path.d.ts +11 -0
  15. package/dist/canonical-path.js +47 -0
  16. package/dist/catch-decisions.js +14 -10
  17. package/dist/catch-selection.d.ts +6 -0
  18. package/dist/catch-selection.js +14 -0
  19. package/dist/claude-delivery.d.ts +11 -0
  20. package/dist/claude-delivery.js +145 -0
  21. package/dist/claude-mod.d.ts +8 -0
  22. package/dist/claude-mod.js +164 -0
  23. package/dist/cli/context.d.ts +0 -1
  24. package/dist/cli/context.js +9 -21
  25. package/dist/cli/harness-command.d.ts +0 -1
  26. package/dist/cli/harness-command.js +0 -6
  27. package/dist/cli/observation-commands.d.ts +1 -1
  28. package/dist/cli/observation-commands.js +31 -58
  29. package/dist/cli/program.js +20 -18
  30. package/dist/cli/registry.js +2 -2
  31. package/dist/cli/square-commands.js +10 -6
  32. package/dist/codex-hook.js +9 -12
  33. package/dist/codex-queue.d.ts +2 -2
  34. package/dist/codex-queue.js +7 -5
  35. package/dist/decisions.d.ts +2 -6
  36. package/dist/decisions.js +16 -17
  37. package/dist/delivery-health.d.ts +1 -2
  38. package/dist/delivery-health.js +4 -5
  39. package/dist/delivery-operations.d.ts +2 -5
  40. package/dist/delivery-operations.js +77 -214
  41. package/dist/delivery.d.ts +25 -47
  42. package/dist/delivery.js +14 -46
  43. package/dist/diagnostic-redaction.js +7 -9
  44. package/dist/file-changes.d.ts +0 -1
  45. package/dist/file-changes.js +2 -19
  46. package/dist/harness-claude.js +8 -6
  47. package/dist/harness-codex.d.ts +0 -2
  48. package/dist/harness-codex.js +0 -2
  49. package/dist/harness-links.js +13 -17
  50. package/dist/harness.js +3 -7
  51. package/dist/help.js +4 -3
  52. package/dist/host-ledger-file-adapter.d.ts +17 -8
  53. package/dist/host-ledger-file-adapter.js +164 -80
  54. package/dist/host-ledger.d.ts +55 -50
  55. package/dist/inbox.d.ts +0 -3
  56. package/dist/inbox.js +13 -30
  57. package/dist/index.d.ts +1 -1
  58. package/dist/index.js +1 -1
  59. package/dist/list.js +1 -4
  60. package/dist/mcp.js +18 -40
  61. package/dist/mention-parse.js +3 -9
  62. package/dist/model.d.ts +11 -2
  63. package/dist/model.js +1 -1
  64. package/dist/notifications.d.ts +3 -16
  65. package/dist/notifications.js +41 -122
  66. package/dist/opencode-delivery.d.ts +14 -0
  67. package/dist/opencode-delivery.js +171 -0
  68. package/dist/opencode.d.ts +39 -18
  69. package/dist/opencode.js +145 -40
  70. package/dist/packages/agent-delivery/src/claude-auth.d.ts +13 -0
  71. package/dist/packages/agent-delivery/src/claude-auth.js +70 -0
  72. package/dist/packages/agent-delivery/src/claude-native.d.ts +28 -0
  73. package/dist/packages/agent-delivery/src/claude-native.js +65 -0
  74. package/dist/packages/agent-delivery/src/claude.d.ts +14 -0
  75. package/dist/packages/agent-delivery/src/claude.js +66 -0
  76. package/dist/packages/agent-delivery/src/deadline.d.ts +11 -0
  77. package/dist/packages/agent-delivery/src/deadline.js +41 -0
  78. package/dist/packages/agent-delivery/src/errors.d.ts +16 -0
  79. package/dist/packages/agent-delivery/src/errors.js +41 -0
  80. package/dist/packages/agent-delivery/src/guards.d.ts +6 -0
  81. package/dist/packages/agent-delivery/src/guards.js +6 -0
  82. package/dist/packages/agent-delivery/src/index.d.ts +83 -0
  83. package/dist/packages/agent-delivery/src/index.js +110 -0
  84. package/dist/packages/agent-delivery/src/local-endpoint.d.ts +26 -0
  85. package/dist/packages/agent-delivery/src/local-endpoint.js +114 -0
  86. package/dist/packages/agent-delivery/src/opencode-native.d.ts +33 -0
  87. package/dist/packages/agent-delivery/src/opencode-native.js +75 -0
  88. package/dist/packages/agent-delivery/src/opencode.d.ts +14 -0
  89. package/dist/packages/agent-delivery/src/opencode.js +127 -0
  90. package/dist/packages/agent-delivery/src/paseo-native.d.ts +58 -0
  91. package/dist/packages/agent-delivery/src/paseo-native.js +122 -0
  92. package/dist/packages/agent-delivery/src/paseo.d.ts +19 -0
  93. package/dist/packages/agent-delivery/src/paseo.js +106 -0
  94. package/dist/packages/agent-delivery/src/pi-client.d.ts +10 -0
  95. package/dist/packages/agent-delivery/src/pi-client.js +106 -0
  96. package/dist/packages/agent-delivery/src/pi-protocol.d.ts +15 -0
  97. package/dist/packages/agent-delivery/src/pi-protocol.js +50 -0
  98. package/dist/packages/agent-delivery/src/pi-send.d.ts +23 -0
  99. package/dist/packages/agent-delivery/src/pi-send.js +4 -0
  100. package/dist/packages/agent-delivery/src/pi.d.ts +25 -0
  101. package/dist/packages/agent-delivery/src/pi.js +209 -0
  102. package/dist/packages/agent-delivery/src/types.d.ts +120 -0
  103. package/dist/participant-host.js +12 -13
  104. package/dist/participant-identity.d.ts +21 -0
  105. package/dist/participant-identity.js +32 -11
  106. package/dist/paseo-delivery.d.ts +2 -2
  107. package/dist/paseo-delivery.js +35 -27
  108. package/dist/paseo-timeline.js +25 -21
  109. package/dist/paseo.d.ts +2 -2
  110. package/dist/paseo.js +1 -2
  111. package/dist/ports.d.ts +7 -20
  112. package/dist/presentation-operations.js +16 -4
  113. package/dist/presentation.d.ts +19 -10
  114. package/dist/presentation.js +99 -177
  115. package/dist/registry.d.ts +15 -66
  116. package/dist/registry.js +45 -123
  117. package/dist/routes.d.ts +1 -28
  118. package/dist/routes.js +22 -104
  119. package/dist/runtime.d.ts +3 -9
  120. package/dist/runtime.js +14 -67
  121. package/dist/search.d.ts +0 -2
  122. package/dist/search.js +3 -10
  123. package/dist/square-actions.js +48 -72
  124. package/dist/square-application.js +25 -23
  125. package/dist/square-core.d.ts +3 -0
  126. package/dist/square-core.js +22 -5
  127. package/dist/square-facade.d.ts +2 -0
  128. package/dist/square-file-adapter.js +4 -7
  129. package/dist/square-projections.d.ts +40 -45
  130. package/dist/square-projections.js +43 -73
  131. package/dist/square-state.js +1 -4
  132. package/dist/square-storage.d.ts +5 -8
  133. package/dist/square-storage.js +13 -36
  134. package/dist/square-wiring.d.ts +0 -5
  135. package/dist/square-wiring.js +3 -21
  136. package/dist/stream.js +4 -6
  137. package/dist/time.js +2 -7
  138. package/dist/views.d.ts +4 -16
  139. package/dist/views.js +12 -19
  140. package/dist/wake-attempts.d.ts +2 -56
  141. package/dist/wake-attempts.js +15 -110
  142. package/dist/wake-eligibility.d.ts +43 -0
  143. package/dist/wake-eligibility.js +106 -0
  144. package/dist/wake-evidence.d.ts +32 -9
  145. package/dist/wake-evidence.js +29 -24
  146. package/dist/wake-sink.d.ts +13 -9
  147. package/dist/wake-sink.js +35 -54
  148. package/dist/watch.js +13 -21
  149. package/extensions/square-pi.js +10 -5
  150. package/guides/architect.md +77 -77
  151. package/guides/brainstorm.md +197 -197
  152. package/guides/claude-native.md +101 -0
  153. package/guides/host-ledger.md +3 -1
  154. package/guides/participant.md +14 -7
  155. package/guides/pi-native-delivery.md +43 -0
  156. package/package.json +4 -3
  157. package/dist/claude-hook.d.ts +0 -10
  158. package/dist/claude-hook.js +0 -60
  159. package/dist/paseo-connection.d.ts +0 -15
  160. package/dist/paseo-connection.js +0 -141
  161. package/dist/presence.d.ts +0 -2
  162. package/dist/presence.js +0 -24
  163. package/dist/presented.d.ts +0 -2
  164. package/dist/presented.js +0 -10
  165. package/dist/state-cell.d.ts +0 -14
  166. package/dist/wake-port.d.ts +0 -23
  167. package/dist/wake-port.js +0 -27
  168. /package/dist/{state-cell.js → packages/agent-delivery/src/types.js} +0 -0
@@ -1,10 +1,10 @@
1
- import { runClaudeHookAsync } from '../claude-hook.js';
1
+ import { runClaudeMod } from '../claude-mod.js';
2
2
  import { runCodexHookAsync } from '../codex-hook.js';
3
3
  import { sessionInbox } from '../inbox.js';
4
4
  import { sweepPendingNotifications } from '../notifications.js';
5
5
  import { cmdListSquares } from '../list.js';
6
6
  import { nameKey, parseActivityId, sameName } from '../model.js';
7
- import { commandPrefix, participantIdentity, renderGrepActivitiesView, renderEventCli, renderAmbientEvent, renderPresenceAnchor, truncateChars, withPathOutput, quoteShell, } from '../presentation.js';
7
+ import { commandPrefix, participantIdentity, renderGrepActivitiesView, renderEventCli, renderAmbientEventFacts, renderPresenceAnchor, truncateChars, withPathOutput, quoteShell, } from '../presentation.js';
8
8
  import { actId, nowMs } from '../runtime.js';
9
9
  import { style } from '../tty-style.js';
10
10
  import { cmdStream, cmdStreamNdjson } from '../stream.js';
@@ -31,9 +31,6 @@ function inboxDisplay(value) {
31
31
  const truncated = truncateChars(value, INBOX_DISPLAY_CHARS - 1);
32
32
  return truncated.remaining === 0 ? truncated.text : `${truncated.text}…`;
33
33
  }
34
- function inboxLimitCommand(sessionId, json) {
35
- return `square inbox --for-session ${quoteShell(sessionId)} --limit ${INBOX_MAX_LIMIT}${json ? ' --json' : ''}`;
36
- }
37
34
  export const listCommand = {
38
35
  parse: (argv) => argv,
39
36
  async execute(argv, context) {
@@ -305,37 +302,9 @@ function parseHistory(argv, context) {
305
302
  continuationArgs: historyContinuationArgs(argv),
306
303
  };
307
304
  }
308
- function applicationHistoryQuery(options) {
309
- return {
310
- ...(options.participants === undefined || options.participants.length === 0 ? {} : { from: options.participants }),
311
- ...(options.mention === undefined ? {} : { mention: options.mention }),
312
- ...(options.afterIndex === undefined ? {} : { after: actId(options.afterIndex) }),
313
- ...(options.beforeIndex === undefined ? {} : { before: actId(options.beforeIndex) }),
314
- ...(options.grep === undefined ? {} : { grep: options.grep }), ...(options.fixed === undefined ? {} : { fixed: options.fixed }),
315
- order: 'asc',
316
- };
317
- }
318
- function activityAsStored(activity) {
319
- const index = parseActivityId(activity.id);
320
- if (index === undefined)
321
- throw new Error('Application returned a non-canonical activity id');
322
- switch (activity.kind) {
323
- case 'say': return { index, kind: 'say', actor: activity.actor, at: activity.at, body: activity.body ?? '', mentions: activity.mentions, ...(activity.reach === undefined ? {} : { reach: activity.reach }), ...(activity.reply === undefined ? {} : { reply: parseActivityId(activity.reply) ?? undefined }) };
324
- case 'done': return { index, kind: 'done', actor: activity.actor, at: activity.at, body: activity.body ?? '' };
325
- case 'hold': return { index, kind: 'hold', actor: activity.actor, at: activity.at, ...(activity.body === undefined ? {} : { body: activity.body }) };
326
- case 'resume': return { index, kind: 'resume', actor: activity.actor, at: activity.at };
327
- case 'join': return { index, kind: 'join', actor: activity.actor, at: activity.at };
328
- case 'listen': return { index, kind: 'listen', actor: activity.actor, target: activity.target ?? '', at: activity.at };
329
- case 'ignore': return { index, kind: 'ignore', actor: activity.actor, target: activity.target ?? '', at: activity.at };
330
- }
331
- }
332
- function historyContinuationCommand(options, squarePath, direction, index) {
333
- const args = [...(options.continuationArgs ?? []), direction, actId(index), '--limit', String(options.lastN ?? HISTORY_DEFAULT_LIMIT)];
334
- return `${commandPrefix(squarePath)} history ${args.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
335
- }
336
- function boundedHistoryCommand(options, squarePath) {
337
- const args = [...(options.continuationArgs ?? []), '--limit', String(HISTORY_MAX_LIMIT)];
338
- return `${commandPrefix(squarePath)} history ${args.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
305
+ function historyContinuationCommand(options, squarePath, args) {
306
+ const full = [...(options.continuationArgs ?? []), ...args];
307
+ return `${commandPrefix(squarePath)} history ${full.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
339
308
  }
340
309
  /** The archive-visible activity model: content plus the lifecycle moves that keep its story honest — a raised hand pairs with its lowering, and a departure pairs with the return. */
341
310
  function isArchiveActivity(item) {
@@ -377,6 +346,8 @@ function renderHistoryProjection(projection, visible, noTruncate, squarePath) {
377
346
  const shown = visible.filter(isArchiveActivity);
378
347
  const preview = noTruncate || shown.length <= 1 ? undefined : 200;
379
348
  const chunks = [];
349
+ // Presence anchors collect into one closing line instead of interrupting the page.
350
+ const anchored = [];
380
351
  for (const activity of shown) {
381
352
  const options = {
382
353
  preview,
@@ -385,15 +356,18 @@ function renderHistoryProjection(projection, visible, noTruncate, squarePath) {
385
356
  const rendered = renderEventCli(activity, options);
386
357
  if (rendered !== '')
387
358
  chunks.push(rendered);
388
- const participants = projection.presenceAnchors[activity.index];
389
- if (participants !== undefined)
390
- chunks.push(renderPresenceAnchor(participants));
359
+ for (const participant of projection.presenceAnchors[activity.index] ?? []) {
360
+ if (!anchored.some((existing) => sameName(existing, participant)))
361
+ anchored.push(participant);
362
+ }
391
363
  }
392
364
  if (chunks.length === 0)
393
365
  return 'latest\n ○ no public activity in this view';
394
366
  if (preview !== undefined && shown.some((activity) => activity.kind === 'say' && activity.body.length > preview)) {
395
367
  chunks.push(`${commandPrefix(squarePath)} history --no-truncate`);
396
368
  }
369
+ if (anchored.length > 0)
370
+ chunks.push(renderPresenceAnchor(anchored));
397
371
  return chunks.join('\n\n');
398
372
  }
399
373
  export const historyCommand = {
@@ -403,15 +377,14 @@ export const historyCommand = {
403
377
  const square = await openSquare(squarePath, { clock: nowMs, env: context.env, hostLedger: hostLedgerForEnv(context.env) });
404
378
  try {
405
379
  // Keep the projection chronological; pagination chooses a stable edge,
406
- // then --order only changes how the selected page is displayed.
380
+ // then --order only changes how the selected page is displayed. The
381
+ // plain archive hides `read` bookkeeping, while --at/-C/--since windows
382
+ // render the raw activity stream around their coordinates.
407
383
  const projection = await historyPresentation(square, { ...options, order: 'asc' });
408
- const useApplicationHistory = options.atIndexes === undefined && options.beforeContext === undefined && options.afterContext === undefined && options.after === undefined;
409
- const applicationHistory = useApplicationHistory
410
- ? await createSquareApplication({ cwd: context.cwd, env: { ...context.env, SQUARE_PARTICIPANT_NAME: undefined }, squarePath, clock: nowMs }).history(applicationHistoryQuery(options))
411
- : undefined;
412
- let events = applicationHistory === undefined ? [...projection.activities] : applicationHistory.map(activityAsStored);
384
+ const hideReadActs = options.atIndexes === undefined && options.beforeContext === undefined && options.afterContext === undefined && options.after === undefined;
385
+ let events = hideReadActs ? projection.activities.filter((activity) => activity.kind !== 'read') : [...projection.activities];
413
386
  if (options.lastN === null && events.length > HISTORY_MAX_LIMIT) {
414
- fail(`✕ history is capped at ${HISTORY_MAX_LIMIT} activities\n${boundedHistoryCommand(options, squarePath)}`);
387
+ fail(`✕ history is capped at ${HISTORY_MAX_LIMIT} activities\n${historyContinuationCommand(options, squarePath, ['--limit', String(HISTORY_MAX_LIMIT)])}`);
415
388
  }
416
389
  const searching = options.grep !== undefined || options.fixed !== undefined;
417
390
  const totalMatches = searching ? events.length : 0;
@@ -440,7 +413,7 @@ export const historyCommand = {
440
413
  : allPublic.some((item) => item.index < (pageMin ?? Infinity)));
441
414
  const cursorDirection = options.afterIndex !== undefined ? '--after' : '--before';
442
415
  const cursorIndex = cursorDirection === '--after' ? Math.max(...publicEvents.map((item) => item.index)) : Math.min(...publicEvents.map((item) => item.index));
443
- const continuation = hasMore ? `\n\n${historyContinuationCommand(options, squarePath, cursorDirection, cursorIndex)}` : '';
416
+ const continuation = hasMore ? `\n\n${historyContinuationCommand(options, squarePath, [cursorDirection, actId(cursorIndex), '--limit', String(options.lastN ?? HISTORY_DEFAULT_LIMIT)])}` : '';
444
417
  return withPathOutput(squarePath, output + continuation, { participantCount: projection.participantCount });
445
418
  }
446
419
  finally {
@@ -522,10 +495,10 @@ export const statusCommand = {
522
495
  ? '◎'
523
496
  : participant.activityCount > 0 ? '●' : '○';
524
497
  const summary = participant.presence === 'watching'
525
- ? 'catching'
498
+ ? 'is nearby · catching'
526
499
  : participant.activityCount > 0
527
- ? formatRelativeTime(participant.lastActiveAt ?? result.now, result.now)
528
- : `quiet · ${participant.lastActiveAt === undefined ? 'just now' : formatRelativeTime(participant.lastActiveAt, result.now)}`;
500
+ ? `is nearby · ${formatRelativeTime(participant.lastActiveAt ?? result.now, result.now)}`
501
+ : `is nearby · quiet · ${participant.lastActiveAt === undefined ? 'just now' : formatRelativeTime(participant.lastActiveAt, result.now)}`;
529
502
  const showAttention = context.name === undefined || sameName(participant.name, context.name);
530
503
  const attention = !showAttention
531
504
  ? ''
@@ -534,7 +507,7 @@ export const statusCommand = {
534
507
  : participant.unreadActivityCount > 0
535
508
  ? `${participant.unreadActivityCount} change${participant.unreadActivityCount === 1 ? '' : 's'} waiting`
536
509
  : 'caught up';
537
- return ` ${glyph} ${participantIdentity(participant.name)}${style('dim', ` · ${summary}${attention === '' ? '' : ` · ${attention}`}`)}`;
510
+ return ` ${glyph} ${participantIdentity(participant.name)}${style('dim', ` ${summary}${attention === '' ? '' : ` · ${attention}`}`)}`;
538
511
  }));
539
512
  const unshown = Math.max(0, orderedHere.length - STATUS_PARTICIPANT_PREVIEW_LIMIT) + lingering;
540
513
  if (orderedHere.length > STATUS_PARTICIPANT_PREVIEW_LIMIT) {
@@ -554,18 +527,18 @@ export const statusCommand = {
554
527
  ? `· ${result.holdActor === undefined ? 'someone' : participantIdentity(result.holdActor)} raised a hand${result.holdReason ? ` — ${result.holdReason}` : ''}${style('dim', ` · ${holdTime}`)}`
555
528
  : undefined;
556
529
  const visible = result.latestAct === undefined
557
- ? ''
558
- : renderAmbientEvent(result.latestAct, context.name ?? '', {
530
+ ? { text: '', bodyClipped: false }
531
+ : renderAmbientEventFacts(result.latestAct, context.name ?? '', {
559
532
  now: result.now,
560
533
  preview: 200,
561
534
  actNumber: presentation.latestActNumber,
562
535
  squareState: presentation.state,
563
536
  });
564
- const latest = visible === ''
537
+ const latest = visible.text === ''
565
538
  ? [result.latestAct === undefined
566
539
  ? ' ○ no public activity yet'
567
540
  : ' · the latest words were meant for other ears']
568
- : [` ${visible.replace(/\n/g, '\n ')}`];
541
+ : [` ${visible.text.replace(/\n/g, '\n ')}`];
569
542
  // Presence events after the latest public act: otherwise the roster can say someone is
570
543
  // here while the latest line shows them leaving, with nothing to reconcile the two.
571
544
  const latestIndex = result.latestAct?.index ?? -1;
@@ -576,7 +549,7 @@ export const statusCommand = {
576
549
  }
577
550
  if (stepsIn.length > 3)
578
551
  latest.push(style('dim', ` → … ${stepsIn.length - 3} more stepped in`));
579
- if (visible.includes('more chars') && result.latestAct !== undefined) {
552
+ if (visible.bodyClipped && result.latestAct !== undefined) {
580
553
  latest.push(`${commandPrefix(squarePath)} history --at ${actId(result.latestAct)} -C 2 --no-truncate`);
581
554
  }
582
555
  const counts = [
@@ -624,7 +597,7 @@ export const inboxCommand = {
624
597
  }
625
598
  if (!sessionId)
626
599
  fail('inbox requires --for-session <session-id>.');
627
- const retry = inboxLimitCommand(sessionId, json);
600
+ const retry = `square inbox --for-session ${quoteShell(sessionId)} --limit ${INBOX_MAX_LIMIT}${json ? ' --json' : ''}`;
628
601
  if (duplicateLimit)
629
602
  fail(`✕ inbox accepts one --limit\n${retry}`);
630
603
  const limit = hasLimit
@@ -673,5 +646,5 @@ function hookCommand(runHook) {
673
646
  present: (result) => process.stdout.write(result),
674
647
  };
675
648
  }
676
- export const claudeHookCommand = hookCommand(runClaudeHookAsync);
649
+ export const claudeModCommand = hookCommand(runClaudeMod);
677
650
  export const codexHookCommand = hookCommand(runCodexHookAsync);
@@ -1,46 +1,48 @@
1
1
  import { helpRequest } from '../help.js';
2
2
  import { isSquareError } from '../model.js';
3
- import { formatRefusal, joinRecoveryCommand, participantsRecoveryCommand, takeoverRecoveryLines } from '../presentation.js';
3
+ import { commandPrefix, formatRefusal, joinRecoveryCommand, participantsRecoveryCommand, takeoverRecoveryLines } from '../presentation.js';
4
4
  import { inSquareCount, nowMs } from '../runtime.js';
5
5
  import { openSquare } from '../square-file-adapter.js';
6
6
  import { closeOpenSquare } from '../open-square.js';
7
7
  import { defaultContext, parseGlobalArgs } from './context.js';
8
8
  import { executeRegisteredCommand, findCommand } from './registry.js';
9
- async function participantCountFor(squarePath) {
10
- try {
11
- const square = await openSquare(squarePath, { clock: nowMs });
12
- try {
13
- return inSquareCount((await square.artifact.read()).state);
14
- }
15
- finally {
16
- await closeOpenSquare(square);
17
- }
18
- }
19
- catch {
20
- return undefined;
21
- }
22
- }
23
9
  async function handleSquareError(error, squarePath, name) {
24
10
  if (isSquareError(error)) {
25
11
  const existing = [error.message];
26
12
  if (squarePath !== undefined && name !== undefined && error.code === 'already_joined') {
27
13
  existing.push(...takeoverRecoveryLines(squarePath, name));
28
14
  }
29
- else if (squarePath !== undefined && /^✕ .* has never stepped into/.test(error.message)) {
15
+ else if (squarePath !== undefined && error.facts?.reason === 'never_joined') {
30
16
  // The caller's name has never joined this square; only a join admits it.
31
17
  if (name !== undefined)
32
18
  existing.push(joinRecoveryCommand(squarePath, name));
33
19
  else
34
20
  existing.push(participantsRecoveryCommand(squarePath));
35
21
  }
36
- else if (squarePath !== undefined && /^✕ .* is not standing in this square/.test(error.message)) {
22
+ else if (squarePath !== undefined && error.facts?.reason === 'not_standing') {
37
23
  existing.push(participantsRecoveryCommand(squarePath));
38
24
  }
25
+ else if (squarePath !== undefined && error.facts?.reason === 'not_addressed' && typeof error.facts.activityId === 'string') {
26
+ // An anchor only works for an activity the artifact actually holds.
27
+ existing.push(error.facts.activityExists === true
28
+ ? `${commandPrefix(squarePath)} history --at ${error.facts.activityId} -C 2`
29
+ : `${commandPrefix(squarePath)} history --limit 10`);
30
+ }
39
31
  if (squarePath === undefined) {
40
32
  process.stderr.write(`${existing.join('\n')}\n`);
41
33
  }
42
34
  else {
43
- const participantCount = await participantCountFor(squarePath);
35
+ let participantCount;
36
+ try {
37
+ const square = await openSquare(squarePath, { clock: nowMs });
38
+ try {
39
+ participantCount = inSquareCount((await square.artifact.read()).state);
40
+ }
41
+ finally {
42
+ await closeOpenSquare(square);
43
+ }
44
+ }
45
+ catch { /* the header count is best effort */ }
44
46
  process.stderr.write(formatRefusal(squarePath, existing, participantCount === undefined ? {} : { participantCount }));
45
47
  }
46
48
  process.exit(error.code === 'not_found' ? 1 : 2);
@@ -3,7 +3,7 @@ import { doctorCommand } from './maintenance-commands.js';
3
3
  import { harnessCommand, installCommand, uninstallCommand } from './harness-command.js';
4
4
  import { helpCommand, versionCommand } from './meta-commands.js';
5
5
  import { mcpServerCommand } from './mcp-server-command.js';
6
- import { catchCommand, claudeHookCommand, codexHookCommand, historyCommand, inboxCommand, listCommand, participantsCommand, statusCommand, streamCommand, } from './observation-commands.js';
6
+ import { catchCommand, claudeModCommand, codexHookCommand, historyCommand, inboxCommand, listCommand, participantsCommand, statusCommand, streamCommand, } from './observation-commands.js';
7
7
  /** Every public command is an executable adapter, including aliases and utility commands. */
8
8
  export const commandRegistry = [
9
9
  { names: ['build'], spec: buildCommand },
@@ -11,7 +11,7 @@ export const commandRegistry = [
11
11
  { names: ['join'], spec: joinCommand },
12
12
  { names: ['stream'], spec: streamCommand },
13
13
  { names: ['inbox'], spec: inboxCommand },
14
- { names: ['claude-hook'], spec: claudeHookCommand },
14
+ { names: ['claude-mod'], spec: claudeModCommand },
15
15
  { names: ['codex-hook'], spec: codexHookCommand },
16
16
  { names: ['catch'], spec: catchCommand },
17
17
  { names: ['express'], spec: expressCommand },
@@ -1,7 +1,7 @@
1
1
  import { cmdActivity } from '../activity.js';
2
2
  import { scanMentionCandidates } from '../mention-parse.js';
3
3
  import { validateDoneBody } from '../decisions.js';
4
- import { formatHardCap, } from '../model.js';
4
+ import { formatHardCap, sameName, } from '../model.js';
5
5
  import { formatRefusal, participantCommandPrefix, participantIdentity, takeoverRecoveryLines, renderRoomChangeText, renderAmbientEvent, withPathOutput, } from '../presentation.js';
6
6
  import { hostLedgerForEnv, hasAutomaticDeliveryIdentity, } from '../registry.js';
7
7
  import { actId, nowMs } from '../runtime.js';
@@ -59,7 +59,7 @@ export const buildCommand = {
59
59
  await createSquare(squarePath, intent.options, snippet);
60
60
  const cap = intent.options.hardCap === null ? 'unlimited' : formatHardCap(intent.options.hardCap);
61
61
  const throttle = intent.options.throttlePerMinute === undefined ? [] : [` · throttle ${intent.options.throttlePerMinute}/min`];
62
- return withPathOutput(squarePath, ['✓ the square is open', ` · cap ${cap}`, ...throttle, ' · nobody here yet — the first join steps in'].join('\n'), { participantCount: 0 });
62
+ return withPathOutput(squarePath, ['· the square stands ready', ` · cap ${cap}`, ...throttle].join('\n'), { participantCount: 0 });
63
63
  },
64
64
  present: (result) => process.stdout.write(result),
65
65
  };
@@ -130,11 +130,15 @@ export const joinCommand = {
130
130
  : `✓ you banished the original ${participantIdentity(joinedName)} — the name is yours`;
131
131
  const isRejoin = joinKind !== 'joined';
132
132
  const reconnect = joinKind === 'reconnected';
133
+ // The long scene belongs to a name's first join here; a return reads its own line.
134
+ const joinedBefore = after.state.acts.filter((act) => act.kind === 'join' && sameName(act.actor, joinedName)).length > 1;
135
+ const rejoinScene = '*the flagstones are where you left them. so is your shadow.*';
136
+ const entryScene = joinKind !== 'joined' ? '' : joinedBefore ? rejoinScene : scene;
133
137
  const output = [
134
138
  entryLine,
135
139
  '',
136
140
  "· carved into the fountain's edge: every word here lands on a real ear — speak when someone needs it.",
137
- ...(reconnect || scene === '' ? [] : ['', scene]),
141
+ ...(reconnect || entryScene === '' ? [] : ['', entryScene]),
138
142
  ...(isRejoin || contextText === '' ? [] : ['', style('dim', 'context'), contextText]),
139
143
  ...(isRejoin || activities === '' ? [] : ['', style('dim', 'recent activity'), activities]),
140
144
  ...fallback,
@@ -193,8 +197,8 @@ export const expressCommand = {
193
197
  async execute(intent, context) {
194
198
  const squarePath = requireSquarePath(context);
195
199
  const body = await resolveBody(intent.activity);
196
- if (intent.reach === undefined && !intent.noMention && intent.mentions.length === 0 && scanMentionCandidates(body).length === 0) {
197
- fail('✕ express needs --mention <name>, --no-mention, --bell, or an @name in the body\nsquare express --help');
200
+ if (intent.reach === undefined && !intent.noMention && intent.mentions.length === 0 && intent.reply === undefined && scanMentionCandidates(body).length === 0) {
201
+ fail("✕ express needs --mention <name>, --no-mention, --bell, or an @name in the body\n · --reply <activity-id> also reaches the author it answers\nsquare express --help");
198
202
  }
199
203
  await cmdActivity(squarePath, intent.name, body, (value) => value, {
200
204
  force: intent.force,
@@ -304,7 +308,7 @@ export const doneCommand = {
304
308
  const name = result.activity.actor;
305
309
  const presentation = await openSquare(squarePath, { clock: nowMs, env: context.env, hostLedger: hostLedgerForEnv(context.env) });
306
310
  const participantCount = (await entryPresentation(presentation, name).finally(() => closeOpenSquare(presentation))).participantCount;
307
- return withPathOutput(squarePath, `○ ${participantIdentity(name)} steps out of the square — done · ${result.activity.id} · just now`, { participantCount });
311
+ return withPathOutput(squarePath, `○ you stepped out — your footsteps fade · ${result.activity.id}`, { participantCount });
308
312
  },
309
313
  present: (result) => process.stdout.write(result),
310
314
  };
@@ -11,17 +11,6 @@ const CODEX_HOOK_EVENTS = {
11
11
  Stop: 'Stop',
12
12
  };
13
13
  const defaultTrace = (line) => { process.stderr.write(`${line}\n`); };
14
- /** Per-stage timings, emitted as each stage completes so a killed hook still leaves a trace. */
15
- function stageTracer(trace) {
16
- const startedAt = Date.now();
17
- let mark = startedAt;
18
- return (stage, extra = '') => {
19
- const now = Date.now();
20
- const durationMs = now - mark;
21
- mark = now;
22
- trace(`square-codex-hook: stage=${stage} durationMs=${durationMs} totalMs=${now - startedAt}${extra === '' ? '' : ` ${extra}`}`);
23
- };
24
- }
25
14
  function hookBudgetMs(env) {
26
15
  const configured = Number(env.SQUARE_CODEX_HOOK_BUDGET_MS ?? CODEX_HOOK_BUDGET_MS);
27
16
  return Number.isFinite(configured) && configured > 0 ? configured : CODEX_HOOK_BUDGET_MS;
@@ -34,7 +23,15 @@ export async function codexHookResponse(input, lookup = sessionInbox, env = proc
34
23
  const hookEventName = CODEX_HOOK_EVENTS[input.hook_event_name];
35
24
  if (hookEventName === undefined)
36
25
  return undefined;
37
- const stage = stageTracer(trace);
26
+ // Per-stage timings, emitted as each stage completes so a killed hook still leaves a trace.
27
+ const startedAt = Date.now();
28
+ let mark = startedAt;
29
+ const stage = (name, extra = '') => {
30
+ const now = Date.now();
31
+ const durationMs = now - mark;
32
+ mark = now;
33
+ trace(`square-codex-hook: stage=${name} durationMs=${durationMs} totalMs=${now - startedAt}${extra === '' ? '' : ` ${extra}`}`);
34
+ };
38
35
  const signal = AbortSignal.timeout(hookBudgetMs(env));
39
36
  const sweepDeadline = Date.now() + Math.min(PRIVILEGED_HOOK_BUDGET_MS, hookBudgetMs(env));
40
37
  const cwd = typeof input.cwd === 'string' ? input.cwd : process.cwd();
@@ -1,4 +1,4 @@
1
- import type { WakeAdapter, WakeDispatchResult } from './delivery.js';
1
+ import type { WakeAdapter, WakeAdapterResult } from './delivery.js';
2
2
  import { type WakeRoute } from './model.js';
3
3
  export interface CodexQueueRequest {
4
4
  threadId: string;
@@ -23,6 +23,6 @@ export declare class CodexQueueAdapter implements WakeAdapter {
23
23
  private readonly opts;
24
24
  readonly kind: "codex-queue";
25
25
  constructor(opts?: CodexQueueAdapterOptions);
26
- dispatch(address: Readonly<Record<string, string>>, payload: string, beforeSend: () => Promise<boolean>, timeoutMs?: number): Promise<WakeDispatchResult>;
26
+ dispatch(address: Readonly<Record<string, string>>, payload: string, beforeSend: () => Promise<boolean>, timeoutMs?: number): Promise<WakeAdapterResult>;
27
27
  }
28
28
  export type { WakeRoute };
@@ -38,22 +38,24 @@ export class CodexQueueAdapter {
38
38
  const remainingMs = () => Math.max(0, deadline - Date.now());
39
39
  const threadId = address.threadId?.trim();
40
40
  if (!threadId) {
41
- return { outcome: 'unavailable', signature: 'invalid_address', message: 'Codex route has no thread id.', routeStale: true };
41
+ return { outcome: 'failed', unavailable: true, signature: 'invalid_address', message: 'Codex route has no thread id.', routeStale: true };
42
42
  }
43
43
  const env = this.opts.env ?? process.env;
44
44
  if (!await codexQueueEligible(threadId, env)) {
45
45
  return {
46
- outcome: 'unavailable',
46
+ outcome: 'failed',
47
+ unavailable: true,
47
48
  signature: 'boundary_not_stopped',
48
49
  message: 'The Codex thread has not reached a current Stop boundary.',
49
50
  retainRoute: true,
50
51
  };
51
52
  }
52
53
  if (!(await beforeSend()))
53
- return { outcome: 'cancelled' };
54
+ return { outcome: 'gate-rejected' };
54
55
  if (!await codexQueueEligible(threadId, env)) {
55
56
  return {
56
- outcome: 'unavailable',
57
+ outcome: 'failed',
58
+ unavailable: true,
57
59
  signature: 'boundary_not_stopped',
58
60
  message: 'The Codex thread left its Stop boundary before queueing.',
59
61
  retainRoute: true,
@@ -61,7 +63,7 @@ export class CodexQueueAdapter {
61
63
  }
62
64
  const remaining = remainingMs();
63
65
  if (remaining === 0) {
64
- return { outcome: 'unavailable', signature: 'dispatch_budget_exhausted', message: 'The wake dispatch budget elapsed before queueing.', retainRoute: true };
66
+ return { outcome: 'failed', unavailable: true, signature: 'dispatch_budget_exhausted', message: 'The wake dispatch budget elapsed before queueing.', retainRoute: true };
65
67
  }
66
68
  try {
67
69
  (this.opts.sendQueue ?? sendCodexQueue)({ threadId, message: payload }, { env, timeoutMs: remaining });
@@ -1,5 +1,4 @@
1
1
  import { type ActivitiesOptions, type Act, type StoredAct, type SquareState, type Reach, type HardCap } from './model.js';
2
- import { directedPeerSays, peerRoomChanges } from './activity-feed.js';
3
2
  import { type Perception } from './square-core.js';
4
3
  import { type DeliveryModel } from './delivery.js';
5
4
  export interface UnreadActivitySummary {
@@ -36,14 +35,11 @@ export declare function decideImplicitJoin(squareState: SquareState, name: strin
36
35
  export type ActDecision = {
37
36
  type: 'sent';
38
37
  act: Act;
39
- confirmation: string;
40
- ownActCount: number;
41
- pendingPublic: ReturnType<typeof directedPeerSays>;
42
- pendingRoomChanges: ReturnType<typeof peerRoomChanges>;
38
+ /** The replied-to author was not standing, so the reply landed without reaching them. */
39
+ replyAuthorNotHere?: string;
43
40
  } | {
44
41
  type: 'blocked';
45
42
  activitySummaries: UnreadActivitySummary[];
46
- unreadRoomChanges: ReturnType<typeof peerRoomChanges>;
47
43
  } | {
48
44
  type: 'capped';
49
45
  count: number;
package/dist/decisions.js CHANGED
@@ -2,7 +2,7 @@ import { SquareError, sameName, validateName, } from './model.js';
2
2
  import { participantIdentity } from './participant-identity.js';
3
3
  import { UNREAD_BLOCK_GRACE_MS, actId, actStableIndex, foldedState, freshWatchLease, publicActs, resolveRosterName, rosterNames, THROTTLE_WINDOW_MS, } from './runtime.js';
4
4
  import { actDelta, directedPeerSays } from './activity-feed.js';
5
- import { formatActivityId, isIgnored, isListening, listeningTo, MAX_IDENTITY_SET_SIZE, validate } from './square-core.js';
5
+ import { actorOf, formatActivityId, isIgnored, isListening, listeningTo, MAX_IDENTITY_SET_SIZE, validate } from './square-core.js';
6
6
  import { deriveDeliveryModel } from './delivery.js';
7
7
  import { compileSearchPattern } from './search.js';
8
8
  import { scanMentionCandidates, resolveNameAt } from './mention-parse.js';
@@ -10,13 +10,10 @@ export function resolveKnownName(squareState, name) {
10
10
  validateName(name);
11
11
  const known = resolveRosterName(squareState, name);
12
12
  if (known === undefined) {
13
- throw new SquareError('invalid_args', `✕ ${participantIdentity(name)} has never stepped into this square`);
13
+ throw new SquareError('invalid_args', `✕ ${participantIdentity(name)} has never stepped into this square`, { reason: 'never_joined' });
14
14
  }
15
15
  return known;
16
16
  }
17
- function participantState(state, name) {
18
- return state.participants.find((participant) => sameName(participant.name, name));
19
- }
20
17
  export function decideJoin(squareState, name, now) {
21
18
  validateName(name);
22
19
  const knownName = resolveRosterName(squareState, name);
@@ -38,7 +35,7 @@ export function decideImplicitJoin(squareState, name, now) {
38
35
  const knownName = resolveRosterName(squareState, name);
39
36
  const joinedName = knownName ?? name;
40
37
  if (knownName !== undefined) {
41
- const current = participantState(foldedState(squareState), knownName);
38
+ const current = foldedState(squareState).participants.find((participant) => sameName(participant.name, knownName));
42
39
  return { joinedName, state: current?.joined === true ? 'active' : 'done' };
43
40
  }
44
41
  return {
@@ -116,7 +113,7 @@ export function decideAct(squareState, input) {
116
113
  validateName(requested);
117
114
  const resolved = joinedNames.find((candidate) => sameName(candidate, requested));
118
115
  if (resolved === undefined) {
119
- throw new SquareError('invalid_args', `✕ ${participantIdentity(requested)} is not standing in this square`);
116
+ throw new SquareError('invalid_args', `✕ ${participantIdentity(requested)} is not standing in this square`, { reason: 'not_standing' });
120
117
  }
121
118
  if (!mentionNames.some((existing) => sameName(existing, resolved))) {
122
119
  if (mentionNames.length >= MAX_IDENTITY_SET_SIZE) {
@@ -156,11 +153,11 @@ export function decideAct(squareState, input) {
156
153
  lines.push(`✕ ${notStanding.map((candidate) => participantIdentity(candidate.token)).join(', ')} ${notStanding.length === 1 ? 'is' : 'are'} not standing in this square`);
157
154
  }
158
155
  lines.push(' · wrap literal @text in backticks, or pass --no-mention to land bare');
159
- throw new SquareError('invalid_args', lines.join('\n'));
156
+ throw new SquareError('invalid_args', lines.join('\n'), { reason: 'unmatched_mention' });
160
157
  }
161
158
  }
162
159
  if (reach === 'bell' && mentionNames.length > 0) {
163
- throw new SquareError('invalid_args', 'A bell cannot be combined with a mention — remove --mention or the @name in the body.');
160
+ throw new SquareError('invalid_args', '✕ a bell cannot be combined with a mention — remove --mention or the @name in the body.', { reason: 'bell_mention_conflict' });
164
161
  }
165
162
  const reply = input.reply;
166
163
  if (reply !== undefined) {
@@ -169,7 +166,14 @@ export function decideAct(squareState, input) {
169
166
  throw new SquareError('invalid_args', `Unknown reply activity: ${label}`);
170
167
  }
171
168
  }
172
- const current = participantState(state, name);
169
+ // A non-standing author never rejects the activity: the reply still lands and the
170
+ // speaker is told the notification did not reach them.
171
+ const repliedTo = reply === undefined ? undefined : squareState.acts.find((act) => act.index === reply);
172
+ const repliedToAuthor = repliedTo === undefined ? undefined : actorOf(repliedTo);
173
+ const replyAuthorNotHere = repliedToAuthor === undefined || sameName(repliedToAuthor, name)
174
+ || state.participants.some((participant) => participant.joined && sameName(participant.name, repliedToAuthor))
175
+ ? undefined
176
+ : repliedToAuthor;
173
177
  const result = validate(state, {
174
178
  kind: 'say', actor: name, at: now, body, mentions: mentionNames,
175
179
  ...(reach !== undefined ? { reach } : {}),
@@ -194,15 +198,13 @@ export function decideAct(squareState, input) {
194
198
  const delivery = deriveDeliveryModel(squareState);
195
199
  const delta = actDelta(squareState.acts, delivery.cursorFor(name));
196
200
  const unreadPublic = directedPeerSays(squareState, delta, name, delivery);
197
- const unreadRoomChanges = [];
198
201
  const activitySummaries = unreadActivitySummaries(squareState, name, now);
199
202
  const latestActivityAgeMs = activitySummaries[0]?.latestActivityAgeMs;
200
203
  const hasUnread = unreadPublic.length > 0;
201
204
  const hasFreshUnreadActivity = latestActivityAgeMs !== undefined && latestActivityAgeMs <= UNREAD_BLOCK_GRACE_MS;
202
205
  if (!force && hasUnread && !hasFreshUnreadActivity) {
203
- return { type: 'blocked', activitySummaries, unreadRoomChanges };
206
+ return { type: 'blocked', activitySummaries };
204
207
  }
205
- const ownActCount = (current?.activityCount ?? 0) + 1;
206
208
  return {
207
209
  type: 'sent',
208
210
  act: {
@@ -210,10 +212,7 @@ export function decideAct(squareState, input) {
210
212
  ...(reach !== undefined ? { reach } : {}),
211
213
  ...(reply !== undefined ? { reply } : {}),
212
214
  },
213
- confirmation: `● your activity lands — #${ownActCount}`,
214
- ownActCount,
215
- pendingPublic: unreadPublic,
216
- pendingRoomChanges: unreadRoomChanges,
215
+ ...(replyAuthorNotHere === undefined ? {} : { replyAuthorNotHere }),
217
216
  };
218
217
  }
219
218
  export function validateDoneBody(body) {
@@ -1,6 +1,5 @@
1
1
  import { type DirectedNotificationRoute } from './delivery.js';
2
- import { type WakeAttempt } from './square-projections.js';
3
- import { type WakeReleaseDiagnostic } from './wake-attempts.js';
2
+ import type { WakeAttempt, WakeReleaseDiagnostic } from './wake-evidence.js';
4
3
  export type DeliveryHealthKind = 'awaiting' | 'wake-accepted' | 'wake-unknown' | 'presented-not-delivered' | 'unreachable';
5
4
  export interface DeliveryHealthItem {
6
5
  squarePath: string;
@@ -71,10 +71,6 @@ function displayField(value) {
71
71
  const truncated = truncateChars(value, DISPLAY_FIELD_LIMIT - 1);
72
72
  return truncated.remaining === 0 ? truncated.text : `${truncated.text}…`;
73
73
  }
74
- function formatItem(item) {
75
- const evidence = item.attempt?.signature === undefined ? '' : ` · ${displayField(item.attempt.signature)}`;
76
- return ` · ${formatActivityId(item.actIndex)} → ${displayField(participantIdentity(item.recipient))} from ${displayField(participantIdentity(item.actor))} · ${formatDuration(item.ageMs)}${evidence}`;
77
- }
78
74
  export function renderDeliveryHealth(items, releases = [], now = Date.now()) {
79
75
  const out = items.length === 0 ? ['✓ no pending delivery attention'] : [`· delivery attention · ${items.length} pending`];
80
76
  if (items.length > 0) {
@@ -85,7 +81,10 @@ export function renderDeliveryHealth(items, releases = [], now = Date.now()) {
85
81
  continue;
86
82
  out.push(`${ACTIONABLE.has(kind) ? '✕' : '○'} ${kind}: ${group.length}`);
87
83
  const details = group.slice(0, DETAIL_LIMIT - displayed);
88
- out.push(...details.map(formatItem));
84
+ out.push(...details.map((item) => {
85
+ const evidence = item.attempt?.signature === undefined ? '' : ` · ${displayField(item.attempt.signature)}`;
86
+ return ` · ${formatActivityId(item.actIndex)} → ${displayField(participantIdentity(item.recipient))} from ${displayField(participantIdentity(item.actor))} · ${formatDuration(item.ageMs)}${evidence}`;
87
+ }));
89
88
  displayed += details.length;
90
89
  }
91
90
  if (items.length > DETAIL_LIMIT)
@@ -1,10 +1,7 @@
1
- import { type SquareState } from './model.js';
2
- import type { HostLedgerPort, PresenceRecord, PresentationEvidenceProjection, SquareArtifactPort, DeliverPendingInput, DeliveryResult, ObserveSquareInput, SquareObservation } from './ports.js';
1
+ import type { SquareState } from './model.js';
2
+ import type { HostLedgerPort, SquareArtifactPort, DeliverPendingInput, DeliveryResult } from './ports.js';
3
3
  import { deriveDeliveryModel } from './delivery.js';
4
- import { type WakeAttempt } from './square-projections.js';
5
- export declare function observeSquare(input: ObserveSquareInput): Promise<SquareObservation>;
6
4
  export declare function deliverPending(input: DeliverPendingInput): Promise<DeliveryResult>;
7
- export declare function selectPendingWakeActivities(state: SquareState, routes: readonly PresenceRecord[], attempts: readonly WakeAttempt[], now: number, graceMs: number, limit: number, delivery?: import("./delivery.js").DeliveryModel, presentations?: readonly PresentationEvidenceProjection[]): number[];
8
5
  export declare function sweepPending(input: {
9
6
  readonly artifact: SquareArtifactPort;
10
7
  readonly hostLedger: HostLedgerPort;