@astrosheep/square 0.4.7 → 0.4.9

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 (84) hide show
  1. package/dist/card-format.d.ts +2 -0
  2. package/dist/card-format.js +2 -0
  3. package/dist/claude-mcp-context.d.ts +0 -1
  4. package/dist/claude-mcp-context.js +0 -10
  5. package/dist/claude-mod.d.ts +2 -0
  6. package/dist/claude-mod.js +211 -0
  7. package/dist/cli/context.d.ts +1 -1
  8. package/dist/cli/context.js +1 -12
  9. package/dist/cli/express-presentation.js +8 -35
  10. package/dist/cli/json.js +1 -1
  11. package/dist/cli/observation-commands.d.ts +2 -3
  12. package/dist/cli/observation-commands.js +21 -59
  13. package/dist/cli/registry.js +3 -5
  14. package/dist/cli/square-commands.d.ts +1 -2
  15. package/dist/cli/square-commands.js +7 -17
  16. package/dist/decisions.js +15 -20
  17. package/dist/harness-claude.js +3 -3
  18. package/dist/help.js +6 -8
  19. package/dist/mcp.js +1 -1
  20. package/dist/neutral.d.ts +15 -1
  21. package/dist/notifications.js +1 -1
  22. package/dist/operation-presentation.d.ts +17 -15
  23. package/dist/operation-presentation.js +63 -37
  24. package/dist/packages/agent-delivery/src/index.d.ts +4 -9
  25. package/dist/packages/agent-delivery/src/index.js +0 -9
  26. package/dist/packages/agent-delivery/src/local-endpoint.d.ts +2 -12
  27. package/dist/packages/agent-delivery/src/local-endpoint.js +4 -48
  28. package/dist/packages/agent-delivery/src/pi-client.js +0 -2
  29. package/dist/packages/agent-delivery/src/types.d.ts +3 -37
  30. package/dist/plugins/paseo/shared/card-format.d.ts +6 -0
  31. package/dist/plugins/paseo/shared/card-format.js +38 -0
  32. package/dist/plugins/paseo/shared/card-presentation.d.ts +3 -1
  33. package/dist/plugins/paseo/shared/card-presentation.js +3 -1
  34. package/dist/presentation.d.ts +2 -20
  35. package/dist/presentation.js +11 -46
  36. package/dist/sqlite-square.js +5 -6
  37. package/dist/square-facade.d.ts +4 -13
  38. package/dist/square-posting.js +1 -1
  39. package/dist/square-tools.d.ts +0 -11
  40. package/dist/square-tools.js +34 -120
  41. package/dist/square-values.d.ts +1 -1
  42. package/dist/square-values.js +1 -1
  43. package/dist/time.d.ts +1 -0
  44. package/dist/time.js +10 -0
  45. package/dist/views.d.ts +1 -1
  46. package/dist/views.js +2 -2
  47. package/dist/wake-transports.d.ts +1 -1
  48. package/dist/wake-transports.js +1 -1
  49. package/guides/catch-cold-path-optimization.md +1 -1
  50. package/guides/claude-native.md +37 -7
  51. package/guides/delivery-primitives.md +2 -1
  52. package/guides/mcp.md +3 -3
  53. package/guides/pi-native-delivery.md +10 -2
  54. package/guides/pi-tools.md +1 -3
  55. package/guides/row-storage-design.md +1 -1
  56. package/guides/square-api.md +6 -0
  57. package/package.json +1 -1
  58. package/plugins/claude/.claude-plugin/plugin.json +3 -2
  59. package/plugins/claude/README.md +9 -0
  60. package/plugins/claude/hooks/hooks.json +1 -9
  61. package/plugins/claude/hooks/register.js +178 -0
  62. package/plugins/claude/skills/square/SKILL.md +4 -4
  63. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  64. package/plugins/paseo/OVERVIEW.md +1 -1
  65. package/plugins/paseo/README.md +20 -23
  66. package/plugins/paseo/client/markdown.tsx +88 -95
  67. package/plugins/paseo/client/palette.ts +37 -12
  68. package/plugins/paseo/client/square-message.tsx +52 -76
  69. package/plugins/paseo/client/transform.ts +4 -6
  70. package/plugins/paseo/shared/card-format.ts +37 -0
  71. package/plugins/paseo/shared/card-presentation.ts +6 -2
  72. package/plugins/paseo/shared/message.ts +1 -6
  73. package/plugins/pi/square-pi.js +69 -50
  74. package/skills/square/SKILL.md +4 -4
  75. package/dist/claude-boundary-state.d.ts +0 -20
  76. package/dist/claude-boundary-state.js +0 -84
  77. package/dist/claude-hook.d.ts +0 -2
  78. package/dist/claude-hook.js +0 -232
  79. package/dist/packages/agent-delivery/src/claude-auth.d.ts +0 -13
  80. package/dist/packages/agent-delivery/src/claude-auth.js +0 -75
  81. package/dist/packages/agent-delivery/src/claude-native.d.ts +0 -30
  82. package/dist/packages/agent-delivery/src/claude-native.js +0 -75
  83. package/dist/packages/agent-delivery/src/claude.d.ts +0 -5
  84. package/dist/packages/agent-delivery/src/claude.js +0 -66
