@astrosheep/square 0.4.6 → 0.4.8

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 (101) 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 +2 -2
  8. package/dist/cli/context.js +14 -16
  9. package/dist/cli/express-presentation.js +12 -53
  10. package/dist/cli/json.js +2 -2
  11. package/dist/cli/observation-commands.d.ts +2 -7
  12. package/dist/cli/observation-commands.js +31 -97
  13. package/dist/cli/registry.js +3 -6
  14. package/dist/cli/square-commands.d.ts +2 -3
  15. package/dist/cli/square-commands.js +12 -22
  16. package/dist/decisions.js +5 -4
  17. package/dist/harness-claude.js +3 -3
  18. package/dist/help.js +9 -16
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/mcp.d.ts +1 -0
  22. package/dist/mcp.js +7 -18
  23. package/dist/model.d.ts +1 -1
  24. package/dist/neutral.d.ts +15 -3
  25. package/dist/notifications.d.ts +1 -3
  26. package/dist/notifications.js +21 -23
  27. package/dist/operation-control.d.ts +0 -1
  28. package/dist/operation-control.js +0 -11
  29. package/dist/operation-presentation.d.ts +28 -21
  30. package/dist/operation-presentation.js +90 -87
  31. package/dist/packages/agent-delivery/src/index.d.ts +4 -9
  32. package/dist/packages/agent-delivery/src/index.js +0 -9
  33. package/dist/packages/agent-delivery/src/local-endpoint.d.ts +2 -12
  34. package/dist/packages/agent-delivery/src/local-endpoint.js +4 -48
  35. package/dist/packages/agent-delivery/src/pi-client.js +0 -2
  36. package/dist/packages/agent-delivery/src/types.d.ts +3 -37
  37. package/dist/participant-identity.d.ts +0 -2
  38. package/dist/participant-identity.js +0 -13
  39. package/dist/plugins/paseo/shared/card-format.d.ts +6 -0
  40. package/dist/plugins/paseo/shared/card-format.js +38 -0
  41. package/dist/plugins/paseo/shared/card-presentation.d.ts +3 -1
  42. package/dist/plugins/paseo/shared/card-presentation.js +3 -1
  43. package/dist/presentation.d.ts +5 -22
  44. package/dist/presentation.js +25 -58
  45. package/dist/runtime.d.ts +6 -6
  46. package/dist/runtime.js +5 -15
  47. package/dist/sqlite-square.d.ts +4 -5
  48. package/dist/sqlite-square.js +29 -32
  49. package/dist/square-api.d.ts +1 -1
  50. package/dist/square-api.js +1 -1
  51. package/dist/square-facade.d.ts +5 -14
  52. package/dist/square-location.d.ts +0 -1
  53. package/dist/square-posting.d.ts +4 -4
  54. package/dist/square-posting.js +14 -16
  55. package/dist/square-tools.d.ts +4 -17
  56. package/dist/square-tools.js +52 -119
  57. package/dist/square-values.d.ts +1 -1
  58. package/dist/square-values.js +1 -1
  59. package/dist/time.d.ts +1 -0
  60. package/dist/time.js +10 -0
  61. package/dist/views.d.ts +1 -1
  62. package/dist/views.js +2 -2
  63. package/dist/wake-transports.d.ts +2 -2
  64. package/dist/wake-transports.js +7 -9
  65. package/dist/wakes.js +1 -1
  66. package/examples/symmetric-domains.mjs +1 -2
  67. package/guides/catch-cold-path-optimization.md +1 -1
  68. package/guides/claude-native.md +37 -7
  69. package/guides/delivery-primitives.md +2 -1
  70. package/guides/mcp.md +3 -3
  71. package/guides/pi-native-delivery.md +10 -2
  72. package/guides/pi-tools.md +1 -3
  73. package/guides/row-storage-design.md +1 -1
  74. package/package.json +1 -1
  75. package/plugins/claude/.claude-plugin/plugin.json +3 -2
  76. package/plugins/claude/README.md +9 -0
  77. package/plugins/claude/hooks/hooks.json +1 -9
  78. package/plugins/claude/hooks/register.js +178 -0
  79. package/plugins/claude/skills/square/SKILL.md +2 -2
  80. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  81. package/plugins/paseo/OVERVIEW.md +1 -1
  82. package/plugins/paseo/README.md +20 -23
  83. package/plugins/paseo/client/markdown.tsx +88 -95
  84. package/plugins/paseo/client/palette.ts +37 -12
  85. package/plugins/paseo/client/square-message.tsx +52 -76
  86. package/plugins/paseo/client/transform.ts +4 -6
  87. package/plugins/paseo/shared/card-format.ts +37 -0
  88. package/plugins/paseo/shared/card-presentation.ts +6 -2
  89. package/plugins/paseo/shared/message.ts +1 -6
  90. package/plugins/pi/square-pi.js +76 -60
  91. package/skills/square/SKILL.md +2 -2
  92. package/dist/claude-boundary-state.d.ts +0 -20
  93. package/dist/claude-boundary-state.js +0 -84
  94. package/dist/claude-hook.d.ts +0 -2
  95. package/dist/claude-hook.js +0 -232
  96. package/dist/packages/agent-delivery/src/claude-auth.d.ts +0 -13
  97. package/dist/packages/agent-delivery/src/claude-auth.js +0 -75
  98. package/dist/packages/agent-delivery/src/claude-native.d.ts +0 -30
  99. package/dist/packages/agent-delivery/src/claude-native.js +0 -75
  100. package/dist/packages/agent-delivery/src/claude.d.ts +0 -5
  101. package/dist/packages/agent-delivery/src/claude.js +0 -66
@@ -1,11 +1,11 @@
1
1
  import path from 'node:path';
2
2
  import { once } from 'node:events';
3
- import { runClaudeHook, runClaudeWatch } from '../claude-hook.js';
3
+ import { runClaudeMod } from '../claude-mod.js';
4
4
  import { runCodexHook, runCodexInterrupt } from '../codex-hook.js';
5
5
  import { runCodexWatch } from '../codex-watch.js';
