@astrosheep/square 0.3.78 → 0.3.80

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 (70) hide show
  1. package/dist/attention-presentation.d.ts +2 -0
  2. package/dist/attention-presentation.js +39 -4
  3. package/dist/automatic-session.js +1 -1
  4. package/dist/boundary-presentation.js +4 -7
  5. package/dist/claude-mod.js +1 -1
  6. package/dist/cli/catch-presentation.d.ts +2 -2
  7. package/dist/cli/catch-presentation.js +3 -3
  8. package/dist/cli/context.d.ts +11 -1
  9. package/dist/cli/context.js +14 -3
  10. package/dist/cli/express-presentation.d.ts +6 -5
  11. package/dist/cli/express-presentation.js +42 -43
  12. package/dist/cli/maintenance-commands.js +6 -6
  13. package/dist/cli/mcp-server-command.js +1 -1
  14. package/dist/cli/observation-commands.d.ts +4 -4
  15. package/dist/cli/observation-commands.js +20 -16
  16. package/dist/cli/program.d.ts +1 -1
  17. package/dist/cli/program.js +5 -5
  18. package/dist/cli/square-commands.js +35 -23
  19. package/dist/decisions.d.ts +3 -5
  20. package/dist/decisions.js +10 -9
  21. package/dist/delivery.d.ts +1 -1
  22. package/dist/help.js +15 -2
  23. package/dist/inbox.js +3 -3
  24. package/dist/index.d.ts +1 -2
  25. package/dist/index.js +1 -2
  26. package/dist/ledger-maintenance.d.ts +1 -1
  27. package/dist/ledger-maintenance.js +1 -1
  28. package/dist/list.d.ts +3 -3
  29. package/dist/list.js +1 -1
  30. package/dist/mcp.d.ts +2 -2
  31. package/dist/mcp.js +12 -7
  32. package/dist/mention-parse.d.ts +2 -8
  33. package/dist/mention-parse.js +6 -9
  34. package/dist/model.d.ts +2 -2
  35. package/dist/notifications.js +24 -8
  36. package/dist/participant-host.js +5 -0
  37. package/dist/plugins/opencode/index.js +1 -1
  38. package/dist/square-actions.d.ts +22 -9
  39. package/dist/square-actions.js +26 -19
  40. package/dist/square-api.d.ts +43 -0
  41. package/dist/square-api.js +471 -0
  42. package/dist/square-facade.d.ts +123 -203
  43. package/dist/square-tools.d.ts +4 -3
  44. package/dist/square-tools.js +21 -15
  45. package/dist/stream.d.ts +2 -2
  46. package/dist/views.d.ts +16 -12
  47. package/dist/views.js +13 -27
  48. package/guides/application-demand-optimization.md +5 -0
  49. package/guides/application-facade-delivery-evidence.md +7 -2
  50. package/guides/mcp-connection-lifetime.md +2 -2
  51. package/guides/mcp.md +1 -1
  52. package/guides/operation-cancellation.md +2 -0
  53. package/guides/primitive-catch-consolidation.md +5 -0
  54. package/guides/primitive-history-consolidation.md +5 -0
  55. package/guides/primitive-status-consolidation.md +5 -0
  56. package/guides/primitive-storage-consolidation.md +5 -0
  57. package/guides/row-storage-design.md +1 -1
  58. package/guides/square-api.md +107 -0
  59. package/package.json +1 -1
  60. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  61. package/plugins/claude/skills/square/SKILL.md +4 -4
  62. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  63. package/plugins/opencode/index.ts +1 -1
  64. package/plugins/paseo/client/markdown.tsx +16 -6
  65. package/plugins/pi/square-pi.js +7 -6
  66. package/skills/square/SKILL.md +4 -4
  67. package/dist/square-application.d.ts +0 -38
  68. package/dist/square-application.js +0 -683
  69. package/guides/application-boundary.md +0 -32
  70. package/guides/application-facade-design.md +0 -98
@@ -1,5 +1,6 @@
1
+ import { type StoredAct } from './model.js';
1
2
  import type { WakeTransportPort } from './ports.js';
2
- import type { Activity, CatchOptions, ExpressOptions, ExpressResult, ExpressionObservation, ListenerChangeResult, OperationControl, OwnershipFenceOptions } from './square-facade.js';
3
+ import type { Activity, ActivityResult, CatchOptions, ExpressOptions, ExpressResult, ExpressionObservation, OperationControl, OwnershipFenceOptions, SquareObservation } from './square-facade.js';
3
4
  import { type CatchSelection } from './catch-decisions.js';