@@ -5,11 +5,6 @@ export interface OpenCodeTarget {
5
5
  readonly sessionId: string;
6
6
  readonly [targetBrand]: true;
7
7
  }
8
- export interface ClaudeTarget {
9
- readonly harness: 'claude';
10
- readonly sessionId: string;
11
- readonly [targetBrand]: true;
12
- }
13
8
  export interface PiTarget {
14
9
  readonly harness: 'pi';
15
10
  readonly sessionId: string;
@@ -25,7 +20,7 @@ export interface CodexTarget {
25
20
  readonly sessionId: string;
26
21
  readonly [targetBrand]: true;
27
22
  }
28
- export type Target = OpenCodeTarget | ClaudeTarget | PiTarget | PaseoTarget | CodexTarget;
23
+ export type Target = OpenCodeTarget | PiTarget | PaseoTarget | CodexTarget;
29
24
  export type Delivery = 'steer' | 'queue';
30
25
  export interface OpenCodeSendTextOptions {
31
26
  readonly delivery?: Delivery;
@@ -33,12 +28,6 @@ export interface OpenCodeSendTextOptions {
33
28
  readonly timeoutMs?: number;
34
29
  readonly signal?: AbortSignal;
35
30
  }
36
- export interface ClaudeSendTextOptions {
37
- readonly delivery?: 'steer';
38
- readonly inputId?: never;
39
- readonly timeoutMs?: number;
40
- readonly signal?: AbortSignal;
41
- }
42
31
  export interface PiSendTextOptions {
43
32
  readonly delivery?: Delivery;
44
33
  readonly inputId?: never;
@@ -58,7 +47,7 @@ export interface CodexSendTextOptions {
58
47
  readonly timeoutMs?: number;
59
48
  readonly signal?: AbortSignal;
60
49
  }
61
- export type SendTextOptions = OpenCodeSendTextOptions | ClaudeSendTextOptions | PiSendTextOptions | PaseoSendTextOptions | CodexSendTextOptions;
50
+ export type SendTextOptions = OpenCodeSendTextOptions | PiSendTextOptions | PaseoSendTextOptions | CodexSendTextOptions;
62
51
  export interface OpenCodeConnectOptions {
63
52
  readonly harness: 'opencode';
64
53
  readonly sessionId: string;
@@ -74,15 +63,6 @@ export interface OpenCodeConnectOptions {
74
63
  readonly timeoutMs?: number;
75
64
  readonly signal?: AbortSignal;
76
65
  }
77
- export interface ClaudeConnectOptions {
78
- readonly harness: 'claude';
79
- readonly sessionId: string;
80
- readonly endpoint: string;
81
- readonly token?: string;
82
- readonly claudeHome?: string;
83
- readonly timeoutMs?: number;
84
- readonly signal?: AbortSignal;
85
- }
86
66
  export interface PiConnectOptions {
87
67
  readonly harness: 'pi';
88
68
  readonly sessionId: string;
@@ -147,20 +127,6 @@ export type OpenCodeDeliveryResult = (OpenCodeAttempt & {
147
127
  readonly state: 'unavailable';
148
128
  readonly code: 'aborted' | 'timeout';
149
129
  });
150
- interface ClaudeAttempt {
151
- readonly harness: 'claude';
152
- readonly sessionId: string;
153
- }
154
- export type ClaudeDeliveryResult = (ClaudeAttempt & {
155
- readonly state: 'written';
156
- readonly messageId: string;
157
- }) | (ClaudeAttempt & {
158
- readonly state: 'unknown';
159
- readonly code: 'timeout' | 'aborted' | 'transport';
160
- }) | (ClaudeAttempt & {
161
- readonly state: 'unavailable';
162
- readonly code: 'aborted' | 'timeout' | 'endpoint_unavailable' | 'authentication_failed';
163
- });
164
130
  interface PiAttempt {
165
131
  readonly harness: 'pi';
166
132
  readonly sessionId: string;
@@ -214,5 +180,5 @@ export type CodexDeliveryResult = (CodexAttempt & {
214
180
  readonly state: 'rejected';
215
181
  readonly code: 'not_found' | 'refused' | 'unsupported_version';
216
182
  });
217
- export type DeliveryResult = OpenCodeDeliveryResult | ClaudeDeliveryResult | PiDeliveryResult | PaseoDeliveryResult | CodexDeliveryResult;
183
+ export type DeliveryResult = OpenCodeDeliveryResult | PiDeliveryResult | PaseoDeliveryResult | CodexDeliveryResult;
218
184
  export {};
@@ -0,0 +1,6 @@
1
+ import type { CardPresentation } from "./card-presentation.ts";
2
+ export declare function reachLabel(reach?: CardPresentation["reach"]): string | undefined;
3
+ /** Calendar days, rather than elapsed hours, keep yesterday correct across DST. */
4
+ export declare function timeLabel(at: number, now?: number, compact?: boolean): string;
5
+ /** Only adjacent references from the same origin can form a range. */
6
+ export declare function cardReferences(items: readonly CardPresentation[], originLabel?: (origin: string) => string): string;
@@ -0,0 +1,38 @@
1
+ export function reachLabel(reach) {
2
+ return reach === "mention" ? "@you" : reach === "attention" ? undefined : reach;
3
+ }
4
+ /** Calendar days, rather than elapsed hours, keep yesterday correct across DST. */
5
+ export function timeLabel(at, now = Date.now(), compact = false) {
6
+ const date = new Date(at), today = new Date(now);
7
+ const day = (value) => `${value.getFullYear()}-${value.getMonth()}-${value.getDate()}`;
8
+ const clock = `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
9
+ if (day(date) === day(today))
10
+ return clock;
11
+ const yesterday = new Date(today);
12
+ yesterday.setDate(today.getDate() - 1);
13
+ if (day(date) === day(yesterday))
14
+ return `${compact ? "yest" : "yesterday"} ${clock}`;
15
+ const shortDate = compact
16
+ ? `${String(date.getMonth() + 1).padStart(2, "0")}/${String(date.getDate()).padStart(2, "0")}`
17
+ : date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
18
+ return `${shortDate} ${clock}`;
19
+ }
20
+ /** Only adjacent references from the same origin can form a range. */
21
+ export function cardReferences(items, originLabel = origin => origin) {
22
+ const multipleOrigins = new Set(items.map(item => item.origin)).size > 1;
23
+ const runs = [];
24
+ for (const item of items) {
25
+ if (item.ref === undefined)
26
+ continue;
27
+ const match = /^act\/(\d+)$/.exec(item.ref);
28
+ const index = match ? Number(match[1]) : undefined;
29
+ const previous = runs.at(-1);
30
+ if (index !== undefined && previous?.origin === item.origin && previous.last !== undefined && previous.last + 1 === index) {
31
+ previous.last = index;
32
+ }
33
+ else
34
+ runs.push({ origin: item.origin, ref: item.ref, first: index, last: index });
35
+ }
36
+ return runs.map(run => `${multipleOrigins ? `${originLabel(run.origin)} ` : ""}${run.first !== run.last
37
+ ? `act/${run.first}–${run.last}` : run.ref}`).join(", ");
38
+ }
@@ -4,7 +4,9 @@ export type CardPresentation = {
4
4
  readonly origin: string;
5
5
  readonly author?: string;
6
6
  readonly ref?: string;
7
- readonly badge?: string;
7
+ /** Absent on cards produced before landing time and reach were recorded. */
8
+ readonly at?: number;
9
+ readonly reach?: 'mention' | 'reply' | 'attention' | 'bell';
8
10
  readonly body: string;
9
11
  };
10
12
  export declare function isCardPresentation(value: unknown): value is CardPresentation;
@@ -3,5 +3,7 @@ export function isCardPresentation(value) {
3
3
  return false;
4
4
  const item = value;
5
5
  return item.kind === 'presentation' && typeof item.origin === 'string' && typeof item.body === 'string'
6
- && ['author', 'ref', 'badge'].every(key => item[key] === undefined || typeof item[key] === 'string');
6
+ && (item.at === undefined || (typeof item.at === 'number' && Number.isFinite(item.at)))
7
+ && (item.reach === undefined || ['mention', 'reply', 'attention', 'bell'].includes(item.reach))
8
+ && ['author', 'ref'].every(key => item[key] === undefined || typeof item[key] === 'string');
7
9
  }
@@ -17,26 +17,10 @@ interface ParticipantOutputOptions {
17
17
  name: string;
18
18
  participantCount?: number;
19
19
  }
20
- interface ActivityLimitOptions extends ParticipantOutputOptions {
21
- count?: number;
22
- hardCap?: number;
23
- draftPath?: string;
24
- }
25
- interface ActivityBlockedOptions extends ParticipantOutputOptions {
26
- retryCommand: string;
27
- activitySummaries: readonly UnreadActivitySummary[];
28
- draftPath?: string;
29
- }
30
20
  interface ExpressWaitingOptions {
31
21
  reason: 'throttled';
32
22
  delayMs?: number;
33
23
  }
34
- interface ExpressNoWaitOptions extends ParticipantOutputOptions {
35
- reason: 'throttled';
36
- retryCommand: string;
37
- delayMs?: number;
38
- draftPath?: string;
39
- }
40
24
  interface WatchStatusOptions extends ParticipantOutputOptions {
41
25
  status: WatchStatus;
42
26
  idleMs?: number;
@@ -92,7 +76,7 @@ export declare function renderAmbientEvent(event: HydratedAct | Activity, viewer
92
76
  mention?: string;
93
77
  perception?: Perception;
94
78
  }): string;
95
- export declare function renderActivityBlocked(opts: ActivityBlockedOptions): string;
79
+ export declare function renderUnreadSummary(activitySummaries: readonly UnreadActivitySummary[]): string[];
96
80
  /** An indeterminate or already-committed send only points to inspection, never resend. */
97
81
  export declare function renderActivityUncertain(opts: ParticipantOutputOptions & {
98
82
  draftPath: string;
@@ -100,10 +84,8 @@ export declare function renderActivityUncertain(opts: ParticipantOutputOptions &
100
84
  detail?: string;
101
85
  }): string;
102
86
  export declare function renderExpressWaiting(opts: ExpressWaitingOptions): string;
103
- export declare function renderExpressNoWait(opts: ExpressNoWaitOptions): string;
104
87
  export declare function renderPresenceAnchor(names: readonly string[]): string;
105
- export declare function renderGrepActivitiesView(visible: readonly HydratedAct[], totalMatches: number, noTruncate: boolean | undefined, squarePath: string, pattern: string, fixed?: boolean, perception?: (act: HydratedAct) => Perception, surface?: PresentationSurface): string;
106
- export declare function renderActivityLimit(opts: ActivityLimitOptions): string;
88
+ export declare function renderGrepActivitiesView(visible: readonly HydratedAct[], totalMatches: number, full: boolean | undefined, squarePath: string, pattern: string, fixed?: boolean, perception?: (act: HydratedAct) => Perception, surface?: PresentationSurface): string;
107
89
  export declare function renderWatchAlreadyActive(opts: ParticipantOutputOptions): string;
108
90
  export declare function renderWatchForceTakeover(_opts: ParticipantOutputOptions): string;
109
91
  export declare function renderWatchReplaceMissing(_opts: ParticipantOutputOptions): string;
@@ -214,17 +214,14 @@ export function renderAmbientEvent(event, viewer, opts = {}) {
214
214
  function draftSavedLines(draftPath) {
215
215
  return draftPath === undefined ? [] : [style('dim', `· draft kept: ${draftPath}`)];
216
216
  }
217
- function withDraftInput(command, draftPath) {
218
- return draftPath === undefined ? command : `${command} < ${quoteShell(draftPath)}`;
219
- }
220
- function renderUnreadSummary(activitySummaries) {
217
+ export function renderUnreadSummary(activitySummaries) {
221
218
  const visibleSummaries = activitySummaries.slice(0, MAX_IDENTITY_SET_SIZE);
222
219
  const remainingSummaries = activitySummaries.length - visibleSummaries.length;
223
220
  return [
224
221
  ...visibleSummaries.map((item) => {
225
222
  const compact = (item.preview.body ?? '').replace(/\s+/g, ' ').trim();
226
223
  const bodyPreview = compact === ''
227
- ? { text: item.preview.metadata === undefined ? '(empty)' : '(structured activity)', remaining: 0 }
224
+ ? { text: item.preview.structured ? '(structured activity)' : '(empty)', remaining: 0 }
228
225
  : truncateChars(compact, UNREAD_PREVIEW_CHARS);
229
226
  const bodyText = bodyPreview.remaining === 0 ? bodyPreview.text : `${bodyPreview.text}${style('dim', `… (+${bodyPreview.remaining} chars)`)}`;
230
227
  return style('dim', ` · ${participantIdentity(item.name)} spoke — ${formatAge(item.latestActivityAgeMs)} ago · "${bodyText}"`);
@@ -232,17 +229,6 @@ function renderUnreadSummary(activitySummaries) {
232
229
  ...(remainingSummaries === 0 ? [] : [style('dim', ` · ${remainingSummaries} more participants have unread activity`)]),
233
230
  ];
234
231
  }
235
- export function renderActivityBlocked(opts) {
236
- const readNowCommand = `${participantCommandPrefix(opts.squarePath, opts.name, opts.owner)} perceive`;
237
- return withPathOutput(opts.squarePath, [
238
- `${style('blocked', '✕')} your activity hasn't landed — someone spoke while you were away`,
239
- ...renderUnreadSummary(opts.activitySummaries),
240
- ...draftSavedLines(opts.draftPath),
241
- `${readNowCommand}`,
242
- ' · take it in, then retry:',
243
- withDraftInput(opts.retryCommand, opts.draftPath),
244
- ].join('\n'), { participantCount: opts.participantCount });
245
- }
246
232
  /** An indeterminate or already-committed send only points to inspection, never resend. */
247
233
  export function renderActivityUncertain(opts) {
248
234
  return formatRefusal(opts.squarePath, [
@@ -252,7 +238,7 @@ export function renderActivityUncertain(opts) {
252
238
  ...(opts.detail === undefined ? [] : [` · ${truncateExternalDiagnostic(opts.detail)}`]),
253
239
  ...draftSavedLines(opts.draftPath),
254
240
  ' · the draft is a saved copy; sending it again could repeat your activity',
255
- `${commandPrefix(opts.squarePath)} history${opts.landedId === undefined ? ' --limit 10' : ` --at ${opts.landedId}`} --no-truncate`,
241
+ `${commandPrefix(opts.squarePath)} history${opts.landedId === undefined ? ' --limit 10' : ` --at ${opts.landedId}`} --full`,
256
242
  ], opts);
257
243
  }
258
244
  export function renderExpressWaiting(opts) {
@@ -262,16 +248,6 @@ export function renderExpressWaiting(opts) {
262
248
  ' · --no-wait saves a draft and returns now',
263
249
  ].join('\n');
264
250
  }
265
- export function renderExpressNoWait(opts) {
266
- const retryCommand = opts.retryCommand;
267
- const lines = [
268
- `${style('blocked', '✕')} the square is packed — shoulder to shoulder`,
269
- ` · a lull opens in ${formatDuration(opts.delayMs)}`,
270
- ...draftSavedLines(opts.draftPath),
271
- `${withDraftInput(retryCommand, opts.draftPath)}`,
272
- ];
273
- return withPathOutput(opts.squarePath, lines.join('\n'), { participantCount: opts.participantCount });
274
- }
275
251
  export function renderPresenceAnchor(names) {
276
252
  const visibleNames = names.slice(0, MAX_IDENTITY_SET_SIZE);
277
253
  const participants = visibleNames.map((name) => participantIdentity(name)).join(', ');
@@ -280,7 +256,7 @@ export function renderPresenceAnchor(names) {
280
256
  return style('dim', names.length === 1 ? `→ ${participants} was here` : `→ ${participants}${suffix} were here`);
281
257
  }
282
258
  const GREP_PREVIEW_CHARS = 160;
283
- export function renderGrepActivitiesView(visible, totalMatches, noTruncate, squarePath, pattern, fixed = false, perception, surface = 'cli') {
259
+ export function renderGrepActivitiesView(visible, totalMatches, full, squarePath, pattern, fixed = false, perception, surface = 'cli') {
284
260
  const publicVisible = visible.filter((act) => act.kind === 'say' || act.kind === 'done');
285
261
  if (totalMatches === 0)
286
262
  return `○ no activity matched ${quoteShell(pattern)}`;
@@ -294,7 +270,7 @@ export function renderGrepActivitiesView(visible, totalMatches, noTruncate, squa
294
270
  chunks.push(header);
295
271
  continue;
296
272
  }
297
- if (noTruncate === true) {
273
+ if (full === true) {
298
274
  const body = rawBody.split('\n').map((line) => ` ${line}`).join('\n');
299
275
  chunks.push(`${header}\n${body}`);
300
276
  continue;
@@ -316,34 +292,23 @@ export function renderGrepActivitiesView(visible, totalMatches, noTruncate, squa
316
292
  }
317
293
  if (publicVisible.length === 1) {
318
294
  chunks.push(surface === 'tool'
319
- ? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, ...(truncated ? { noTruncate: true } : {}) })
320
- : `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2${truncated ? ' --no-truncate' : ''}`);
295
+ ? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, ...(truncated ? { full: true } : {}) })
296
+ : `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2${truncated ? ' --full' : ''}`);
321
297
  }
322
298
  else if (truncated && publicVisible.length > 1) {
323
299
  chunks.push(surface === 'tool'
324
- ? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, noTruncate: true })
325
- : `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2 --no-truncate`);
300
+ ? formatToolAction('history', { location: displayPath(squarePath), at: [formatActivityId(publicVisible[0].index)], context: 2, full: true })
301
+ : `${commandPrefix(squarePath)} history --at ${formatActivityId(publicVisible[0].index)} -C 2 --full`);
326
302
  }
327
303
  return chunks.join('\n\n');
328
304
  }
329
- export function renderActivityLimit(opts) {
330
- // The cap wording lives inside the count: the speaker is simply spent.
331
- const spoken = opts.count !== undefined && opts.hardCap !== undefined ? ` — ${opts.count}/${opts.hardCap} spoken` : '';
332
- const doneCommand = `${participantCommandPrefix(opts.squarePath, opts.name, opts.owner)} done`;
333
- return withPathOutput(opts.squarePath, [
334
- `${style('blocked', '✕')} you’ve reached your speaking cap${spoken}`,
335
- ...draftSavedLines(opts.draftPath),
336
- ' · your draft stays unsent; done only steps out',
337
- doneCommand,
338
- ].join('\n'), { participantCount: opts.participantCount });
339
- }
340
305
  export function renderWatchAlreadyActive(opts) {
341
306
  return [
342
307
  `${style('blocked', '✕')} you are already perceiving`,
343
308
  ` · an active perceive is already running for ${participantIdentity(opts.name)}`,
344
309
  ` · ${opts.surface === 'tool' ? 'takeover' : '--takeover'} lets a new perceive take over`,
345
310
  opts.surface === 'tool'
346
- ? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle: 1800000, takeover: true })
311
+ ? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle: '30m', takeover: true })
347
312
  : `${participantCommandPrefix(opts.squarePath, opts.name, opts.owner)} perceive --idle 30m --takeover`,
