@astrosheep/square 0.3.93 → 0.3.95

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 (146) hide show
  1. package/dist/activity-feed.d.ts +3 -5
  2. package/dist/activity-feed.js +16 -14
  3. package/dist/artifact.js +3 -3
  4. package/dist/attention.d.ts +19 -0
  5. package/dist/attention.js +30 -0
  6. package/dist/boundary-presentation.d.ts +2 -2
  7. package/dist/boundary-presentation.js +33 -40
  8. package/dist/catch-decisions.d.ts +5 -8
  9. package/dist/catch-decisions.js +45 -25
  10. package/dist/claude-delivery-status.js +10 -4
  11. package/dist/claude-delivery.js +19 -11
  12. package/dist/claude-mod.js +24 -53
  13. package/dist/cli/context.d.ts +9 -4
  14. package/dist/cli/context.js +30 -27
  15. package/dist/cli/express-presentation.d.ts +3 -1
  16. package/dist/cli/express-presentation.js +28 -16
  17. package/dist/cli/json.d.ts +3 -0
  18. package/dist/cli/json.js +14 -0
  19. package/dist/cli/mcp-server-command.js +2 -2
  20. package/dist/cli/observation-commands.d.ts +1 -3
  21. package/dist/cli/observation-commands.js +43 -56
  22. package/dist/cli/program.js +3 -3
  23. package/dist/cli/registry.js +7 -6
  24. package/dist/cli/square-commands.d.ts +0 -2
  25. package/dist/cli/square-commands.js +30 -44
  26. package/dist/codex-hook.d.ts +3 -2
  27. package/dist/codex-hook.js +13 -4
  28. package/dist/codex-queue.js +4 -4
  29. package/dist/decisions.d.ts +5 -16
  30. package/dist/decisions.js +9 -33
  31. package/dist/delivery-attempts.d.ts +52 -0
  32. package/dist/delivery-attempts.js +73 -0
  33. package/dist/delivery-deferral.js +2 -2
  34. package/dist/delivery-effects.d.ts +139 -0
  35. package/dist/delivery-effects.js +163 -0
  36. package/dist/delivery-health.d.ts +0 -1
  37. package/dist/delivery-health.js +1 -3
  38. package/dist/delivery-operations.d.ts +2 -2
  39. package/dist/delivery-operations.js +76 -101
  40. package/dist/delivery-primitives.d.ts +5 -0
  41. package/dist/delivery-primitives.js +3 -0
  42. package/dist/delivery.d.ts +1 -1
  43. package/dist/delivery.js +7 -6
  44. package/dist/help.js +14 -14
  45. package/dist/http-delivery.d.ts +16 -0
  46. package/dist/http-delivery.js +101 -0
  47. package/dist/inbox.d.ts +9 -22
  48. package/dist/inbox.js +23 -27
  49. package/dist/index.d.ts +1 -3
  50. package/dist/index.js +1 -1
  51. package/dist/mcp.d.ts +3 -0
  52. package/dist/mcp.js +23 -24
  53. package/dist/model.d.ts +12 -21
  54. package/dist/model.js +5 -8
  55. package/dist/notifications.d.ts +1 -1
  56. package/dist/notifications.js +8 -5
  57. package/dist/operation-presentation.d.ts +6 -6
  58. package/dist/operation-presentation.js +55 -58
  59. package/dist/owner.d.ts +11 -0
  60. package/dist/owner.js +32 -0
  61. package/dist/paseo-delivery.d.ts +4 -1
  62. package/dist/paseo-delivery.js +7 -12
  63. package/dist/paseo-state.d.ts +2 -2
  64. package/dist/paseo-state.js +6 -4
  65. package/dist/plugins/opencode/delivery.js +27 -15
  66. package/dist/ports.d.ts +18 -47
  67. package/dist/presentation-operations.d.ts +14 -19
  68. package/dist/presentation-operations.js +51 -61
  69. package/dist/presentation.d.ts +7 -17
  70. package/dist/presentation.js +46 -91
  71. package/dist/receive.d.ts +66 -0
  72. package/dist/receive.js +54 -0
  73. package/dist/runtime.d.ts +1 -8
  74. package/dist/runtime.js +2 -17
  75. package/dist/seats.d.ts +2 -3
  76. package/dist/seats.js +7 -15
  77. package/dist/session-lifecycle.d.ts +6 -2
  78. package/dist/session-lifecycle.js +39 -11
  79. package/dist/sqlite-square.d.ts +36 -23
  80. package/dist/sqlite-square.js +162 -211
  81. package/dist/square-api.d.ts +16 -11
  82. package/dist/square-api.js +27 -23
  83. package/dist/square-core.d.ts +0 -14
  84. package/dist/square-core.js +0 -9
  85. package/dist/square-domain.d.ts +4 -2
  86. package/dist/square-domain.js +65 -52
  87. package/dist/square-facade.d.ts +47 -105
  88. package/dist/square-index.d.ts +5 -13
  89. package/dist/square-index.js +13 -38
  90. package/dist/square-legacy-framing.d.ts +2 -0
  91. package/dist/square-legacy-framing.js +8 -0
  92. package/dist/square-location.d.ts +1 -14
  93. package/dist/square-location.js +4 -70
  94. package/dist/square-migration-host-ledger.d.ts +2 -2
  95. package/dist/square-migration-host-ledger.js +6 -5
  96. package/dist/square-migration.d.ts +4 -1
  97. package/dist/square-migration.js +93 -38
  98. package/dist/square-receive.d.ts +6 -0
  99. package/dist/square-receive.js +18 -0
  100. package/dist/square-sqlite.d.ts +9 -3
  101. package/dist/square-sqlite.js +139 -114
  102. package/dist/square-tools.d.ts +7 -10
  103. package/dist/square-tools.js +21 -61
  104. package/dist/stream.js +4 -5
  105. package/dist/views.d.ts +23 -13
  106. package/dist/views.js +47 -53
  107. package/dist/wakes.d.ts +1 -5
  108. package/dist/wakes.js +4 -6
  109. package/examples/symmetric-domains.mjs +250 -0
  110. package/guides/application-facade-delivery-evidence.md +6 -6
  111. package/guides/attention-primitive.md +32 -0
  112. package/guides/change-waits.md +2 -2
  113. package/guides/claude-native.md +18 -9
  114. package/guides/codex-delivery.md +17 -6
  115. package/guides/delivery-primitives.md +180 -0
  116. package/guides/mcp-connection-lifetime.md +1 -1
  117. package/guides/mcp.md +3 -3
  118. package/guides/migration.md +148 -151
  119. package/guides/operation-cancellation.md +1 -1
  120. package/guides/participant-ownership.md +78 -47
  121. package/guides/pi-tools.md +34 -5
  122. package/guides/primitive-catch-consolidation.md +5 -5
  123. package/guides/primitive-history-consolidation.md +2 -2
  124. package/guides/primitive-status-consolidation.md +3 -3
  125. package/guides/primitive-storage-consolidation.md +1 -1
  126. package/guides/receive-primitive.md +90 -0
  127. package/guides/row-runtime-delivery-evidence.md +1 -1
  128. package/guides/row-storage-design.md +22 -28
  129. package/guides/square-api.md +314 -91
  130. package/guides/symmetric-domains.md +92 -0
  131. package/package.json +14 -1
  132. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  133. package/plugins/claude/skills/square/SKILL.md +2 -6
  134. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  135. package/plugins/opencode/delivery.ts +27 -17
  136. package/plugins/paseo/client/palette.ts +18 -18
  137. package/plugins/paseo/client/square-message.tsx +17 -23
  138. package/plugins/pi/square-pi.js +17 -17
  139. package/skills/square/SKILL.md +2 -6
  140. package/dist/square-backend.d.ts +0 -13
  141. package/dist/square-backend.js +0 -1
  142. package/dist/square-stdio.d.ts +0 -22
  143. package/dist/square-stdio.js +0 -235
  144. package/dist/stdio-server.d.ts +0 -3
  145. package/dist/stdio-server.js +0 -212
  146. package/guides/backends.md +0 -193