4
5
  import { type HostContext } from './participant-host.js';
5
6
  export interface OperationContext extends HostContext {
@@ -8,6 +9,7 @@ export interface OperationContext extends HostContext {
8
9
  export type { OwnershipFenceOptions };
9
10
  export declare function catchUp(square: OperationContext, name: string, options?: CatchOptions, control?: OperationControl): Promise<CatchSelection>;
10
11
  export declare function catchUp(square: OperationContext, name: string, options: CatchOptions, control: OperationControl | undefined, leaseId: string): Promise<CatchSelection | null>;
12
+ type LandingContext = Pick<SquareObservation, 'standingCount' | 'held' | 'now'>;
11
13
  export declare function join(square: OperationContext, name: string, control?: OperationControl, admission?: {
12
14
  readonly requireKnown?: boolean;
13
15
  }): Promise<{
@@ -15,28 +17,39 @@ export declare function join(square: OperationContext, name: string, control?: O
15
17
  readonly activity: Activity | null;
16
18
  readonly participantCount: number;
17
19
  readonly reconnected: boolean;
20
+ readonly observation: LandingContext;
18
21
  }>;
19
22
  /** Takeover holds the host CAS fence across the single done+join artifact transaction. */
20
- export declare function takeover(square: OperationContext, name: string, _oldSessionIds?: readonly string[], control?: OperationControl): Promise<{
23
+ export declare function takeover(square: OperationContext, name: string, control?: OperationControl): Promise<{
21
24
  readonly name: string;
22
25
  readonly activities: readonly Activity[];
23
26
  readonly participantCount: number;
24
27
  readonly epoch?: number;
28
+ readonly observation: LandingContext;
25
29
  }>;
26
30
  export declare function implicitJoin(square: OperationContext, name: string, control?: OperationControl): Promise<{
27
31
  readonly name: string;
28
32
  readonly state: 'joined' | 'active' | 'done';
29
33
  readonly activity: Activity | null;
30
34
  }>;
31
- export interface ExpressCommittedResult extends ExpressResult {
35
+ export interface ExpressCommittedResult extends Omit<ExpressResult, 'waited' | 'observation'> {
32
36
  readonly observation: ExpressionObservation;
33
37
  }
34
38
  export declare function express(square: OperationContext, name: string, body: string, options?: ExpressOptions, control?: OperationControl): Promise<ExpressCommittedResult>;
35
- export declare function listen(square: OperationContext, actor: string, target: string, control?: OperationControl): Promise<ListenerChangeResult>;
36
- export declare function ignore(square: OperationContext, actor: string, target: string, control?: OperationControl): Promise<ListenerChangeResult>;
39
+ export interface ListenerCommittedResult {
40
+ readonly activity: Activity | null;
41
+ readonly observation: LandingContext;
42
+ }
43
+ export declare function listen(square: OperationContext, actor: string, target: string, control?: OperationControl): Promise<ListenerCommittedResult>;
44
+ export declare function ignore(square: OperationContext, actor: string, target: string, control?: OperationControl): Promise<ListenerCommittedResult>;
37
45
  export declare function listening(square: OperationContext, actor: string, control?: OperationControl): Promise<readonly string[]>;
38
- export declare function done(square: OperationContext, name: string, body?: string, fence?: OwnershipFenceOptions, control?: OperationControl): Promise<ExpressResult>;
39
- export declare function endOwnedSession(square: OperationContext, name: string, sessionId: string, expectedEpoch?: number): Promise<ExpressResult | null>;
46
+ export interface LifecycleCommittedResult extends ActivityResult {
47
+ readonly observation: LandingContext & {
48
+ readonly activity: StoredAct;
49
+ };
50
+ }
51
+ export declare function done(square: OperationContext, name: string, body?: string, fence?: OwnershipFenceOptions, control?: OperationControl): Promise<LifecycleCommittedResult>;
52
+ export declare function endOwnedSession(square: OperationContext, name: string, sessionId: string, expectedEpoch?: number): Promise<ActivityResult | null>;
40
53
  export declare function retireEndedSessionRoutes(square: OperationContext, sessionId: string): Promise<void>;
41
- export declare function hold(square: OperationContext, name: string, reason?: string, control?: OperationControl): Promise<ExpressResult>;
42
- export declare function resume(square: OperationContext, name: string, control?: OperationControl): Promise<ExpressResult>;
54
+ export declare function hold(square: OperationContext, name: string, reason?: string, control?: OperationControl): Promise<LifecycleCommittedResult>;
55
+ export declare function resume(square: OperationContext, name: string, control?: OperationControl): Promise<LifecycleCommittedResult>;
@@ -40,21 +40,23 @@ export async function join(square, name, control, admission = {}) {
40
40
  const preview = (await square.artifact.read((facts) => {
41
41
  // Express may reenter a known participant, but must never create a new name.
42
42
  const selected = admission.requireKnown ? resolveKnownName(facts, name) : name;
43
+ const now = square.clock();
43
44
  return {
44
- ...decideJoin(facts, selected, square.clock()),
45
+ ...decideJoin(facts, selected, now),
45
46
  participantCount: facts.roster().filter((p) => p.joined || p.done).length,
47
+ observation: { standingCount: inSquareCount(facts), held: facts.hold().active, now },
46
48
  };
47
49
  }, control?.signal)).value;
48
50
  name = preview.joinedName;
49
51
  if (preview.joinAct === undefined) {
50
52
  if (hostLedger === undefined)
51
- return { name: preview.joinedName, activity: null, participantCount: preview.participantCount, reconnected: false };
53
+ return { name: preview.joinedName, activity: null, participantCount: preview.participantCount, reconnected: false, observation: preview.observation };
52
54
  const identity = processIdentity(square.env ?? process.env);
53
55
  const owner = await readParticipantOwner(square.location, preview.joinedName, hostLedger);
54
56
  if (owner?.session === identity.session)
55
57
  return {
56
58
  name: preview.joinedName, activity: null, participantCount: preview.participantCount,
57
- reconnected: identity.channel !== 'unknown',
59
+ reconnected: identity.channel !== 'unknown', observation: preview.observation,
58
60
  };
59
61
  // Missing or foreign owner must pass CAS, not become a silent reconnect.
60
62
  }
@@ -80,6 +82,7 @@ export async function join(square, name, control, admission = {}) {
80
82
  return {
81
83
  name: decision.joinedName, stored,
82
84
  participantCount: facts.roster().filter((p) => p.joined || p.done).length,
85
+ observation: { standingCount: inSquareCount(facts), held: facts.hold().active, now },
83
86
  };
84
87
  }, control?.signal)).value;
85
88
  }
@@ -91,11 +94,11 @@ export async function join(square, name, control, admission = {}) {
91
94
  await publishCommittedIdentity(square, committed.name, epoch);
92
95
  return {
93
96
  name: committed.name, activity: committed.stored === null ? null : toPublicActivity(committed.stored),
94
- participantCount: committed.participantCount, reconnected: false,
97
+ participantCount: committed.participantCount, reconnected: false, observation: committed.observation,
95
98
  };
96
99
  }
97
100
  /** Takeover holds the host CAS fence across the single done+join artifact transaction. */
98
- export async function takeover(square, name, _oldSessionIds = [], control) {
101
+ export async function takeover(square, name, control) {
99
102
  throwIfAborted(control);
100
103
  validateName(name);
101
104
  const hostLedger = square.hostLedger;
@@ -113,6 +116,7 @@ export async function takeover(square, name, _oldSessionIds = [], control) {
113
116
  return {
114
117
  name: joinedName, stored: [storedDone, storedJoin],
115
118
  participantCount: facts.roster().filter((p) => p.joined || p.done).length,
119
+ observation: { standingCount: inSquareCount(facts), held: facts.hold().active, now },
116
120
  };
117
121
  }, control?.signal)).value;
118
122
  };
@@ -131,11 +135,11 @@ export async function takeover(square, name, _oldSessionIds = [], control) {
131
135
  }, control?.signal);
132
136
  if (outcome.status === 'busy')
133
137
  throw new SquareError('already_joined', `${participantIdentity(name)} already stands here — another session holds the name`);
134
- return { name: outcome.result.name, activities: outcome.result.stored.map(toPublicActivity), participantCount: outcome.result.participantCount, epoch: outcome.epoch };
138
+ return { name: outcome.result.name, activities: outcome.result.stored.map(toPublicActivity), participantCount: outcome.result.participantCount, epoch: outcome.epoch, observation: outcome.result.observation };
135
139
  }