348
313
  ].join('\n');
349
314
  }
@@ -375,7 +340,7 @@ export function renderWatchStatus(opts) {
375
340
  ? style('dim', `○ dust settles on the flagstones — ${formatDuration(idleMs)} of quiet`)
376
341
  : style('dim', '○ only footsteps in the square — nothing new for you');
377
342
  // The quiet report never repeats the perceive just run.
378
- const hints = [opts.surface === 'tool' ? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle: 1800000 }) : `${prefix} perceive --idle 30m`];
343
+ const hints = [opts.surface === 'tool' ? formatToolAction('perceive', { location: displayPath(opts.squarePath), as: opts.name, idle: '30m' }) : `${prefix} perceive --idle 30m`];
379
344
  return [
380
345
  quiet,
381
346
  ...(opts.showPerceiveHint === false ? [] : hints),
@@ -215,9 +215,9 @@ export class SqliteSquare {
215
215
  ...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...(reply === undefined ? {} : { reply }) });
216
216
  const decision = rejectUnsentActivity(() => {
217
217
  if (proposed.type === 'blocked')
218
- throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { pending: proposed.activitySummaries.reduce((count, summary) => count + summary.count, 0) });
218
+ throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { activitySummaries: proposed.activitySummaries });
219
219
  if (proposed.type === 'capped')