@@ -1,21 +1,23 @@
1
1
  import { formatActivityId } from './square-core.js';
2
+ import { assertCurrentSeat } from './square-domain.js';
3
+ import { canonicalPath } from './canonical-path.js';
2
4
  import { validateMetadataMatch, validateDeferralDuration, validateDeferralId } from './delivery-deferral.js';
3
- import { squareLocation, localSquareLocation } from './square-location.js';
5
+ import { squareLocation } from './square-location.js';
4
6
  import crypto from 'node:crypto';
5
7
  import { setTimeout as sleep } from 'node:timers/promises';
6
- import { InternalSquareError, SquareError, isSquareError, nameKey, sameBody, validateName } from './model.js';
7
- import { coreDone, coreHold, coreIgnore, coreListen, coreListening, coreResume, coreUnlisten, decideAct, decideImplicitJoin, decideJoin, resolveKnownName, validateDoneBody } from './decisions.js';
8
- import { HELD_WAIT_BUDGET_MS, WATCH_HEARTBEAT_MS, inSquareCount, presenceAnchor } from './runtime.js';
8
+ import { InternalSquareError, SquareError, isSquareError, nameKey, validateName } from './model.js';
9
+ import { coreDone, coreIgnore, coreListen, coreListening, coreUnlisten, decideAct, decideJoin, resolveKnownName, validateDoneBody } from './decisions.js';
10
+ import { WATCH_HEARTBEAT_MS, inSquareCount, presenceAnchor } from './runtime.js';
9
11
  import { catchLimit, decideCatch, observeCatchSelection, selectCatchPage } from './catch-decisions.js';
10
- import { directedSuffix } from './activity-feed.js';
12
+ import { expressionContext } from './activity-feed.js';
11
13
  import { expressHint } from './hints.js';
12
- import { asSeatRef, participantAuthority, requireBody, requireJoinName, requireSeat } from './seats.js';
14
+ import { asSeatRef, participantAuthority, requireOwner, requireJoinName } from './seats.js';
13
15
  import { recoveryObservation, entryPresentation, snapshot, queryStatus, queryParticipants, catchPresence, parseRequiredActivityId, toPublicActivity, publicActivities, selectHistory, NON_READ, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
14
16
  import { sessionInboxCounts } from './inbox.js';
15
17
  import { rememberSquarePath, squareIndexPath } from './square-index.js';
16
- import { createDefaultWakeTransport } from './notifications.js';
17
18
  import { deliverPending } from './delivery-operations.js';
18
19
  import { participantIdentity } from './participant-identity.js';
20
+ import { joinRecoveryCommand } from './presentation.js';
19
21
  import { acquireWatchLease, ownsWatchLease, pulseWatchLease, releaseWatchLease } from './wakes.js';
20
22
  import { createArtifactPort, createSquare, diagnoseSquareFile, prepareSquareBuild } from './artifact.js';
21
23
  import { migrateSquareFile } from './square-migration.js';
@@ -24,7 +26,6 @@ import { streamSquare } from './stream.js';
24
26
  export { createSquareResourceOwner } from './artifact.js';
25
27
  export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE } from './square-core.js';
26
28
  export { CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT } from './catch-decisions.js';