136
140
  const committed = await commitLifecycle();
137
141
  await publishCommittedIdentity(square, committed.name);
138
- return { name: committed.name, activities: committed.stored.map(toPublicActivity), participantCount: committed.participantCount };
142
+ return { name: committed.name, activities: committed.stored.map(toPublicActivity), participantCount: committed.participantCount, observation: committed.observation };
139
143
  }
140
144
  export async function implicitJoin(square, name, control) {
141
145
  throwIfAborted(control);
@@ -185,14 +189,16 @@ export async function express(square, name, body, options = {}, control) {
185
189
  }
186
190
  catch (error) {
187
191
  if (isSquareError(error))
188
- error.facts = { ...error.facts, reason: 'invalid_reply', activityId: options.reply };
192
+ error.facts = {
193
+ ...error.facts, reason: 'invalid_reply', activityId: options.reply,
194
+ };
189
195
  throw error;
190
196
  }
191
197
  });
192
198
  const committed = (await square.artifact.transact((facts) => {
193
199
  // Selected-row decoding is storage work, not evidence that admission safely refused.
194
200
  const proposed = decideAct(facts, { name, body, force: options.force ?? false, now, mentions: options.mentions,
195
- ...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...('requireExplicitReach' in options ? { requireExplicitReach: options.requireExplicitReach === true } : {}), ...(reply === undefined ? {} : { reply }) });
201
+ ...(options.reach === undefined ? {} : { reach: options.reach }), ...(options.noMention === undefined ? {} : { noMention: options.noMention }), ...(reply === undefined ? {} : { reply }) });
196
202
  const holder = proposed.type === 'held' ? facts.hold().actor : undefined;
197
203
  const decision = rejectUnsentActivity(() => {
198
204
  const decision = proposed;
@@ -216,6 +222,7 @@ export async function express(square, name, body, options = {}, control) {
216
222
  standingCount: inSquareCount(facts), held: facts.hold().active, now,
217
223
  ownActivityCount: facts.participant(name).sayCount, hardCap: facts.header().hardCap,
218
224
  },
225
+ ...(decision.unmatchedMentions === undefined ? {} : { unmatchedMentions: decision.unmatchedMentions }),
219
226
  ...(decision.replyAuthorNotHere === undefined ? {} : { replyAuthorNotHere: decision.replyAuthorNotHere }),
220
227
  };
221
228
  }, control?.signal)).value;