220
- throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`);
220
+ throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`, { spoken: facts.participant(name).sayCount, ...(facts.header().hardCap == null ? {} : { hardCap: facts.header().hardCap }) });
221
221
  if (proposed.type === 'throttled')
222
222
  throw new SquareError('throttled', `${name} is throttled`, { retryAfterMs: proposed.delayMs });
223
223
  if (proposed.type === 'bell_quota')
@@ -515,11 +515,10 @@ export class SqliteSquare {
515
515
  throw new SquareError('invalid_args', 'History order must be asc or desc.');
516
516
  if (query.since !== undefined && !Number.isFinite(query.since))
517
517
  throw new SquareError('invalid_args', 'History timestamp must be finite');
518
- for (const count of [query.contextBefore, query.contextAfter])
519
- if (count !== undefined && (!Number.isSafeInteger(count) || count < 0))
520
- throw new SquareError('invalid_args', 'History context must be a non-negative safe integer');
518
+ if (query.context !== undefined && (!Number.isSafeInteger(query.context) || query.context < 0 || query.context > HISTORY_MAX_LIMIT))
519
+ throw new SquareError('invalid_args', `History context must be a non-negative integer no greater than ${HISTORY_MAX_LIMIT}`);
521
520
  const limit = query.limit === undefined ? (query.at?.length ? null : HISTORY_DEFAULT_LIMIT) : query.limit;
522
- const contextual = !!query.at?.length || query.contextBefore !== undefined || query.contextAfter !== undefined;
521
+ const contextual = !!query.at?.length || query.context !== undefined;
523
522
  const kinds = contextual || query.since !== undefined ? [...NON_READ, 'read'] : NON_READ;
524
523
  return (await this.artifact.read(facts => {
525
524
  const selected = selectHistory(facts, query, limit, kinds, query.observe === true);
@@ -2,7 +2,7 @@ import type { MetadataMatch } from './delivery-deferral.js';
2
2
  export type { MetadataMatch, MetadataScalar } from './delivery-deferral.js';
3
3
  import type { ActivityId, Perception, Reach } from './square-core.js';
4
4
  import type { Owner, HydratedAct, WakeAddress, ActivityMetadata, DirectedNotificationRoute } from './model.js';
5
- import type { OperationControl } from './neutral.js';
5
+ import type { OperationControl, UnreadActivitySummary } from './neutral.js';
6
6
  export interface ActivitySearch {
7
7
  readonly text: string;
8
8
  readonly mode: 'literal' | 'regex';
@@ -16,7 +16,7 @@ export interface HeldSeat {
16
16
  readonly name: string;
17
17
  readonly generation: string;
18
18
  }
19
- export type { PerceiveWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError } from './neutral.js';
19
+ export type { PerceiveWaitStart, OperationProgress, OperationControl, OperationFailureDetail, OperationError, UnreadActivitySummary, SquareErrorFacts } from './neutral.js';
20
20
  export type { ActivityId, Perception, Reach } from './square-core.js';
21
21
  export type { Owner, WakeAddress, ActivityMetadata, JsonValue, DirectedNotificationRoute } from './model.js';
22
22
  /** Indexed archive event, including read bookkeeping and a say's linked content. */
@@ -57,7 +57,7 @@ export interface ExpressResult {
57
57
  readonly activity: Activity;
58
58
  /** The replied-to author was not standing when the reply landed. */
59
59
  readonly replyAuthorNotHere?: string;
60
- /** Body @name tokens with no standing match at landing; never stored on the activity. */
60
+ /** Explicit mentions and body @name tokens with no standing match at landing; never stored on the activity. */
61
61
  readonly unmatchedMentions?: readonly string[];
62
62
  /** Occasional participant-facing nudge; not part of the activity. */
63
63
  readonly hint?: string;
@@ -119,8 +119,7 @@ export interface HistoryQuery extends ActivityQuery, ObservationOptions {
119
119
  readonly order?: 'asc' | 'desc';
120
120
  readonly mention?: string;
121
121
  readonly since?: number;
122
- readonly contextBefore?: number;
123
- readonly contextAfter?: number;
122
+ readonly context?: number;
124
123
  }
125
124
  export interface HistoryResult {
126
125
  readonly activities: readonly Activity[];
@@ -255,14 +254,6 @@ export interface StreamOptions {
255
254
  readonly start?: StreamStart;
256
255
  }
257
256
  export type StreamRecord = Activity | PerceivedActivity;
258
- export interface UnreadActivitySummary {
259
- readonly name: string;
260
- readonly count: number;
261
- readonly latestActivityAgeMs: number;
262
- readonly preview: Extract<ArchiveRecord, {
263
- kind: 'say';
264
- }>;
265
- }
266
257
  export interface EntryPresentation {
267
258
  readonly joinedBefore: boolean;
268
259
  readonly scene: string;
@@ -134,7 +134,7 @@ export async function flushSquarePosts(artifact, location, clock, signal, ledger
134
134
  const result = await ledger.post({ owner: post.owner, key: squarePostKey(location, post), text: rendered.text,
135
135
  ...(post.kind === 'activity' ? { details: { kind: 'presentation', origin: displayAttentionPath(location),
136
136
  ref: formatActivityId(post.index), author: post.from, body: post.body ?? '',
137
- ...(post.route === 'bell' ? { badge: '🔔' } : {}) } } : {}),
137
+ at: post.at, reach: post.route } } : {}),
138
138
  }, signal);
139
139
  posted = ['posted', 'duplicate', 'suppressed'].includes(result.status);
140
140
  knownUnsent = !posted;
@@ -6,16 +6,6 @@ export interface ToolIdentity {
6
6
  readonly wakeAddress?: WakeAddress;
7
7
  }
8
8
  type JsonObject = Record<string, unknown>;
9
- export declare class SquareExpressDrafts {
10
- private readonly drafts;
11
- private purgeExpired;
12
- resolve(args: JsonObject, owner?: Owner): {
13
- args: JsonObject;
14
- token?: string;
15
- };
16
- consume(token?: string): void;
17
- retain(args: JsonObject, owner: Owner | undefined, token: string | undefined, failure: JsonObject, expressAttempted: boolean): string | undefined;
18
- }
19
9
  interface ToolBinding {
20
10
  identity: ToolIdentity;
21
11
  readonly now?: () => number;
@@ -48,6 +38,5 @@ export declare function squareToolFailure(error: unknown, signal?: AbortSignal):
48
38
  export declare function squareToolFailureText(failure: JsonObject, context?: {
49
39
  location?: string;
50
40
  participant?: string;
51
- draft?: string;
52
41
  }): string;
53
42
  export {};