6
6
  import { isSquareError } from '../model.js';
7
7
  import { commandPrefix, truncateChars, withPathOutput, quoteShell, } from '../presentation.js';
8
- import { PARTICIPANTS_DEFAULT_LIMIT, PARTICIPANTS_MAX_LIMIT, renderHistoryResult, renderParticipantsResult, renderStatusResult, renderSquareList, } from '../operation-presentation.js';
8
+ import { historyContinuationCommand, renderHistoryResult, renderStatusResult, renderSquareList, } from '../operation-presentation.js';
9
9
  import { formatTimestamp, parseTimeOrRelative } from '../time.js';
10
10
  import { discover, inbox, formatActivityId, parseActivityId, PERCEIVE_DEFAULT_LIMIT, PERCEIVE_MAX_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from '../square-api.js';
11
11
  import { renderPerceiveOutcome, renderPerceiveProgress } from './perceive-presentation.js';
@@ -134,8 +134,7 @@ export const perceiveCommand = {
134
134
  let mention;
135
135
  let limit;
136
136
  let id;
137
- let replace = false;
138
- let now = false;
137
+ let takeover = false;
139
138
  const participants = [];
140
139
  for (let index = 0; index < argv.length; index++) {
141
140
  if (argv[index] === '--id') {
@@ -162,29 +161,25 @@ export const perceiveCommand = {
162
161
  limit = parseBoundedLimit(argv[index + 1], '--limit', PERCEIVE_MAX_LIMIT, `${commandPrefix(requireSquarePath(context))} perceive --limit ${PERCEIVE_MAX_LIMIT}`);
163
162
  index += 1;
164
163
  }
165
- else if (argv[index] === '--replace')
166
- replace = true;
167
- else if (argv[index] === '--now')
168
- now = true;
164
+ else if (argv[index] === '--takeover')
165
+ takeover = true;
169
166
  else if (argv[index] !== '--json')
170
167
  fail(`✕ perceive does not know ${argv[index]}\nsquare perceive --help`);
171
168
  }
172
169
  if (id !== undefined) {
173
- if (argv.some((flag) => ['--idle', '--from', '--mention', '--limit', '--replace'].includes(flag))) {
174
- fail('✕ --id cannot be combined with --idle, --from, --mention, --limit or --replace\nsquare perceive --help');
170
+ if (argv.some((flag) => ['--idle', '--from', '--mention', '--limit', '--takeover'].includes(flag))) {
171
+ fail('✕ --id cannot be combined with --idle, --from, --mention, --limit or --takeover\nsquare perceive --help');
175
172
  }
176
173
  return { id };
177
174
  }
178
- if (idle !== undefined && now)
179
- fail('perceive accepts --now or --idle, not both.');
180
- if (replace && idle === undefined)
181
- fail('--replace can only be used with --idle.');
175
+ if (takeover && idle === undefined)
176
+ fail('--takeover can only be used with --idle.');
182
177
  return {
183
178
  ...(participants.length > 0 ? { from: participants } : {}),
184
179
  ...(mention === undefined ? {} : { mention }),
185
180
  limit: limit ?? PERCEIVE_DEFAULT_LIMIT,
186
181
  ...(idle === undefined ? {} : { idle }),
187
- ...(replace ? { replace } : {}),
182
+ ...(takeover ? { takeover } : {}),
188
183
  };
189
184
  },
190
185
  async execute(intent, context) {
@@ -244,7 +239,7 @@ function historyContinuationArgs(argv) {
244
239
  continue;
245
240
  }
246
241
  result.push(flag);
247
- if (flag === '--from' || flag === '--since' || flag === '--at' || flag === '-B' || flag === '-A' || flag === '-C' || flag === '--mention' || flag === '--grep' || flag === '--fixed' || flag === '--order' || flag === '--format') {
242
+ if (flag === '--from' || flag === '--since' || flag === '--at' || flag === '-C' || flag === '--mention' || flag === '--search' || flag === '--order' || flag === '--format') {
248
243
  const value = argv[index + 1];
249
244
  if (value !== undefined) {
250
245
  result.push(value);
@@ -261,12 +256,11 @@ function parseHistory(argv, context) {
261
256
  let after;
262
257
  let before;
263
258
  const at = [];
264
- let beforeContext;
265
- let afterContext;
259
+ let historyContext;
266
260
  let mention;
267
- let noTruncate = false;
268
- let grep;
269
- let fixed;
261
+ let full = false;
262
+ let search;
263
+ let regex = false;
270
264
  let order;
271
265
  let format;
272
266
  const participants = [];
@@ -299,32 +293,20 @@ function parseHistory(argv, context) {
299
293
  at.push(...values.map((value) => formatActivityId(parseActRef(value, flag))));
300
294
  index += 1;
301
295
  }
302
- else if (flag === '-B') {
303
- beforeContext = parseNonNegativeInteger(requireValue(argv, index, flag), flag);
304
- index += 1;
305
- }
306
- else if (flag === '-A') {
307
- afterContext = parseNonNegativeInteger(requireValue(argv, index, flag), flag);
308
- index += 1;
309
- }
310
296
  else if (flag === '-C') {
311
- const context = parseNonNegativeInteger(requireValue(argv, index, flag), flag);
312
- beforeContext = context;
313
- afterContext = context;
297
+ historyContext = parseNonNegativeInteger(requireValue(argv, index, flag), flag);
314
298
  index += 1;
315
299
  }
316
- else if (flag === '--no-truncate')
317
- noTruncate = true;
300
+ else if (flag === '--full')
301
+ full = true;
318
302
  else if (flag === '--mention') {
319
303
  mention = requireValue(argv, index, flag);
320
304
  index += 1;
321
305
  }
322
- else if (flag === '--grep') {
323
- grep = requireValue(argv, index, flag);
324
- index += 1;
325
- }
326
- else if (flag === '--fixed') {
327
- fixed = requireValue(argv, index, flag);
306
+ else if (flag === '--regex')
307
+ regex = true;
308
+ else if (flag === '--search') {
309
+ search = requireValue(argv, index, flag);
328
310
  index += 1;
329
311
  }
330
312
  else if (flag === '--order') {
@@ -341,26 +323,20 @@ function parseHistory(argv, context) {
341
323
  else if (flag !== '--json')
342
324
  fail(`✕ history does not know ${flag}\nsquare history --help`);
343
325
  }
344
- if (grep !== undefined && fixed !== undefined)
345
- fail('--grep and --fixed cannot be combined.');
346
- if (grep === '' || fixed === '')
347
- fail('--grep and --fixed require non-empty text.');
326
+ if (search === '')
327
+ fail('--search requires non-empty text.');
348
328
  if (before !== undefined && after !== undefined)
349
329
  fail('--before and --after cannot be combined.');
350
330
  return {
351
331
  query: { limit, from: participants.length === 0 ? undefined : participants, since,
352
332
  cursor: after !== undefined ? { id: after, direction: 'after' } : before === undefined ? undefined : { id: before, direction: 'before' },
353
333
  at: at.length === 0 ? undefined : at,
354
- contextBefore: beforeContext, contextAfter: afterContext, mention, order,
355
- search: grep !== undefined ? { text: grep, mode: 'regex' } : fixed === undefined ? undefined : { text: fixed, mode: 'literal' } },
356
- noTruncate, format,
334
+ context: historyContext, mention, order,
335
+ search: search === undefined ? undefined : { text: search, mode: regex ? 'regex' : 'literal' } },
336
+ full, format,
357
337
  continuationArgs: historyContinuationArgs(argv),
358
338
  };
359
339
  }
360
- function historyContinuationCommand(options, squarePath, args) {
361
- const full = [...(options.continuationArgs ?? []), ...args];
362
- return `${commandPrefix(squarePath)} history ${full.map((arg) => arg.startsWith('-') || /^act\/\d+$/.test(arg) || /^\d+$/.test(arg) ? arg : quoteShell(arg)).join(' ')}`;
363
- }
364
340
  function renderFields(sayNumbers, item, fields) {
365
341
  return fields.map((field) => {
366
342
  switch (field) {
@@ -388,7 +364,7 @@ export const historyCommand = {
388
364
  catch (error) {
389
365
  const bounds = error?.operation?.historyBounds;
390
366
  if (bounds !== undefined)
391
- fail(`✕ history is capped at ${bounds.maxLimit} activities\n${historyContinuationCommand(options, squarePath, ['--limit', String(bounds.maxLimit)])}`);
367
+ fail(`✕ history is capped at ${bounds.maxLimit} activities\n${historyContinuationCommand(squarePath, [...options.continuationArgs, '--limit', String(bounds.maxLimit)])}`);
392
368
  throw error;
393
369
  }
394
370
  if (context.json)
@@ -400,36 +376,12 @@ export const historyCommand = {
400
376
  }
401
377
  return renderHistoryResult(squarePath, outcome, {
402
378
  query: options.query,
403
- noTruncate: options.noTruncate,
379
+ full: options.full,
404
380
  continuationArgs: options.continuationArgs,
405
381
  });
406
382
  },
407
383
  present: (result) => process.stdout.write(result),
408
384
  };
409
- function participantsLimitCommand(squarePath, limit) {
410
- return `${commandPrefix(squarePath)} participants --limit ${limit}`;
411
- }
412
- function parseParticipants(argv, context) {
413
- let limit = PARTICIPANTS_DEFAULT_LIMIT;
414
- for (let index = 0; index < argv.length; index++) {
415
- if (argv[index] === '--json')
416
- continue;
417
- if (argv[index] !== '--limit')
418
- usage(context.command);
419
- limit = parseBoundedLimit(argv[index + 1], '--limit', PARTICIPANTS_MAX_LIMIT, participantsLimitCommand(requireSquarePath(context), PARTICIPANTS_MAX_LIMIT));
420
- index += 1;
421
- }
422
- return { limit };
423
- }
424
- export const participantsCommand = {
425
- parse(argv, context) { return parseParticipants(argv, context); },
426
- async execute(intent, context) {
427
- const squarePath = requireSquarePath(context);
428
- const data = await withSquare(context, (square) => square.participants(context.json ? {} : { observe: true }));
429
- return context.json ? jsonResult(data) : renderParticipantsResult(squarePath, data, intent.limit);
430
- },
431
- present: (result) => process.stdout.write(result),
432
- };
433
385
  export const statusCommand = {
434
386
  parse(argv, context) { if (argv.some((arg) => arg !== '--json'))
435
387
  usage(context.command); return undefined; },
@@ -498,28 +450,10 @@ function hookCommand(runHook) {
498
450
  present: (result) => process.stdout.write(result),
499
451
  };
500
452
  }
501
- export const claudeHookCommand = {
502
- parse(argv, context) { if (argv.length > 0)
503
- usage(context.command); return undefined; },
504
- execute: async () => {
505
- try {
506
- return await runClaudeHook(await readStdin(), process.env, text => new Promise((resolve, reject) => {
507
- process.stdout.write(text, error => { if (error)
508
- reject(error);
509
- else
510
- resolve(); });
511
- }));
512
- }
513
- catch {
514
- return '';
515
- }
516
- },
517
- present: () => { },
518
- };
519
- export const claudeWatchCommand = {
453
+ export const claudeModCommand = {
520
454
  parse(argv, context) { if (argv.length > 0)
521
455
  usage(context.command); return undefined; },
522
- execute: async () => runClaudeWatch(await readStdin(), process.env),
456
+ execute: async () => runClaudeMod(await readStdin(), process.env),
523
457
  present: () => { },
524
458
  };
525
459
  export const codexHookCommand = {
@@ -1,10 +1,10 @@
1
- import { buildCommand, doneCommand, expressCommand, ignoreCommand, joinCommand, listenCommand, listeningCommand, unlistenCommand } from './square-commands.js';
1
+ import { buildCommand, doneCommand, expressCommand, ignoreCommand, joinCommand, listenCommand, unlistenCommand } from './square-commands.js';
2
2
  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
6
  import { JSON_COMMANDS } from './json.js';
7
- import { perceiveCommand, claudeHookCommand, claudeWatchCommand, codexHookCommand, codexWatchCommand, codexInterruptCommand, historyCommand, inboxCommand, listCommand, participantsCommand, statusCommand, streamCommand, } from './observation-commands.js';
7
+ import { perceiveCommand, claudeModCommand, codexHookCommand, codexWatchCommand, codexInterruptCommand, historyCommand, inboxCommand, listCommand, statusCommand, streamCommand, } from './observation-commands.js';
8
8
  /** Every public command is an executable adapter, including aliases and utility commands. */
9
9
  export const commandRegistry = [
10
10
  { names: ['build'], spec: buildCommand },
@@ -12,8 +12,7 @@ export const commandRegistry = [
12
12
  { names: ['join'], spec: joinCommand },
13
13
  { names: ['stream'], spec: streamCommand },
14
14
  { names: ['inbox'], spec: inboxCommand },
15
- { names: ['claude-hook'], spec: claudeHookCommand },
16
- { names: ['claude-watch'], spec: claudeWatchCommand },
15
+ { names: ['claude-mod'], spec: claudeModCommand },
17
16
  { names: ['codex-hook'], spec: codexHookCommand },
18
17
  { names: ['codex-watch'], spec: codexWatchCommand },
19
18
  { names: ['codex-interrupt'], spec: codexInterruptCommand },
@@ -22,7 +21,6 @@ export const commandRegistry = [
22
21
  { names: ['listen'], spec: listenCommand },
23
22
  { names: ['ignore'], spec: ignoreCommand },
24
23
  { names: ['unlisten'], spec: unlistenCommand },
25
- { names: ['listening'], spec: listeningCommand },
26
24
  { names: ['done'], spec: doneCommand },
27
25
  { names: ['install'], spec: installCommand },
28
26
  { names: ['uninstall'], spec: uninstallCommand },
@@ -30,7 +28,6 @@ export const commandRegistry = [
30
28
  { names: ['doctor'], spec: doctorCommand },
31
29
  { names: ['history'], spec: historyCommand },
32
30
  { names: ['status'], spec: statusCommand },
33
- { names: ['participants'], spec: participantsCommand },
34
31
  { names: ['help'], spec: helpCommand },
35
32
  { names: ['version', '--version', '-v'], spec: versionCommand },
36
33
  { names: ['mcp-server'], spec: mcpServerCommand },
@@ -8,7 +8,7 @@ interface BuildIntent {
8
8
  }
9
9
  interface JoinIntent {
10
10
  lastN: number;
11
- kick: boolean;
11
+ takeover: boolean;
12
12
  }
13
13
  interface ActivityIntent {
14
14
  activity?: string;
@@ -25,7 +25,7 @@ interface BodyIntent {
25
25
  body?: string;
26
26
  }
27
27
  interface ListenerIntent {
28
- target?: string;
28
+ target: string;
29
29
  }
30
30
  export declare const buildCommand: CommandSpec<BuildIntent, string>;
31
31
  export declare const joinCommand: CommandSpec<JoinIntent, string>;
@@ -33,6 +33,5 @@ export declare const expressCommand: CommandSpec<ActivityIntent>;
33
33
  export declare const listenCommand: CommandSpec<ListenerIntent, string>;
34
34
  export declare const ignoreCommand: CommandSpec<ListenerIntent, string>;
35
35
  export declare const unlistenCommand: CommandSpec<ListenerIntent, string>;
36
- export declare const listeningCommand: CommandSpec<ListenerIntent, string>;
37
36
  export declare const doneCommand: CommandSpec<BodyIntent, string>;
38
37
  export {};
@@ -1,6 +1,6 @@
1
1
  import { formatHardCap } from '../model.js';
2
2
  import { commandPrefix, participantCommandPrefix, withPathOutput, } from '../presentation.js';
3
- import { renderJoinResult, renderLifecycleResult, renderListenerChange, renderListeningResult, } from '../operation-presentation.js';
3
+ import { renderJoinResult, renderLifecycleResult, renderListenerChange, } from '../operation-presentation.js';
4
4
  import { Square, requireOwner, requireJoinName, selectOwnSeat } from '../square-api.js';
5
5
  import { executeExpression } from './express-presentation.js';
6
6
  import { jsonResult } from './json.js';
@@ -62,23 +62,23 @@ export const buildCommand = {
62
62
  export const joinCommand = {
63
63
  parse(argv, context) {
64
64
  let lastN = JOIN_DEFAULT_LAST;
65
- let kick = false;
65
+ let takeover = false;
66
66
  for (let index = 0; index < argv.length; index++) {
67
67
  if (argv[index] === '--last') {
68
68
  lastN = parseBoundedLimit(argv[index + 1], '--last', JOIN_MAX_LAST, `${context.name === undefined ? commandPrefix(requireSquarePath(context)) : participantCommandPrefix(requireSquarePath(context), context.name)} join --last ${JOIN_MAX_LAST}`);
69
69
  index += 1;
70
70
  }
71
- else if (argv[index] === '--kick')
72
- kick = true;
71
+ else if (argv[index] === '--takeover')
72
+ takeover = true;
73
73
  else if (argv[index] !== '--json')
74
74
  usage(context.command);
75
75
  }
76
- return { lastN, kick };
76
+ return { lastN, takeover };
77
77
  },
78
78
  async execute(intent, context) {
79
79
  const { owner, wakeAddress } = commandIdentity(context.env, context.owner);
80
80
  const data = await withSquare(context, (square) => square.join(requireJoinName(context.name), {
81
- owner: requireOwner(owner), wakeAddress, takeover: intent.kick, last: intent.lastN, ...(context.json ? {} : { observe: true }),
81
+ owner: requireOwner(owner), wakeAddress, takeover: intent.takeover, last: intent.lastN, ...(context.json ? {} : { observe: true }),
82
82
  }));
83
83
  return context.json ? jsonResult(data) : renderJoinResult(data, context.owner ?? context.env.SQUARE_OWNER);
84
84
  },
@@ -153,15 +153,14 @@ export const expressCommand = {
153
153
  },
154
154
  present: () => { },
155
155
  };
156
- function parseListener(argv, context, targetRequired) {
157
- const args = argv.filter((arg) => arg !== '--json');
158
- if (targetRequired ? args.length !== 1 : args.length !== 0)
159
- usage(context.command);
160
- return targetRequired ? { target: args[0] } : {};
161
- }
162
156
  function listenerCommand(verb) {
163
157
  return {
164
- parse(argv, context) { return parseListener(argv, context, true); },
158
+ parse(argv, context) {
159
+ const args = argv.filter((arg) => arg !== '--json');
160
+ if (args.length !== 1)
161
+ usage(context.command);
162
+ return { target: args[0] };
163
+ },
165
164
  async execute(intent, context) {
166
165
  const squarePath = requireSquarePath(context);
167
166
  const data = await withSquare(context, async (square) => (await selectOwnSeat(square, commandIdentity(context.env, context.owner).owner, context.name))[verb](intent.target, context.json ? {} : { observe: true }));
@@ -173,15 +172,6 @@ function listenerCommand(verb) {
173
172
  export const listenCommand = listenerCommand('listen');
174
173
  export const ignoreCommand = listenerCommand('ignore');
175
174
  export const unlistenCommand = listenerCommand('unlisten');
176
- export const listeningCommand = {
177
- parse(argv, context) { return parseListener(argv, context, false); },
178
- async execute(_intent, context) {
179
- const squarePath = requireSquarePath(context);
180
- const data = await withSquare(context, async (square) => (await selectOwnSeat(square, commandIdentity(context.env, context.owner).owner, context.name)).listening(context.json ? {} : { observe: true }));
181
- return context.json ? jsonResult(data) : renderListeningResult(squarePath, data);
182
- },
183
- present: (result) => process.stdout.write(result),
184
- };
185
175
  export const doneCommand = {
186
176
  parse(argv, context) {
187
177
  const args = argv.filter((arg) => arg !== '--json');
package/dist/decisions.js CHANGED
@@ -65,10 +65,11 @@ export function unreadActivitySummaries(facts, name, now) {
65
65
  }
66
66
  const selected = facts.activities([...summaries.values()].map((item) => item.lastIndex));
67
67
  const byIndex = new Map(selected.map((item) => [item.index, item]));
68
- return [...summaries].map(([name, summary]) => ({
69
- name, count: summary.count, latestActivityAgeMs: Math.max(0, now - summary.latestAt),
70
- preview: byIndex.get(summary.lastIndex),
71
- })).sort((a, b) => a.latestActivityAgeMs - b.latestActivityAgeMs || a.name.localeCompare(b.name));
68
+ return [...summaries].map(([name, summary]) => {
69
+ const latest = byIndex.get(summary.lastIndex);
70
+ return { name, count: summary.count, latestActivityAgeMs: Math.max(0, now - summary.latestAt),
71
+ preview: { ...(latest.body === undefined ? {} : { body: latest.body }), structured: latest.metadata !== undefined } };
72
+ }).sort((a, b) => a.latestActivityAgeMs - b.latestActivityAgeMs || a.name.localeCompare(b.name));
72
73
  }
73
74
  export function decideAct(facts, input) {
74
75
  const { now, force, reach, reply } = input;
@@ -71,8 +71,8 @@ export async function doctorClaudePlugin(homeDir, run = runClaude) {
71
71
  return [
72
72
  fs.existsSync(bundle) ? `✓ Square Claude plugin bundle ${root}` : `○ Square Claude plugin bundle missing ${root}`,
73
73
  installed ? `✓ ${CLAUDE_PLUGIN_ID} installed` : `○ ${CLAUDE_PLUGIN_ID} unavailable`,
74
- `Claude delivery uses synchronous prompt/tool hooks and one finite 24-hour asyncRewake Stop observer; actual coverage ends at native boundaries.`,
75
- `Idle Escape cannot disarm a watcher, and already emitted notifications cannot be recalled; busy Escape disarms at the next prompt boundary.`,
76
- `Native stderr output is recorded unknown until its exact token/hash frame appears at a later prompt boundary; model comprehension is not observed.`,
74
+ `Claude delivery uses a mod: busy turns append context and log it; idle main sessions submit an attributed plugin prompt.`,
75
+ `Stop suppresses the current delivery batch; clear, resume and module reload retire the captured helper and attachment.`,
76
+ `Exact native acceptance records presentation, not model comprehension. Paseo does not yet expose Claude ui_log events.`,
77
77
  ];
78
78
  }
package/dist/help.js CHANGED
@@ -13,9 +13,9 @@ const COMMANDS = [
13
13
  details: ['Options:', ' --depth <N> Descend through at most N directory levels (default 4; maximum 16; 0 scans only the current directory).', ' --limit <N> Show one page (default 20, maximum 100).', ' --after <path> Resume after a relative path from a previous page.'],
14
14
  },
15
15
  {
16
- names: ['join'], usage: '--as <name> join [--last N] [--kick]', usesSquare: true, group: 'participant',
16
+ names: ['join'], usage: '--as <name> join [--last N] [--takeover]', usesSquare: true, group: 'participant',
17
17
  summary: 'Step into the square and read its current context.',
18
- details: ['Options:', ' --last <N> Show the last N public activities (default 10, maximum 100).', ' --kick End the standing participant and reclaim the name for this session.'],
18
+ details: ['Options:', ' --last <N> Show the last N public activities (default 10, maximum 100).', ' --takeover End the standing participant and reclaim the name for this session.'],
19
19
  },
20
20
  {
21
21
  names: ['express'], usage: '--as <name> express [-f|--force] [--no-wait] [--metadata <json>] [--mention <name>... | --bell] [--no-mention] [--reply <activity-id>] [<activity> | -]', usesSquare: true, group: 'participant',
@@ -40,11 +40,10 @@ const COMMANDS = [
40
40
  { names: ['listen'], usage: '--as <name> listen <participant>', usesSquare: true, group: 'participant', summary: 'Turn an ear toward one participant\'s future activity.' },
41
41
  { names: ['unlisten'], usage: '--as <name> unlisten <participant>', usesSquare: true, group: 'participant', summary: 'Stop listening without blocking that participant\'s mentions or replies.' },
42
42
  { names: ['ignore'], usage: '--as <name> ignore <participant>', usesSquare: true, group: 'participant', summary: 'Stop hearing one participant\'s future activity, except bells.' },
43
- { names: ['listening'], usage: '--as <name> listening', usesSquare: true, group: 'participant', summary: 'Show who you are turned toward.', details: ['Listening applies to future activity. What you could hear when an activity landed does not change afterward.'] },
44
43
  {
45
- names: ['perceive'], usage: '--as <name> perceive [--id <activity-id>] [--now | --idle <duration>] [--from <names>] [--mention] [--limit <count>] [--replace]', usesSquare: true, group: 'participant',
44
+ names: ['perceive'], usage: '--as <name> perceive [--id <activity-id>] [--idle <duration>] [--from <names>] [--mention] [--limit <count>] [--takeover]', usesSquare: true, group: 'participant',
46
45
  summary: 'Perceive directed conversation since you last looked.',
47
- details: ['Modes:', ' --id <activity-id> Perceive exactly one activity addressed to you, with its full body; implies --now.', ' Marks only this activity seen; repeats return it again. No filters, limit, idle or replace.', ' history stays read-only; perceive --id consumes the selected activity.', ' --now Take in activity immediately; bare perceive already does this.', ' --idle <duration> Wait for something relevant, or for quiet to last this long.', '', 'Attention:', ' Mentions arrive when you are addressed; bells arrive for everyone; bare says require listen.', ' listen and ignore are future-only and fixed when each say lands.', '', 'Filters:', ' --from <names> Match only comma-separated participants.', ' --mention Match direct attention for your current participant (and bells).', ' --limit <count> Return one page (default 10, maximum 100).', '', 'Recovery:', ' --replace Replace another active perceive for this participant.'],
46
+ details: ['Modes:', ' --id <activity-id> Open one activity addressed to you in full; repeats work. Use it alone.', ' --idle <duration> Wait for something relevant, or for quiet to last this long.', '', 'Attention:', ' Mentions arrive when you are addressed; bells arrive for everyone; bare says require listen.', ' listen and ignore are future-only and fixed when each say lands.', '', 'Filters:', ' --from <names> Match only comma-separated participants.', ' --mention Match direct attention for your current participant (and bells).', ' --limit <count> Return one page (default 10, maximum 100).', '', 'Recovery:', ' --takeover Take over from another active perceive for this participant.'],
48
47
  },
49
48
  { names: ['done'], usage: '--as <name> done', usesSquare: true, group: 'participant', summary: 'Step out of the square.', details: ['done takes no message. Use express before leaving to send one.'] },
50
49
  {
@@ -60,19 +59,13 @@ const COMMANDS = [
60
59
  { names: ['codex-hook'], usage: '{command}', summary: 'Present pending attention at one native agent boundary.', hiddenFromIndex: true },
61
60
  { names: ['codex-watch'], usage: '{command}', summary: 'Observe pending attention from a native async Stop hook.', hiddenFromIndex: true },
62
61
  { names: ['codex-interrupt'], usage: '{command}', summary: 'Cancel pending attention at a native Interrupt boundary.', hiddenFromIndex: true },
63
- { names: ['claude-hook'], usage: '{command}', summary: 'Receive a native Claude hook event.', hiddenFromIndex: true },
64
- { names: ['claude-watch'], usage: '{command}', summary: 'Observe pending attention from a native async Stop hook.', hiddenFromIndex: true },
62
+ { names: ['claude-mod'], usage: '{command}', summary: 'Run the Claude mod delivery helper.', hiddenFromIndex: true },
65
63
  {
66
64
  names: ['history'], usage: 'history [filters] [output]', usesSquare: true, group: 'participant',
67
65
  summary: 'Read or search the archive without changing what you have perceived.',
68
- details: ['Optional --as is accepted but does not change the archive or claim a name.', '', 'Filters:', ' --from <names> Match activities from participants.', ' --since <time> Match activities after a time.', ' --grep <regex> | --fixed <s> Search activity ids, participants, and original bodies.', ' --mention <name> Match direct attention for a participant.', ' --at <ids> Center on comma-separated activity ids; may repeat.', ' -B, -A, -C <N> Set non-negative context around every --at coordinate.', ' --before <id> Read the page immediately before an activity.', ' --after <id> Read the page immediately after an activity.', '', 'Results:', ' --limit <N> Page size (default 10, maximum 100).', ' --order <asc|desc> Set display order (default oldest first).', '', 'Output:', ' --no-truncate --json --format <fields>', ' One result shows its full body; multiple results use previews.', ' --no-truncate shows every original body.'],
66
+ details: ['Filters:', ' --from <names> Match activities from participants.', ' --since <time> Match activities after a time.', ' --search <text> [--regex] Search ids, participants, and original bodies; literal by default.', ' --mention <name> Match direct attention for a participant.', ' --at <ids> Center on comma-separated activity ids; may repeat.', ' -C <N> Set symmetric context around every --at coordinate.', ' --before <id> Read the page immediately before an activity.', ' --after <id> Read the page immediately after an activity.', '', 'Results:', ' --limit <N> Page size (default 10, maximum 100).', ' --order <asc|desc> Set display order (default oldest first).', '', 'Output:', ' --full --json --format <fields>', ' One result shows its full body; multiple results use previews.', ' --full shows every original body.'],
69
67
  },
70
68
  { names: ['status'], usage: '[--as <name>] status', usesSquare: true, group: 'participant', summary: 'Show who is present and what happened most recently.' },
71
- {
72
- names: ['participants'], usage: 'participants [--limit <count>]', usesSquare: true, group: 'host',
73
- summary: 'Show the participant roster and current states.',
74
- details: ['Options:', ' --limit <count> Show the first count names in human text (default 20, maximum 100).'],
75
- },
76
69
  {
77
70
  names: ['install'], usage: 'install (--all | <target>...) [-f]', group: 'maintenance',
78
71
  summary: 'Install Square support for one or more agent hosts.',
@@ -101,8 +94,8 @@ function isHelpFlag(value) {
101
94
  }
102
95
  export function renderGlobalHelp() {
103
96
  const groups = [
104
- { key: 'participant', title: 'In the square:', order: ['join', 'express', 'listen', 'unlisten', 'ignore', 'listening', 'perceive', 'history', 'status', 'done'] },
105
- { key: 'host', title: 'Prepare and manage:', order: ['build', 'list', 'participants'] },
97
+ { key: 'participant', title: 'In the square:', order: ['join', 'express', 'listen', 'unlisten', 'ignore', 'perceive', 'history', 'status', 'done'] },
98
+ { key: 'host', title: 'Prepare and manage:', order: ['build', 'list'] },
106
99
  { key: 'maintenance', title: 'Setup:', order: ['install', 'uninstall', 'doctor'] },
107
100
  ];
108
101
  const commandLines = groups.flatMap(({ key, title, order }) => [
@@ -117,7 +110,7 @@ export function renderGlobalHelp() {
117
110
  'Usage: square [--location <square>] [--as <name>] [--owner <id>] <command> [args...]',
118
111
  'Location: square-accessing commands require --location <square>. Use square list to find nearby squares and your joined names; use --as to select a participant.',
119
112
  'Identity: --owner overrides SQUARE_OWNER, then a complete harness identity, then user:<OS user>@<host>. Incomplete or ambiguous harness identities refuse. Owners without wake use perceive --idle.',
120
- 'Output: --json on join, express, perceive, history, listen, ignore, unlisten, listening, done, status, participants and inbox prints the SDK result without observation; a participant handle becomes {name}.',
113
+ 'Output: --json on join, express, perceive, history, listen, ignore, unlisten, done, status and inbox prints the SDK result without observation; a participant handle becomes {name}.',
121
114
  'History emits one JSON document; stream --ndjson emits one SDK record per line.',
122
115
  '',
123
116
  ...commandLines,
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { Square, squareLocation, squareClock, discover, inbox, diagnoseSquare } from './square-api.js';
1
+ export { Square, squareLocation, discover, inbox, diagnoseSquare } from './square-api.js';
2
2
  export { SquareError, ACTIVITY_METADATA_MAX_BYTES } from './model.js';
3
3
  export { selectOwnSeat, requireOwner, requireJoinName, localUserOwner, harnessOwner, decodeHarnessOwner } from './square-api.js';
4
4
  export { postAndDispatch, dispatchEligibleCards } from './notifications.js';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Square, squareLocation, squareClock, discover, inbox, diagnoseSquare } from './square-api.js';
1
+ export { Square, squareLocation, discover, inbox, diagnoseSquare } from './square-api.js';
2
2
  export { SquareError, ACTIVITY_METADATA_MAX_BYTES } from './model.js';
3
3
  export { selectOwnSeat, requireOwner, requireJoinName, localUserOwner, harnessOwner, decodeHarnessOwner } from './square-api.js';
4
4
  export { postAndDispatch, dispatchEligibleCards } from './notifications.js';
package/dist/mcp.d.ts CHANGED
@@ -4,6 +4,7 @@ import type { SquareAtInput } from './square-facade.js';
4
4
  import type { WakeAddress } from './model.js';
5
5
  /** Each tool call chooses its square and owns its connection lifetime. */
6
6
  export interface SquareMcpOptions extends Omit<SquareAtInput, 'path'> {
7
+ readonly env?: NodeJS.ProcessEnv;
7
8
  readonly owner?: Owner;
8
9
  readonly wakeAddress?: WakeAddress;
9
10
  }
package/dist/mcp.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { SQUARE_TOOLS, SQUARE_TOOL_INSTRUCTIONS, createSquareToolRunner, squareToolsEnabled } from './square-tools.js';
4
- import { operationEnv } from './participant-identity.js';
5
4
  import { codexWakeAddress } from './codex-address.js';
6
5
  import { readClaudeMcpCall } from './claude-mcp-context.js';
7
6
  import { SQUARE_IDENTITY } from './identity.js';
8
- import { Square, discover, squareClock } from './square-api.js';
7
+ import { Square, discover } from './square-api.js';
9
8
  import { harnessOwner } from './square-api.js';
10
9
  export function createSquareMcpServer(options) {
11
10
  const { owner: configuredOwner, wakeAddress, ...resourceOptions } = options;
@@ -21,7 +20,7 @@ export function createSquareMcpServer(options) {
21
20
  return invoke(tool, args, { signal: extra.signal }, async () => {
22
21
  const threadId = extra._meta?.threadId;
23
22
  const opencodeSessionId = extra._meta?.['ai.opencode/sessionID'];
24
- // Claude's bundled plugin requires a per-call native hook association; startup identity is not a fallback.
23
+ // Claude's bundled mod requires a per-call native association; startup identity is not a fallback.
25
24
  const claude = baseEnv.SQUARE_CLAUDE_MCP_CONTEXT === '1'
26
25
  ? await readClaudeMcpCall(extra._meta?.['claudecode/toolUseId'], baseEnv)
27
26
  : undefined;
@@ -32,27 +31,17 @@ export function createSquareMcpServer(options) {
32
31
  : typeof opencodeSessionId === 'string' && opencodeSessionId.trim()
33
32
  ? harnessOwner({ channel: 'opencode', session: opencodeSessionId })
34
33
  : configuredOwner;
35
- const env = claude !== undefined
36
- ? { ...operationEnv('claude', claude.sessionId, baseEnv),
37
- // An agent loop ID is not a session ID.
38
- CLAUDE_CODE_CHILD_SESSION: claude.agentId === undefined ? '' : '1' }
39
- : typeof threadId === 'string' && threadId.trim()
40
- ? operationEnv('codex', threadId, baseEnv)
41
- : typeof opencodeSessionId === 'string' && opencodeSessionId.trim()
42
- ? operationEnv('opencode', opencodeSessionId, baseEnv)
43
- : baseEnv;
44
34
  const callWake = wakeAddress !== undefined && (owner === configuredOwner
45
35
  || wakeAddress.kind === 'paseo' && wakeAddress.address.agentId === baseEnv.PASEO_AGENT_ID
46
36
  || wakeAddress.kind === 'opencode-server' && wakeAddress.address.sessionId === opencodeSessionId)
47
37
  ? wakeAddress : undefined;
38
+ const clock = resourceOptions.clock ?? Date.now;
48
39
  return {
49
40
  identity: { owner, wakeAddress: claude === undefined && typeof threadId === 'string' && threadId.trim()
50
- ? { ...codexWakeAddress(threadId, env), kind: 'codex-queue' } : callWake },
51
- open: (location, control) => Square.at({ ...resourceOptions, env, cwd: claude?.cwd ?? resourceOptions.cwd, path: location }, control),
52
- discover: async (discovery, control) => ({
53
- result: await discover({ ...resourceOptions, env, cwd: claude?.cwd ?? resourceOptions.cwd }, discovery, control),
54
- now: squareClock(env, resourceOptions.clock)(),
55
- }),
41
+ ? { ...codexWakeAddress(threadId, baseEnv), kind: 'codex-queue' } : callWake },
42
+ now: clock,
43
+ open: (location, control) => Square.at({ ...resourceOptions, cwd: claude?.cwd ?? resourceOptions.cwd, path: location, clock }, control),
44
+ discover: (discovery, control) => discover({ cwd: claude?.cwd ?? resourceOptions.cwd }, discovery, control),
56
45
  };
57
46
  }).then(({ text, isError }) => ({
58
47
  ...(isError ? { isError } : {}), content: [{ type: 'text', text }],
package/dist/model.d.ts CHANGED
@@ -54,7 +54,7 @@ export type DirectedNotificationRoute = import('./attention.js').AudienceRoute;
54
54
  export interface WatchOptions {
55
55
  participants?: string[];
56
56
  mention?: string;
57
- replace?: boolean;
57
+ takeover?: boolean;
58
58
  }
59
59
  export type PublicAct = Extract<HydratedAct, {
60
60
  kind: 'say' | 'done';
package/dist/neutral.d.ts CHANGED
@@ -2,9 +2,17 @@
2
2
  export type Owner = string;
3
3
  export type SquareErrorCode = 'invalid_name' | 'invalid_args' | 'unknown_participant' | 'not_joined' | 'already_joined' | 'already_done' | 'capped' | 'throttled' | 'bell_quota' | 'behind' | 'io' | 'unavailable';
4
4
  export type InternalSquareErrorCode = SquareErrorCode | 'not_found' | 'cap_reached' | 'conflict' | 'pending_peer';
5
+ /** One speaker's unperceived activity, previewed by its latest body. */
6
+ export interface UnreadActivitySummary {
7
+ readonly name: string;
8
+ readonly count: number;
9
+ readonly latestActivityAgeMs: number;
10
+ readonly preview: {
11
+ readonly body?: string;
12
+ readonly structured: boolean;
13
+ };
14
+ }
5
15
  export interface SquareErrorFacts {
6
- /** Copyable recovery for a missing, detached or foreign seat. */
7
- join?: string;
8
16
  /** Express admission rejected before any activity was committed. */
9
17
  activityUnsent?: true;
10
18
  /** Refusal reason, including absent participants, conflicting reach, and inaccessible activities. */
@@ -15,8 +23,12 @@ export interface SquareErrorFacts {
15
23
  targets?: readonly string[];
16
24
  /** Whether the artifact holds that activity at all; an unknown id needs an ordinary page. */
17
25
  activityExists?: boolean;
18
- pending?: number;
26
+ /** Who spoke while an express was away; the refusal rests on exactly these. */
27
+ activitySummaries?: readonly UnreadActivitySummary[];
19
28
  retryAfterMs?: number;
29
+ /** A capped speaker's spoken count against the square's cap. */
30
+ spoken?: number;
31
+ hardCap?: number;
20
32
  }
21
33
  export interface PerceiveWaitStart {
22
34
  readonly idleMs: number;
@@ -3,7 +3,6 @@ import type { Owner } from './owner.js';
3
3
  export { createDefaultDeliveryTransports } from './wake-transports.js';
4
4
  /** Best-effort dispatch for currently eligible cards, including cards restored by release. */
5
5
  export declare function dispatchEligibleCards(ledger: DeliveryLedger, owner: Owner, options?: {
6
- readonly env?: NodeJS.ProcessEnv;
7
6
  readonly signal?: AbortSignal;
8
7
  readonly track?: (result: HandoffResult) => void;
9
8
  readonly transports?: readonly DeliveryTransport[];
@@ -15,10 +14,9 @@ export declare function postAndDispatch(ledger: DeliveryLedger, input: {
15
14
  readonly text: string;
16
15
  readonly details?: Readonly<Record<string, unknown>>;
17
16
  }, options?: {
18
- readonly env?: NodeJS.ProcessEnv;
19
17
  readonly signal?: AbortSignal;
20
18
  readonly track?: (result: HandoffResult) => void;
21
19
  readonly transports?: readonly DeliveryTransport[];
22
20
  }): Promise<PostResult>;
23
21
  /** Best-effort dispatch after a card has been posted; never inspect producer storage. */
24
- export declare function dispatchPostedCard(ledger: DeliveryLedger, owner: Owner, key: string, track: (result: HandoffResult) => void, env?: NodeJS.ProcessEnv, signal?: AbortSignal, suppliedTransports?: readonly DeliveryTransport[]): Promise<void>;
22
+ export declare function dispatchPostedCard(ledger: DeliveryLedger, owner: Owner, key: string, track: (result: HandoffResult) => void, signal?: AbortSignal, suppliedTransports?: readonly DeliveryTransport[]): Promise<void>;