@@ -224,19 +231,18 @@ export async function express(square, name, body, options = {}, control) {
224
231
  ? await deliverPending({ artifact: square.artifact, hostLedger: square.hostLedger, transport: square.wakeTransport, location: square.location, activity: committed.stored.index, now })
225
232
  .catch(() => ({ attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 }))
226
233
  : { attempted: 0, accepted: 0, failed: 0, unknown: 0, notCapable: 1 };
227
- return {
228
- activity: toPublicActivity(committed.stored), delivery, observation: committed.observation,
229
- ...(committed.replyAuthorNotHere === undefined ? {} : { replyAuthorNotHere: committed.replyAuthorNotHere }),
230
- };
234
+ const { stored, observation, ...metadata } = committed;
235
+ return { activity: toPublicActivity(stored), delivery, observation, ...metadata };
231
236
  }
232
237
  async function landListenerChange(square, verb, actor, target, control) {
233
238
  throwIfAborted(control);
234
239
  const now = square.clock();
235
- const stored = (await square.artifact.transact((facts) => {
240
+ const committed = (await square.artifact.transact((facts) => {
236
241
  const act = verb === 'listen' ? coreListen(facts, actor, target, now) : coreIgnore(facts, actor, target, now);
237
- return act === undefined ? null : facts.land(act);
242
+ const stored = act === undefined ? null : facts.land(act);
243
+ return { stored, observation: { standingCount: inSquareCount(facts), held: facts.hold().active, now } };
238
244
  }, control?.signal)).value;
239
- return { activity: stored === null ? null : toPublicActivity(stored) };
245
+ return { activity: committed.stored === null ? null : toPublicActivity(committed.stored), observation: committed.observation };
240
246
  }
241
247
  export function listen(square, actor, target, control) { return landListenerChange(square, 'listen', actor, target, control); }
242
248
  export function ignore(square, actor, target, control) { return landListenerChange(square, 'ignore', actor, target, control); }
@@ -256,7 +262,9 @@ async function landCore(square, verb, actor, body = '', fence = {}, control) {
256
262
  const result = facts.land(verb === 'done' ? coreDone(facts, actor, body, now) : verb === 'hold' ? coreHold(facts, actor, body, now) : coreResume(facts, actor, now));
257
263
  if (session !== undefined)
258
264
  dropEndedSessionWakeRoutes(facts, square.location, session, { expectedEpoch: fence.expectedEpoch, force: true, participant: actor });
259
- return result;
265
+ return { activity: toPublicActivity(result), observation: {
266
+ activity: result, standingCount: inSquareCount(facts), held: facts.hold().active, now,
267
+ } };
260
268
  }, control?.signal)).value;
261
269
  for (const row of owners)
262
270
  await hostLedger.removePresenceIfUnchanged(row).catch((error) => {
@@ -264,8 +272,7 @@ async function landCore(square, verb, actor, body = '', fence = {}, control) {
264
272
  });
265
273
  return stored;
266
274
  };
267
- const stored = hostLedger === undefined ? await commitAndCleanup() : await hostLedger.withClaimLock(commitAndCleanup, control?.signal);
268
- return { activity: toPublicActivity(stored) };
275
+ return hostLedger === undefined ? commitAndCleanup() : hostLedger.withClaimLock(commitAndCleanup, control?.signal);
269
276
  }