27
- export { HELD_WAIT_BUDGET_MS } from './runtime.js';
28
29
  export { HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
29
30
  export { DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from './list.js';
30
31
  function checkControl(control) {
@@ -65,38 +66,28 @@ export class SqliteSquare {
65
66
  location;
66
67
  artifact;
67
68
  clock;
68
- body;
69
- wakeAddress;
70
69
  wakeTransport;
71
70
  indexPath;
72
- automaticDelivery;
73
- ownsArtifact;
74
- defaultParticipant;
75
- constructor(location, artifact, clock, body, wakeAddress, wakeTransport, indexPath, automaticDelivery = true, ownsArtifact = true, defaultParticipant) {
71
+ closesArtifact;
72
+ deliveryLocation;
73
+ constructor(location, artifact, clock, wakeTransport, indexPath, closesArtifact = true, deliveryLocation = location) {
76
74
  this.location = location;
77
75
  this.artifact = artifact;
78
76
  this.clock = clock;
79
- this.body = body;
80
- this.wakeAddress = wakeAddress;
81
77
  this.wakeTransport = wakeTransport;
82
78
  this.indexPath = indexPath;
83
- this.automaticDelivery = automaticDelivery;
84
- this.ownsArtifact = ownsArtifact;
85
- this.defaultParticipant = defaultParticipant;
79
+ this.closesArtifact = closesArtifact;
80
+ this.deliveryLocation = deliveryLocation;
86
81
  }
87
- static async at(input, control, automaticDelivery = true) {
82
+ static async at(input, control) {
88
83
  const env = { ...(input.env ?? process.env) }, location = squareLocation({ ...input, env });
89
84
  const clock = squareClock(env, input.clock);
90
- const wakeTransport = input.wakeTransport ?? (automaticDelivery
91
- ? await createDefaultWakeTransport(env).catch(() => undefined) : undefined);
92
85
  // A request can abort its own borrowed reads, never the owner's connection lifetime.
93
86
  const borrowed = input.resources?.artifact(location);
94
87
  const artifact = borrowed ?? createArtifactPort(location, undefined, control?.signal);
95
88
  try {
96
89
  await artifact.read(facts => facts.header(), control?.signal);
97
- const resource = new SqliteSquare(location, artifact, clock, input.body, input.wakeAddress, wakeTransport, squareIndexPath(env), automaticDelivery, borrowed === undefined, input.participant);
98
- await resource.publishIdentity();
99
- return resource;
90
+ return new SqliteSquare(location, artifact, clock, input.wakeTransport || undefined, squareIndexPath(env), borrowed === undefined, await canonicalPath(location));
100
91
  }
101
92
  catch (error) {
102
93
  if (borrowed === undefined)
@@ -106,33 +97,33 @@ export class SqliteSquare {
106
97
  throw error;
107
98
  }
108
99
  }
109
- static async build(input, control, automaticDelivery = true) {
100
+ static async build(input, control) {
110
101
  checkControl(control);
111
102
  const env = { ...(input.env ?? process.env) }, location = squareLocation({ ...input, env });
112
103
  await createSquare(location, { hardCap: input.hardCap, throttlePerMinute: input.throttlePerMinute,
113
104
  template: input.template, force: input.force ?? false }, input.markdown, control?.signal);
114
105
  // Publication already committed; cancellation cannot erase the completed build.
115
- return SqliteSquare.at({ ...input, path: location, env }, undefined, automaticDelivery);
106
+ return SqliteSquare.at({ ...input, path: location, env });
116
107
  }
117
108
  static inMemory(input) {
118
109
  const env = { ...(input.env ?? process.env) };
119
- return new SqliteSquare('memory', createArtifactPort(':memory:', prepareSquareBuild(input, input.markdown)), squareClock(env, input.clock), input.body, input.wakeAddress, input.wakeTransport, undefined, true, true, input.participant);
110
+ return new SqliteSquare(`memory://${crypto.randomUUID()}`, createArtifactPort(':memory:', prepareSquareBuild(input, input.markdown)), squareClock(env, input.clock), input.wakeTransport || undefined);
120
111
  }
121
- /** Discovery is best effort and never grants write authority. Finish it before returning. */
122
- async publishIdentity() {
123
- if (this.location !== 'memory' && this.body !== undefined && this.indexPath !== undefined)
124
- await rememberSquarePath(this.location, this.body, this.indexPath).catch(() => undefined);
112
+ /** Discovery is best effort and never grants write authority. */
113
+ async publishSeat(owner) {
114
+ if (this.indexPath !== undefined)
115
+ await rememberSquarePath(this.location, owner, this.indexPath).catch(() => undefined);
125
116
  }
126
- observation(standingCount, held, participant, now = this.clock()) {
127
- return { location: this.location, standingCount, held, now,
128
- ...(participant === undefined ? {} : { participant }), automaticDeliveryAvailable: this.automaticDelivery && this.body !== undefined };
117
+ observation(standingCount, participant, now = this.clock()) {
118
+ return { location: this.location, standingCount, now,
119
+ ...(participant === undefined ? {} : { participant }) };
129
120
  }
130
121
  async contextObservation(participant, control) {
131
- return (await this.artifact.read(facts => this.observation(inSquareCount(facts), facts.hold().active, participant), control?.signal)).value;
122
+ return (await this.artifact.read(facts => this.observation(inSquareCount(facts), participant), control?.signal)).value;
132
123
  }
133
- handle(name, seat) { return new SqliteSquare.ParticipantHandle(name, this, seat); }
134
- // The nested handle can use its resource's private dependencies without widening
135
- // the concrete-derived backend contract or copying them into a second context.
124
+ handle(seat) { return new SqliteSquare.ParticipantHandle(seat.participant, this, seat); }
125
+ // The nested handle uses its resource's private dependencies without copying
126
+ // them into a second context.
136
127
  static ParticipantHandle = class {
137
128
  name;
138
129
  owner;
@@ -150,16 +141,11 @@ export class SqliteSquare {
150
141
  const control = input === undefined ? operationControl : optionsOrControl;
151
142
  let name = this.name, effect = 'unsent';
152
143
  let landedId;
153
- let waited = false, heldWaitedMs = 0;
154
144
  try {
155
145
  checkControl(control);
156
146
  name = (await square.artifact.read(facts => resolveKnownName(facts, this.name), control?.signal)).value;
157
- const seat = requireSeat(this.seat, square.body, name);
158
- const feed = !options.observe ? undefined : (await square.artifact.read(facts => {
159
- const pendingPublic = directedSuffix(facts, name);
160
- return { pendingPublic, sayNumbers: facts.sayOrdinals(pendingPublic.map(item => item.index)),
161
- perceptions: Object.fromEntries(pendingPublic.map(item => [item.index, 'full'])) };
162
- }, control?.signal)).value;
147
+ const seat = this.seat;
148
+ const context = !options.observe ? undefined : (await square.artifact.read(facts => expressionContext(facts, name), control?.signal)).value;
163
149
  while (true) {
164
150
  checkControl(control);
165
151
  try {
@@ -179,12 +165,9 @@ export class SqliteSquare {
179
165
  // Decoding selected rows is storage work, not proof of safe admission refusal.
180
166
  const proposed = decideAct(facts, { name, body, force: options.force ?? false, metadata: options.metadata, now, mentions: options.mentions,
181
167
  ...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...(reply === undefined ? {} : { reply }) });
182
- const holder = proposed.type === 'held' ? facts.hold().actor : undefined;
183
168
  const decision = rejectUnsentActivity(() => {
184
169
  if (proposed.type === 'blocked')
185
170
  throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { pending: proposed.activitySummaries.reduce((count, summary) => count + summary.count, 0) });
186
- if (proposed.type === 'held')
187
- throw new SquareError('held', 'The square is held', { ...(holder === undefined ? {} : { holder }), ...(proposed.reason === undefined ? {} : { holdReason: proposed.reason }) });
188
171
  if (proposed.type === 'capped')
189
172
  throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`);
190
173
  if (proposed.type === 'throttled')
@@ -193,46 +176,29 @@ export class SqliteSquare {
193
176
  throw new SquareError('bell_quota', `${participantIdentity(name)} cannot ring the bell yet`, { retryAfterMs: Math.max(1, proposed.nextAt - now) });
194
177
  return proposed;
195
178
  });
196
- return { stored: facts.land(decision.act), standingCount: inSquareCount(facts), held: facts.hold().active,
179
+ return { stored: facts.land(decision.act), standingCount: inSquareCount(facts),
197
180
  ownActivityCount: facts.participant(name).sayCount, hardCap: facts.header().hardCap,
198
181
  ...(decision.unmatchedMentions === undefined ? {} : { unmatchedMentions: decision.unmatchedMentions }),
199
182
  ...(decision.replyAuthorNotHere === undefined ? {} : { replyAuthorNotHere: decision.replyAuthorNotHere }) };
200
183
  }, control?.signal)).value;
201
184
  landedId = formatActivityId(committed.stored.index);
202
185
  effect = 'landed';
203
- await square.publishIdentity();
204
- const delivery = square.wakeTransport !== undefined && square.location !== 'memory'
205
- ? await deliverPending({ artifact: square.artifact, transport: square.wakeTransport, location: square.location, activity: committed.stored.index, now })
206
- .catch(() => ({ attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 }))
207
- : { attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 };
208
- const { stored, standingCount, held, ownActivityCount, hardCap, ...metadata } = committed;
186
+ if (square.wakeTransport !== undefined)
187
+ await deliverPending({ artifact: square.artifact, transport: square.wakeTransport, location: square.deliveryLocation, activity: committed.stored.index, now }).catch(() => undefined);
188
+ const { stored, standingCount, ownActivityCount, hardCap, ...metadata } = committed;
209
189
  const hint = expressHint(ownActivityCount);
210
- return { activity: toPublicActivity(stored), delivery, waited, ...metadata,
211
- ...(hint === undefined ? {} : { hint }), ...(feed === undefined ? {} : { observation: {
212
- ...square.observation(standingCount, held, name, now), ownActivityCount, hardCap, ...feed, participant: name,
190
+ return { activity: toPublicActivity(stored), ...metadata,
191
+ ...(hint === undefined ? {} : { hint }), ...(context === undefined ? {} : { observation: {
192
+ ...square.observation(standingCount, name, now), ownActivityCount, hardCap, context, participant: name,
213
193
  } }) };
214
194
  }
215
195
  catch (error) {
216
196
  if (effect !== 'landed' && isSquareError(error) && error.facts?.activityUnsent === true)
217
197
  effect = 'unsent';
218
- if (effect === 'landed' || !isSquareError(error) || options.noWait || (error.code !== 'held' && error.code !== 'throttled'))
219
- throw error;
220
- if (error.code === 'held' && heldWaitedMs >= HELD_WAIT_BUDGET_MS)
198
+ if (effect === 'landed' || !isSquareError(error) || options.noWait || error.code !== 'throttled')
221
199
  throw error;
222
- waited = true;
223
- control?.onProgress?.({ kind: 'waiting', reason: error.code,
224
- ...(error.code === 'throttled' ? { delayMs: error.facts?.retryAfterMs ?? 1 } : {}),
225
- ...(error.facts?.holder === undefined ? {} : { holder: error.facts.holder }),
226
- ...(error.facts?.holdReason === undefined ? {} : { holdReason: error.facts.holdReason }) });
227
- if (error.code === 'throttled')
228
- await sleep(error.facts?.retryAfterMs ?? 1, undefined, { signal: control?.signal });
229
- else {
230
- const started = Date.now();
231
- const observation = await square.artifact.read(facts => facts.hold().active, control?.signal);
232
- if (observation.value)
233
- await square.artifact.changed(observation.version, Math.max(1, HELD_WAIT_BUDGET_MS - heldWaitedMs), control?.signal);
234
- heldWaitedMs += Date.now() - started;
235
- }
200
+ control?.onProgress?.({ kind: 'waiting', reason: 'throttled', delayMs: error.facts?.retryAfterMs ?? 1 });
201
+ await sleep(error.facts?.retryAfterMs ?? 1, undefined, { signal: control?.signal });
236
202
  }
237
203
  }
238
204
  }
@@ -246,13 +212,13 @@ export class SqliteSquare {
246
212
  const square = this.owner;
247
213
  const name = (await square.artifact.read(facts => resolveKnownName(facts, this.name), control?.signal)).value;
248
214
  checkControl(control);
249
- const seat = requireSeat(this.seat, square.body, name), now = square.clock();
215
+ const seat = this.seat, now = square.clock();
250
216
  return (await square.artifact.transactAs(participantAuthority(seat), facts => {
251
217
  const act = verb === 'listen' ? coreListen(facts, name, target, now) : verb === 'ignore' ? coreIgnore(facts, name, target, now) : coreUnlisten(facts, name, target, now);
252
218
  const activity = act === undefined ? null : toPublicActivity(facts.land(act));
253
219
  return { activity, ...(!options.observe ? {} : { observation: {
254
- ...square.observation(inSquareCount(facts), facts.hold().active, name, now), participant: name,
255
- requestedTarget: target, target: activity?.target ?? target,
220
+ ...square.observation(inSquareCount(facts), name, now), participant: name,
221
+ target: activity?.target ?? target,
256
222
  } }) };
257
223
  }, control?.signal)).value;
258
224
  }
@@ -263,7 +229,7 @@ export class SqliteSquare {
263
229
  const square = this.owner;
264
230
  return (await square.artifact.read(facts => {
265
231
  const name = resolveKnownName(facts, this.name);
266
- return { listening: coreListening(facts, name), ...(!options.observe ? {} : { observation: square.observation(inSquareCount(facts), facts.hold().active, name) }) };
232
+ return { listening: coreListening(facts, name), ...(!options.observe ? {} : { observation: square.observation(inSquareCount(facts), name) }) };
267
233
  }, control?.signal)).value;
268
234
  }
269
235
  /** Receipt selection rechecks the lease inside the writer, not at its last heartbeat. */
@@ -278,15 +244,14 @@ export class SqliteSquare {
278
244
  const square = this.owner;
279
245
  let name = this.name, subject = 'caller';
280
246
  let leaseId, seat;
281
- let waitStarted = false, replaced = false;
282
247
  let selection = options;
283
248
  const idle = options.idle ?? 0;
284
- const complete = async (caught, stop) => {
249
+ const complete = async (caught, reason = 'drained') => {
285
250
  const view = caught ?? (await square.artifact.read(facts => observeCatchSelection(facts, name, [], {
286
251
  unseenOnly: true, senders: selection.from, ...(selection.mention === true ? { attentionOnly: true } : {}),
287
252
  }, square.clock()))).value;
288
- if (stop === 'empty-now' || stop === undefined)
289
- stop = view.terminalStatus ?? stop;
253
+ if (reason === 'drained')
254
+ reason = view.terminalStatus ?? reason;
290
255
  if (leaseId !== undefined) {
291
256
  await releaseWatchLease(square.artifact, seat, leaseId).catch(() => undefined);
292
257
  leaseId = undefined;
@@ -298,13 +263,12 @@ export class SqliteSquare {
298
263
  }
299
264
  catch { /* Optional presence cannot erase the completed selection or receipts. */ }
300
265
  }
301
- const status = stop === 'already-active' || stop === 'replaced' || stop === 'capped' || stop === 'quorum' ? stop : undefined;
302
- return { activities: view.activities.map(activity => ({ ...toPublicActivity(activity), perception: 'full' })),
303
- consumedThrough: view.consumedThrough, remaining: view.remaining, idleExpired: stop === 'stale',
304
- ...(status === undefined ? {} : { status }), ...(view.hint === undefined ? {} : { hint: view.hint }), ...(!options.observe ? {} : { observation: {
305
- ...square.observation(view.standingCount, view.held, view.participant, view.now), participant: view.participant,
306
- sayNumbers: view.sayNumbers, ownActivityCount: view.ownActivityCount, hardCap: view.hardCap, stop,
307
- ...(presence === undefined ? { enrichmentUnavailable: true } : { presence }), waitStarted, replaced,
266
+ return { activities: view.activities, remaining: view.remaining, reason,
267
+ ...(view.hint === undefined ? {} : { hint: view.hint }), ...(!options.observe ? {} : { observation: {
268
+ ...square.observation(view.standingCount, view.participant, view.now), participant: view.participant,
269
+ deliveryAvailable: view.deliveryAvailable,
270
+ ownActivityCount: view.ownActivityCount, hardCap: view.hardCap,
271
+ ...(presence === undefined ? { enrichmentUnavailable: true } : { presence }),
308
272
  } }) };
309
273
  };
310
274
  try {
@@ -319,7 +283,8 @@ export class SqliteSquare {
319
283
  catchLimit(options.limit);
320
284
  const probe = (await square.artifact.read(facts => {
321
285
  name = resolveKnownName(facts, this.name);
322
- seat = requireSeat(this.seat, square.body, name);
286
+ seat = this.seat;
287
+ assertCurrentSeat(facts, asSeatRef(seat));
323
288
  subject = 'filter';
324
289
  const from = options.from?.map(target => resolveKnownName(facts, target));
325
290
  selection = { ...options, ...(from === undefined ? {} : { from }) };
@@ -331,7 +296,7 @@ export class SqliteSquare {
331
296
  }, control?.signal)).value;
332
297
  if (idle === 0) {
333
298
  const data = probe ?? (await this.catchPage(name, seat, selection, control));
334
- return await complete(data, data.activities.length === 0 ? 'empty-now' : undefined);
299
+ return await complete(data);
335
300
  }
336
301
  const watch = {
337
302
  ...(selection.from === undefined ? {} : { participants: [...selection.from] }), ...(options.mention ? { mention: name } : {}),
@@ -341,10 +306,9 @@ export class SqliteSquare {
341
306
  if (start.type === 'active')
342
307
  return await complete(undefined, 'already-active');
343
308
  leaseId = start.leaseId;
344
- waitStarted = true;
345
- replaced = start.replaced;
346
- control?.onProgress?.({ kind: 'catch-started', participant: name, idleMs: idle, replacementRequested: options.replace ?? false, replaced });
347
- let quietSince = square.clock(), wasHeld = false, nextHeartbeat = start.heartbeatAt + WATCH_HEARTBEAT_MS;
309
+ control?.onProgress?.({ kind: 'catch-started', participant: name, idleMs: idle, replacementRequested: options.replace ?? false, replaced: start.replaced });
310
+ const quietSince = square.clock();
311
+ let nextHeartbeat = start.heartbeatAt + WATCH_HEARTBEAT_MS;
348
312
  while (true) {
349
313
  checkControl(control);
350
314
  // Arm before selecting: a commit during selection must not be missed.
@@ -356,21 +320,16 @@ export class SqliteSquare {
356
320
  return await complete(undefined, pulse.status);
357
321
  if (pulse.heartbeatAt !== undefined)
358
322
  nextHeartbeat = pulse.heartbeatAt + WATCH_HEARTBEAT_MS;
359
- if (pulse.type === 'sleep') {
360
- const caught = await this.catchPage(name, seat, selection, control, leaseId);
361
- if (caught === null)
362
- return await complete(undefined, 'replaced');
363
- if (caught.activities.length > 0)
364
- return await complete(caught);
365
- }
366
- if (pulse.type === 'held' || wasHeld)
367
- quietSince = square.clock();
368
- wasHeld = pulse.type === 'held';
369
- if (!wasHeld && square.clock() - quietSince >= idle) {
323
+ const caught = await this.catchPage(name, seat, selection, control, leaseId);
324
+ if (caught === null)
325
+ return await complete(undefined, 'replaced');
326
+ if (caught.activities.length > 0)
327
+ return await complete(caught);
328
+ if (square.clock() - quietSince >= idle) {
370
329
  const owns = await ownsWatchLease(square.artifact, seat, square.clock(), leaseId, control?.signal);
371
- return await complete(undefined, owns ? 'stale' : 'replaced');
330
+ return await complete(undefined, owns ? 'idle' : 'replaced');
372
331
  }
373
- const deadline = Math.min(nextHeartbeat, wasHeld ? Infinity : quietSince + idle);
332
+ const deadline = Math.min(nextHeartbeat, quietSince + idle);
374
333
  await square.artifact.changed(baseline, Math.max(0, deadline - square.clock()), control?.signal);
375
334
  }
376
335
  }
@@ -386,7 +345,7 @@ export class SqliteSquare {
386
345
  async deferDelivery(input, control) {
387
346
  checkControl(control);
388
347
  const match = validateMetadataMatch(input?.match), duration = validateDeferralDuration(input?.durationMs);
389
- const square = this.owner, seat = requireSeat(this.seat, square.body, this.name);
348
+ const square = this.owner, seat = this.seat;
390
349
  return (await square.artifact.transactAs(participantAuthority(seat), facts => {
391
350
  const now = square.clock(), expiresAt = now + duration, id = crypto.randomUUID();
392
351
  const result = { id, expiresAt: new Date(expiresAt).toISOString() };
@@ -398,7 +357,7 @@ export class SqliteSquare {
398
357
  checkControl(control);
399
358
  validateDeferralId(id);
400
359
  const duration = validateDeferralDuration(durationMs), square = this.owner;
401
- const seat = requireSeat(this.seat, square.body, this.name);
360
+ const seat = this.seat;
402
361
  return (await square.artifact.transactAs(participantAuthority(seat), facts => {
403
362
  const now = square.clock(), expiresAt = now + duration;
404
363
  const result = { id, expiresAt: new Date(expiresAt).toISOString() };
@@ -408,55 +367,51 @@ export class SqliteSquare {
408
367
  async releaseDeliveryDeferral(id, control) {
409
368
  checkControl(control);
410
369
  validateDeferralId(id);
411
- const square = this.owner, seat = requireSeat(this.seat, square.body, this.name);
370
+ const square = this.owner, seat = this.seat;
412
371
  return (await square.artifact.transactAs(participantAuthority(seat), facts => facts.releaseDeliveryDeferral(asSeatRef(seat), id, square.clock()), control?.signal)).value;
413
372
  }
414
- history(query, control) { return this.owner.history(query, control); }
415
- async lifecycle(verb, body, options, control) {
416
- if (verb === 'done')
417
- validateDoneBody(body);
373
+ async done(body, options = {}, control) {
374
+ validateDoneBody(body);
418
375
  const square = this.owner;
419
376
  const name = (await square.artifact.read(facts => resolveKnownName(facts, this.name), control?.signal)).value;
420
- const seat = requireSeat(this.seat, square.body, name), now = square.clock();
377
+ const seat = this.seat, now = square.clock();
421
378
  return (await square.artifact.transactAs(participantAuthority(seat), facts => {
422
- const stored = facts.land(verb === 'done' ? coreDone(facts, name, body ?? '', now) : verb === 'hold' ? coreHold(facts, name, body ?? '', now) : coreResume(facts, name, now));
423
- return { activity: toPublicActivity(stored), ...(!options.observe ? {} : { observation: {
424
- ...square.observation(inSquareCount(facts), facts.hold().active, name, now), activity: stored,
425
- } }) };
379
+ const stored = facts.land(coreDone(facts, name, body ?? '', now));
380
+ return { activity: toPublicActivity(stored), ...(!options.observe ? {} : { observation: square.observation(inSquareCount(facts), name, now),
381
+ }) };
426
382
  }, control?.signal)).value;
427
383
  }
428
- hold(reason, options = {}, control) { return this.lifecycle('hold', reason, options, control); }
429
- resume(options = {}, control) { return this.lifecycle('resume', undefined, options, control); }
430
- done(body, options = {}, control) { return this.lifecycle('done', body, options, control); }
431
384
  };
432
- async participant(requested) {
433
- const selected = requested ?? this.defaultParticipant;
434
- if (selected !== undefined) {
435
- validateName(selected);
436
- const seat = this.body === undefined ? undefined : (await this.artifact.read(facts => facts.seat(selected))).value;
437
- return this.handle(selected, seat);
438
- }
439
- if (this.body !== undefined) {
440
- const seats = (await this.artifact.read(facts => facts.seatsForBody(this.body))).value;
441
- if (seats.length === 1)
442
- return this.handle(seats[0].participant, seats[0]);
443
- if (seats.length > 1)
444
- throw new SquareError('invalid_args', 'Square needs an explicit participant name: this body holds multiple names');
445
- }
446
- throw new SquareError('invalid_args', 'Square needs one unambiguous participant name');
385
+ async participant(name, { owner }) {
386
+ validateName(name);
387
+ requireOwner(owner);
388
+ return (await this.artifact.read(facts => {
389
+ const participant = facts.participant(name), seat = facts.seat(name);
390
+ if (!participant?.joined || seat === undefined || seat.owner !== owner || seat.attachment !== 'attached') {
391
+ const reason = participant === undefined ? 'has never stepped into this square'
392
+ : !participant.joined ? 'needs a current attached seat; join first'
393
+ : seat !== undefined && seat.owner !== owner ? 'is not held by this owner; join before writing'
394
+ : seat?.attachment === 'detached' ? 'is away — join again before writing'
395
+ : 'needs a current attached seat; join first';
396
+ throw new SquareError('already_joined', `${participantIdentity(participant?.name ?? name)} ${reason}`, {
397
+ reason: 'needs_seat', join: joinRecoveryCommand(this.location, participant?.name ?? name),
398
+ });
399
+ }
400
+ return this.handle(seat);
401
+ })).value;
447
402
  }
448
- async join(requested, options = {}, control) {
403
+ async join(requested, options, control) {
449
404
  let name = requested;
450
405
  try {
451
406
  checkControl(control);
452
407
  name = requireJoinName(requested);
453
- const last = options.last ?? HISTORY_DEFAULT_LIMIT;
408
+ const last = options?.last ?? HISTORY_DEFAULT_LIMIT;
454
409
  if (!Number.isSafeInteger(last) || last < 1 || last > HISTORY_MAX_LIMIT)
455
410
  throw new SquareError('invalid_args', 'Join history limit must be between 1 and 100');
456
- const body = requireBody(this.body), now = this.clock();
411
+ const owner = requireOwner(options?.owner), wakeAddress = options.wakeAddress, now = this.clock();
457
412
  const initial = !options.takeover ? undefined : (await this.artifact.read(facts => facts.participant(name)?.joined ? facts.seat(name) : undefined, control?.signal)).value;
458
- const authority = initial === undefined ? { kind: 'join', participant: name, body, wakeAddress: this.wakeAddress }
459
- : { kind: 'takeover', participant: initial.participant, body, expectedGeneration: initial.generation, wakeAddress: this.wakeAddress };
413
+ const authority = initial === undefined ? { kind: 'join', participant: name, owner, wakeAddress }
414
+ : { kind: 'takeover', participant: initial.participant, owner, expectedGeneration: initial.generation, wakeAddress };
460
415
  const committed = (await this.artifact.transactAs(authority, facts => {
461
416
  const participant = facts.participant(name)?.name ?? name;
462
417
  const current = facts.participant(participant), currentSeat = facts.seat(participant);
@@ -468,10 +423,12 @@ export class SqliteSquare {
468
423
  kind = 'taken-over';
469
424
  }
470
425
  else if (current?.joined) {
471
- if (currentSeat === undefined || !sameBody(currentSeat.body, body))
472
- throw new SquareError('already_joined', `${participantIdentity(participant)} is held by another body; take it over explicitly`);
473
- if (this.wakeAddress !== undefined && canRefreshWakeAddress(currentSeat.wakeAddress, this.wakeAddress))
474
- facts.updateWakeAddress(asSeatRef(currentSeat), this.wakeAddress);
426
+ if (currentSeat === undefined || currentSeat.owner !== owner)
427
+ throw new SquareError('already_joined', `${participantIdentity(participant)} is held by another owner; take it over explicitly`);
428
+ if (currentSeat.attachment === 'detached')
429
+ facts.reattachSeat(asSeatRef(currentSeat), wakeAddress);
430
+ else if (wakeAddress !== undefined && canRefreshWakeAddress(currentSeat.wakeAddress, wakeAddress))
431
+ facts.updateWakeAddress(asSeatRef(currentSeat), wakeAddress);
475
432
  kind = 'reconnected';
476
433
  }
477
434
  if (kind !== 'reconnected') {
@@ -483,11 +440,11 @@ export class SqliteSquare {
483
440
  const seat = facts.seat(participant);
484
441
  if (seat === undefined)
485
442
  throw new SquareError('invalid_args', 'The join activity did not establish its artifact seat.');
486
- return { participant: this.handle(seat.participant, seat), activity, kind,
487
- participantCount: facts.roster().filter(item => item.joined || item.done).length,
488
- ...(!options.observe ? {} : { observation: this.observation(inSquareCount(facts), facts.hold().active, seat.participant, now) }) };
443
+ return { participant: this.handle(seat), activity, kind,
444
+ ...(!options.observe ? {} : { observation: { ...this.observation(inSquareCount(facts), seat.participant, now),
445
+ deliveryAvailable: seat.wakeAddress !== undefined } }) };
489
446
  }, control?.signal)).value;
490
- await this.publishIdentity();
447
+ await this.publishSeat(owner);
491
448
  if (!options.observe)
492
449
  return committed;
493
450
  let entry;
@@ -501,30 +458,27 @@ export class SqliteSquare {
501
458
  throw failure(error, { operation: 'join', subject: 'caller', participant: name });
502
459
  }
503
460
  }
504
- async implicitJoin(name, control) {
461
+ /** Restore only a standing seat; a concurrent departure or takeover cannot be revived. */
462
+ async reattach(name, { owner, wakeAddress }, control) {
505
463
  checkControl(control);
506
464
  validateName(name);
507
- const body = requireBody(this.body), now = this.clock();
508
- const result = (await this.artifact.transactAs({ kind: 'join', participant: name, body, wakeAddress: this.wakeAddress }, facts => {
509
- const decision = decideImplicitJoin(facts, name, now);
510
- let seat = facts.seat(decision.joinedName);
511
- if (decision.joinAct === undefined) {
512
- if (decision.state === 'active' && (seat === undefined || !sameBody(seat.body, body)))
513
- throw new SquareError('already_joined', `${participantIdentity(decision.joinedName)} is held by another body`);
514
- if (decision.state === 'active' && this.wakeAddress !== undefined && canRefreshWakeAddress(seat.wakeAddress, this.wakeAddress))
515
- facts.updateWakeAddress(asSeatRef(seat), this.wakeAddress);
516
- }
517
- else {
518
- facts.land(decision.joinAct);
519
- seat = facts.seat(decision.joinedName);
520
- if (seat === undefined)
521
- throw new SquareError('invalid_args', 'The implicit join did not establish its artifact seat.');
522
- }
523
- return { state: decision.state, ...(decision.state === 'done' ? {} : { participant: this.handle(decision.joinedName, seat) }) };
465
+ requireOwner(owner);
466
+ const captured = (await this.artifact.read(facts => facts.seat(name), control?.signal)).value;
467
+ if (captured === undefined || captured.owner !== owner)
468
+ return null;
469
+ const seat = (await this.artifact.transactAs({ kind: 'join', participant: name, owner, wakeAddress }, facts => {
470
+ const current = facts.seat(name);
471
+ if (!facts.participant(name)?.joined || current === undefined || current.generation !== captured.generation || current.owner !== owner)
472
+ return null;
473
+ if (current.attachment === 'detached')
474
+ facts.reattachSeat(asSeatRef(current), wakeAddress);
475
+ else if (wakeAddress !== undefined && canRefreshWakeAddress(current.wakeAddress, wakeAddress))
476
+ facts.updateWakeAddress(asSeatRef(current), wakeAddress);
477
+ return facts.seat(name);
524
478
  }, control?.signal)).value;
525
- if (result.participant !== undefined)
526
- await this.publishIdentity();
527
- return result;
479
+ if (seat !== null)
480
+ await this.publishSeat(owner);
481
+ return seat === null ? null : this.handle(seat);
528
482
  }
529
483
  async snapshot(control) { return (await this.artifact.read(facts => snapshot(facts, this.clock()), control?.signal)).value; }
530
484
  async history(query = {}, control) {
@@ -555,78 +509,75 @@ export class SqliteSquare {
555
509
  if (indexes.includes(anchor))
556
510
  (presenceAnchors[anchor] ??= []).push(participant.name);
557
511
  }
558
- return { activities, observation: { ...this.observation(inSquareCount(facts), facts.hold().active), ...selected,
512
+ return { activities, observation: { ...this.observation(inSquareCount(facts)), ...selected,
559
513
  sayNumbers: facts.sayOrdinals(indexes), presenceAnchors } };
560
514
  }, control?.signal)).value;
561
515
  }
562
516
  async status(options = {}, control) {
563
- return (await this.artifact.read(facts => {
564
- const seats = this.body === undefined ? [] : facts.seatsForBody(this.body);
565
- const viewer = options.viewer ?? this.defaultParticipant ?? (seats.length === 1 ? seats[0].participant : '');
566
- return queryStatus(facts, {
567
- location: this.location, now: this.clock(), automaticDeliveryAvailable: this.automaticDelivery && this.body !== undefined,
568
- }, viewer, options.observe === true);
569
- }, control?.signal)).value;
517
+ return (await this.artifact.read(facts => queryStatus(facts, { location: this.location, now: this.clock() }, options.viewer, options.observe === true), control?.signal)).value;
570
518
  }
571
519
  async participants(options = {}, control) {
572
520
  return (await this.artifact.read(facts => queryParticipants(facts, {
573
- location: this.location, now: this.clock(), automaticDeliveryAvailable: this.automaticDelivery && this.body !== undefined,
521
+ location: this.location, now: this.clock(),
574
522
  }, options.observe === true), control?.signal)).value;
575
523
  }
576
524
  async recovery(requested, control) {
577
- const name = (await this.participant(requested).catch(() => undefined))?.name;
578
- const facts = name === undefined ? undefined : (await this.artifact.read(facts => recoveryObservation(facts, name, this.clock()), control?.signal).catch(() => undefined))?.value;
579
- return facts ?? await this.contextObservation(name, control);
525
+ const facts = requested === undefined ? undefined : (await this.artifact.read(facts => recoveryObservation(facts, requested, this.clock()), control?.signal).catch(() => undefined))?.value;
526
+ return facts ?? await this.contextObservation(requested, control);
580
527
  }
581
528
  stream(options, control) {
582
529
  // A path stream follows replacements independently of this connection's inode
583
530
  // and lifetime. Only explicit artifact readers borrow an existing port.
584
531
  return streamSquare(this.location, options, control);
585
532
  }
586
- async recognize() {
587
- if (this.body === undefined)
588
- return [];
589
- const candidates = (await this.artifact.read(facts => facts.seatsForBody(this.body))).value;
590
- return candidates.map(seat => this.handle(seat.participant, seat));
533
+ async seatsOf(owner) {
534
+ requireOwner(owner);
535
+ return (await this.artifact.read(facts => facts.seatsForOwner(owner).map(({ participant: name, generation, attachment }) => ({ name, generation, attachment })))).value;
591
536
  }
592
- close() { return this.ownsArtifact ? this.artifact.close() : Promise.resolve(); }
593
- async cancelDeliveries(name, expectedGeneration) {
594
- const body = this.body;
595
- if (body === undefined)
596
- return false;
537
+ close() { return this.closesArtifact ? this.artifact.close() : Promise.resolve(); }
538
+ async heldSeat(name, { owner, generation }) {
539
+ requireOwner(owner);
597
540
  const seat = (await this.artifact.read(facts => facts.seat(name))).value;
598
- if (seat === undefined || seat.generation !== expectedGeneration || !sameBody(seat.body, body))
599
- return false;
600
- return this.artifact.cancelDeliveries(asSeatRef(seat));
541
+ return seat?.generation === generation && seat.owner === owner ? seat : undefined;
542
+ }
543
+ async cancelDeliveries(name, identity) {
544
+ const seat = await this.heldSeat(name, identity);
545
+ return seat === undefined ? false : this.artifact.cancelDeliveries(asSeatRef(seat));
546
+ }
547
+ async detach(name, identity) {
548
+ const captured = await this.heldSeat(name, identity);
549
+ if (captured === undefined)
550
+ return null;
551
+ const seat = asSeatRef(captured);
552
+ return (await this.artifact.transactAs({ kind: 'host-cleanup', seat }, facts => facts.detachSeat(seat) ? true : null)).value;
601
553
  }
602
- async endOwnedSession(name, sessionId, expectedGeneration, body) {
603
- const captured = (await this.artifact.read(facts => facts.seat(name))).value;
604
- if (captured === undefined || captured.body.session !== sessionId || (body !== undefined && !sameBody(captured.body, body))
605
- || (expectedGeneration !== undefined && captured.generation !== expectedGeneration))
554
+ async endHeld(name, identity) {
555
+ const captured = await this.heldSeat(name, identity);
556
+ if (captured === undefined)
606
557
  return null;
607
- return (await this.artifact.transactAs(participantAuthority(captured), facts => {
558
+ return (await this.artifact.transactAs({ kind: 'host-cleanup', seat: asSeatRef(captured) }, facts => {
608
559
  const current = facts.seat(name);
609
- if (current === undefined || current.generation !== captured.generation || !sameBody(current.body, captured.body))
560
+ if (current === undefined || current.generation !== captured.generation || current.owner !== captured.owner)
610
561
  return null;
611
562
  return { activity: toPublicActivity(facts.land(coreDone(facts, current.participant, '', this.clock()))) };
612
563
  })).value;
613
564
  }
614
565
  }
615
- export function diagnoseSquare(input, control) { checkControl(control); return diagnoseSquareFile(localSquareLocation(input)); }
616
- export function migrateSquare(input, control) { checkControl(control); const env = input.env ?? process.env; return migrateSquareFile(localSquareLocation(input), control?.signal, env); }
566
+ export function diagnoseSquare(input, control) { checkControl(control); return diagnoseSquareFile(squareLocation(input)); }
567
+ export function migrateSquare(input, control) { checkControl(control); const env = input.env ?? process.env; return migrateSquareFile(squareLocation(input), control?.signal, env); }
617
568
  export function discover(input, options = {}, control) {
618
569
  if (input.path !== undefined || (input.env ?? process.env).SQUARE_LOCATION)
619
- localSquareLocation(input);
570
+ squareLocation(input);
620
571
  const env = { ...(input.env ?? process.env) };
621
572
  return discoverSquares(input.cwd ?? process.cwd(), options, control, { clock: squareClock(env, input.clock) });
622
573
  }
623
- export async function inbox(input, identity, options = {}, control) {
574
+ export async function inbox(input, owner, options = {}, control) {
624
575
  checkControl(control);
576
+ requireOwner(owner);
625
577
  const env = { ...(input.env ?? process.env) }, limit = options.limit ?? 20;
626
578
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
627
579
  throw new SquareError('invalid_args', 'Inbox limit must be between 1 and 100');
628
- const query = typeof identity === 'string' ? { sessionId: identity, env } : { body: identity, env };
629
- const rows = await sessionInboxCounts(query, control?.signal);
580
+ const rows = await sessionInboxCounts({ owner, env }, control?.signal);
630
581
  checkControl(control);
631
582
  const compare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
632
583
  rows.sort((a, b) => compare(a.squarePath, b.squarePath) || compare(nameKey(a.name), nameKey(b.name)) || compare(a.name, b.name));