270
277
  export function done(square, name, body = '', fence = {}, control) { return landCore(square, 'done', name, body, fence, control); }
271
278
  function liveClaimedParticipants(rows, sessionId) {
@@ -0,0 +1,43 @@
1
+ import type { ActivityResult, HistoryQuery, HistoryResult, JoinOptions, JoinResult, ObservationOptions, OperationControl, Participant, SquareAtInput, SquareBuildInput, SquareLocation, StatusOptions, StatusResult, ParticipantsResult, RecoveryResult, DiscoveryOptions, InboxOptions, InboxResult, StreamOptions } from './square-facade.js';
2
+ export type * from './square-facade.js';
3
+ export { createSquareResourceOwner } from './open-square.js';
4
+ export { formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE } from './square-core.js';
5
+ export { CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT } from './catch-decisions.js';
6
+ export { HELD_WAIT_BUDGET_MS } from './runtime.js';
7
+ export { HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT } from './views.js';
8
+ export { DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from './list.js';
9
+ export declare function squareLocation(input: SquareLocation): string;
10
+ export declare function squareClock(env: NodeJS.ProcessEnv, clock?: () => number): () => number;
11
+ /** One concrete square resource. Request handles may borrow a server-owned connection. */
12
+ export declare class Square {
13
+ readonly location: string;
14
+ private readonly square;
15
+ private readonly defaultParticipant?;
16
+ private readonly transport;
17
+ private constructor();
18
+ static at(input: SquareAtInput, control?: OperationControl): Promise<Square>;
19
+ static build(input: SquareBuildInput, control?: OperationControl): Promise<Square>;
20
+ static inMemory(input: Omit<SquareBuildInput, 'path' | 'resources'>): Square;
21
+ private handle;
22
+ participant(requested?: string): Promise<Participant>;
23
+ join(requested?: string, options?: JoinOptions, control?: OperationControl): Promise<JoinResult>;
24
+ doneOwnedSession(name: string, body: string, expectedEpoch: number, control?: OperationControl): Promise<ActivityResult>;
25
+ implicitJoin(name: string, control?: OperationControl): Promise<{
26
+ readonly state: 'joined' | 'active' | 'done';
27
+ readonly participant?: Participant;
28
+ }>;
29
+ snapshot(control?: OperationControl): Promise<import("./square-facade.js").SquareSnapshot>;
30
+ history(query?: HistoryQuery, control?: OperationControl): Promise<HistoryResult>;
31
+ status(options?: StatusOptions, control?: OperationControl): Promise<StatusResult>;
32
+ participants(options?: ObservationOptions, control?: OperationControl): Promise<ParticipantsResult>;
33
+ recovery(requested?: string, control?: OperationControl): Promise<RecoveryResult>;
34
+ stream(options: StreamOptions, control?: OperationControl): AsyncIterable<import("./square-facade.js").StreamRecord>;
35
+ recognize(env: NodeJS.ProcessEnv): Promise<Participant | null>;
36
+ close(): Promise<void>;
37
+ endOwnedSession(name: string, sessionId: string, expectedEpoch?: number): Promise<ActivityResult | null>;
38
+ retireEndedSessionRoutes(sessionId: string): Promise<void>;
39
+ }
40
+ export declare function diagnoseSquare(input: SquareLocation, control?: OperationControl): Promise<import("./artifact.js").DiagnoseResult>;
41
+ export declare function migrateSquare(input: SquareLocation, control?: OperationControl): Promise<import("./square-migration.js").MigrationOutcome>;
42
+ export declare function discover(input: SquareAtInput, options?: DiscoveryOptions, control?: OperationControl): Promise<import("./square-facade.js").DiscoveryResult>;
43
+ export declare function inbox(input: SquareAtInput, sessionId: string, options?: InboxOptions, control?: OperationControl): Promise<InboxResult>;