@astrosheep/square 0.3.30 → 0.3.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/claude-plugin/.claude-plugin/plugin.json +1 -1
  2. package/claude-plugin/hooks/hooks.json +0 -3
  3. package/claude-plugin/skills/square/SKILL.md +5 -4
  4. package/codex-plugin/.codex-plugin/plugin.json +1 -1
  5. package/dist/activity.js +8 -3
  6. package/dist/artifact.js +10 -51
  7. package/dist/automatic-session.js +49 -14
  8. package/dist/boundary-presentation.d.ts +1 -1
  9. package/dist/boundary-presentation.js +58 -14
  10. package/dist/catch-decisions.d.ts +17 -0
  11. package/dist/catch-decisions.js +53 -0
  12. package/dist/claude-hook.d.ts +2 -1
  13. package/dist/claude-hook.js +5 -2
  14. package/dist/cli/context.js +10 -2
  15. package/dist/cli/observation-commands.d.ts +5 -1
  16. package/dist/cli/observation-commands.js +68 -33
  17. package/dist/cli/square-commands.js +18 -12
  18. package/dist/codex-hook.d.ts +2 -1
  19. package/dist/codex-hook.js +5 -2
  20. package/dist/codex-queue.js +1 -1
  21. package/dist/decisions.js +2 -2
  22. package/dist/delivery-health.d.ts +1 -1
  23. package/dist/delivery-operations.d.ts +25 -0
  24. package/dist/delivery-operations.js +207 -0
  25. package/dist/delivery.d.ts +1 -0
  26. package/dist/help.js +1 -1
  27. package/dist/host-ledger-file-adapter.d.ts +34 -0
  28. package/dist/host-ledger-file-adapter.js +156 -0
  29. package/dist/host-ledger.d.ts +160 -0
  30. package/dist/host-ledger.js +1 -0
  31. package/dist/inbox.d.ts +2 -2
  32. package/dist/inbox.js +22 -14
  33. package/dist/index.d.ts +4 -1
  34. package/dist/index.js +1 -0
  35. package/dist/landing.d.ts +18 -14
  36. package/dist/landing.js +29 -113
  37. package/dist/model.d.ts +9 -17
  38. package/dist/model.js +2 -2
  39. package/dist/notifications.d.ts +12 -10
  40. package/dist/notifications.js +122 -190
  41. package/dist/open-square.d.ts +5 -4
  42. package/dist/open-square.js +1 -1
  43. package/dist/paseo-delivery.js +2 -0
  44. package/dist/ports.d.ts +138 -0
  45. package/dist/ports.js +1 -0
  46. package/dist/presence.d.ts +1 -2
  47. package/dist/presence.js +13 -46
  48. package/dist/presentation-operations.d.ts +3 -0
  49. package/dist/presentation-operations.js +51 -0
  50. package/dist/presentation.d.ts +2 -2
  51. package/dist/presentation.js +11 -7
  52. package/dist/presented.d.ts +1 -12
  53. package/dist/presented.js +6 -75
  54. package/dist/registry.d.ts +10 -10
  55. package/dist/registry.js +47 -113
  56. package/dist/routes.d.ts +27 -30
  57. package/dist/routes.js +88 -151
  58. package/dist/runtime.d.ts +1 -1
  59. package/dist/runtime.js +3 -4
  60. package/dist/square-actions.d.ts +33 -0
  61. package/dist/square-actions.js +204 -0
  62. package/dist/square-facade.d.ts +10 -7
  63. package/dist/square-file-adapter.d.ts +5 -3
  64. package/dist/square-file-adapter.js +23 -5
  65. package/dist/square-projections.d.ts +68 -0
  66. package/dist/square-projections.js +92 -0
  67. package/dist/square-storage.d.ts +2 -2
  68. package/dist/square-storage.js +2 -2
  69. package/dist/square-wiring.d.ts +3 -3
  70. package/dist/square-wiring.js +44 -29
  71. package/dist/views.d.ts +8 -2
  72. package/dist/views.js +28 -24
  73. package/dist/wake-attempts.d.ts +29 -22
  74. package/dist/wake-attempts.js +36 -119
  75. package/dist/wake-evidence.d.ts +6 -18
  76. package/dist/wake-evidence.js +17 -80
  77. package/dist/wake-port.js +1 -1
  78. package/dist/wakes.d.ts +2 -16
  79. package/dist/wakes.js +7 -27
  80. package/dist/watch.js +2 -3
  81. package/extensions/square-pi.js +7 -2
  82. package/package.json +1 -1
  83. package/skills/brainstorm/SKILL.md +2 -2
  84. package/skills/square/SKILL.md +5 -4
package/dist/landing.js CHANGED
@@ -1,126 +1,42 @@
1
- import { extractMentions, formatActivityId, parseActivityId } from './square-core.js';
2
- import { coreDone, coreHold, coreIgnore, coreListen, coreListening, coreResume, decideAct, decideImplicitJoin, decideJoin } from './decisions.js';
3
- import { deriveDeliveryModel } from './delivery.js';
4
- import { SquareError } from './model.js';
5
- import { participantIdentity } from './participant-identity.js';
6
- function storeActs(state, acts) {
7
- const stored = [];
8
- for (const act of acts) {
9
- const item = { ...act, index: state.runtime.nextActIndex };
10
- state.runtime.nextActIndex += 1;
11
- state.acts.push(item);
12
- stored.push(item);
13
- }
14
- return stored;
15
- }
16
- function committedActivity(stored, verb) {
17
- const activity = stored[0];
18
- if (activity === undefined)
19
- throw new Error(`${verb} activity did not commit`);
20
- return activity;
21
- }
22
- function exposeActivity(stored) {
23
- if (stored.kind === 'read' || stored.actor === undefined)
24
- throw new Error(`Cannot expose stored activity ${formatActivityId(stored.index)}`);
1
+ import { done as applyDone, express as applyExpress, hold as applyHold, ignore as applyIgnore, implicitJoin as applyImplicitJoin, join as applyJoin, listen as applyListen, listening as applyListening, resume as applyResume, } from './square-actions.js';
2
+ function artifactOf(square) {
3
+ if ('artifact' in square)
4
+ return square.artifact;
5
+ const { cell } = square;
25
6
  return {
26
- id: formatActivityId(stored.index), at: stored.at, kind: stored.kind, actor: stored.actor,
27
- ...('body' in stored && stored.body !== undefined ? { body: stored.body } : {}),
28
- mentions: stored.kind === 'say' ? extractMentions(stored.body) : [],
29
- ...('target' in stored ? { target: stored.target } : {}),
30
- ...(stored.kind === 'say' && stored.reply !== undefined ? { reply: formatActivityId(stored.reply) } : {}),
7
+ read: () => cell.read(),
8
+ transact: (fn) => cell.transact(fn),
9
+ changed: (sinceVersion, timeoutMs) => cell.changed(sinceVersion, timeoutMs),
10
+ close: () => cell.close(),
31
11
  };
32
12
  }
33
- function parseRequiredActivityId(id) {
34
- const index = parseActivityId(id);
35
- if (index === undefined)
36
- throw new SquareError('invalid_args', `Invalid activity id: ${id}`);
37
- return index;
38
- }
39
- async function wakeAfterCommit(square, recipients, activity) {
40
- if (recipients.length === 0)
41
- return;
42
- try {
43
- square.notifier?.wake(recipients, activity);
44
- }
45
- catch { /* post-commit effects cannot undo activities */ }
13
+ function contextOf(square) {
14
+ return { artifact: artifactOf(square), clock: square.clock, ...('location' in square ? { location: square.location, hostLedger: square.hostLedger, env: square.env } : {}) };
46
15
  }
47
- export async function join(square, name) {
48
- const now = square.clock();
49
- const committed = await square.cell.transact((state) => {
50
- const decision = decideJoin(state, name, now);
51
- if (decision.joinAct === undefined)
52
- return { result: { name: decision.joinedName, stored: null } };
53
- return { state, result: { name: decision.joinedName, stored: committedActivity(storeActs(state, [decision.joinAct]), 'join') } };
54
- });
55
- return { name: committed.name, activity: committed.stored === null ? null : exposeActivity(committed.stored) };
16
+ export function join(square, name) {
17
+ return applyJoin(contextOf(square), name);
56
18
  }
57
- /** Automatic presence distinguishes first entry, current presence, and completed presence. */
58
- export async function implicitJoin(square, name) {
59
- const now = square.clock();
60
- const committed = await square.cell.transact((state) => {
61
- const decision = decideImplicitJoin(state, name, now);
62
- if (decision.joinAct === undefined)
63
- return { result: { name: decision.joinedName, state: decision.state, stored: null } };
64
- return { state, result: { name: decision.joinedName, state: decision.state, stored: committedActivity(storeActs(state, [decision.joinAct]), 'join') } };
65
- });
66
- return { name: committed.name, state: committed.state, activity: committed.stored === null ? null : exposeActivity(committed.stored) };
19
+ export function implicitJoin(square, name) {
20
+ return applyImplicitJoin(contextOf(square), name);
67
21
  }
68
- export async function express(square, name, body, options = {}) {
69
- const now = square.clock();
70
- const reply = options.reply === undefined ? undefined : parseRequiredActivityId(options.reply);
71
- const committed = await square.cell.transact((state) => {
72
- const decision = decideAct(state, { name, body, force: options.force ?? false, now, ...(options.reach === undefined ? {} : { reach: options.reach }), ...(reply === undefined ? {} : { reply }) });
73
- if (decision.type === 'blocked') {
74
- const pending = decision.activitySummaries.reduce((count, summary) => count + summary.count, 0) + decision.unreadRoomChanges.length;
75
- throw new SquareError('behind', `${participantIdentity(name)} has pending activity`, { pending });
76
- }
77
- if (decision.type === 'held') {
78
- const holder = state.acts.filter((activity) => activity.kind === 'hold').at(-1)?.actor;
79
- throw new SquareError('held', 'The square is held', holder === undefined ? undefined : { holder });
80
- }
81
- if (decision.type === 'capped')
82
- throw new SquareError('capped', `${participantIdentity(name)} reached the activity cap`);
83
- if (decision.type === 'throttled')
84
- throw new SquareError('throttled', `${name} is throttled`, { retryAfterMs: decision.delayMs });
85
- if (decision.type === 'bell_quota')
86
- throw new SquareError('bell_quota', `${participantIdentity(name)} cannot ring the bell yet`, { retryAfterMs: Math.max(1, decision.nextAt - now) });
87
- const stored = committedActivity(storeActs(state, [decision.act]), 'express');
88
- return { state, result: { stored, recipients: deriveDeliveryModel(state).plan(stored).map((notification) => notification.recipient) } };
89
- });
90
- const activity = exposeActivity(committed.stored);
91
- await wakeAfterCommit(square, committed.recipients, activity);
92
- return { activity };
93
- }
94
- async function landListenerChange(square, verb, actor, target) {
95
- const now = square.clock();
96
- const stored = await square.cell.transact((state) => {
97
- const act = verb === 'listen'
98
- ? coreListen(state, actor, target, now)
99
- : coreIgnore(state, actor, target, now);
100
- if (act === undefined)
101
- return { result: null };
102
- return { state, result: committedActivity(storeActs(state, [act]), verb) };
103
- });
104
- return { activity: stored === null ? null : exposeActivity(stored) };
22
+ export function express(square, name, body, options) {
23
+ return applyExpress(contextOf(square), name, body, options);
105
24
  }
106
25
  export function listen(square, actor, target) {
107
- return landListenerChange(square, 'listen', actor, target);
26
+ return applyListen(contextOf(square), actor, target);
108
27
  }
109
28
  export function ignore(square, actor, target) {
110
- return landListenerChange(square, 'ignore', actor, target);
29
+ return applyIgnore(contextOf(square), actor, target);
30
+ }
31
+ export function listening(square, actor) {
32
+ return applyListening(contextOf(square), actor);
33
+ }
34
+ export function done(square, name, body = '') {
35
+ return applyDone(contextOf(square), name, body);
111
36
  }
112
- export async function listening(square, actor) {
113
- const { state } = await square.cell.read();
114
- return coreListening(state, actor);
37
+ export function hold(square, name, reason = '') {
38
+ return applyHold(contextOf(square), name, reason);
115
39
  }
116
- async function landCore(square, verb, actor, body = '') {
117
- const now = square.clock();
118
- const stored = await square.cell.transact((state) => {
119
- const act = verb === 'done' ? coreDone(state, actor, body, now) : verb === 'hold' ? coreHold(state, actor, body, now) : coreResume(state, actor, now);
120
- return { state, result: committedActivity(storeActs(state, [act]), verb) };
121
- });
122
- return { activity: exposeActivity(stored) };
40
+ export function resume(square, name) {
41
+ return applyResume(contextOf(square), name);
123
42
  }
124
- export function done(square, name, body = '') { return landCore(square, 'done', name, body); }
125
- export function hold(square, name, reason = '') { return landCore(square, 'hold', name, reason); }
126
- export function resume(square, name) { return landCore(square, 'resume', name); }
package/dist/model.d.ts CHANGED
@@ -5,12 +5,16 @@ export declare const WAKE_ROUTE_KINDS: readonly ["opencode-server", "codex-queue
5
5
  export type WakeRouteKind = typeof WAKE_ROUTE_KINDS[number];
6
6
  export declare function isWakeRouteKind(value: unknown): value is WakeRouteKind;
7
7
  export interface WakeRoute {
8
- ownerId: string;
8
+ location: string;
9
+ participant: string;
9
10
  sessionId: string;
11
+ channel: string;
10
12
  kind: WakeRouteKind;
11
13
  address: Record<string, string>;
12
14
  updatedAt: number;
13
15
  }
16
+ export interface ReceiverRoute extends WakeRoute {
17
+ }
14
18
  export type SquareErrorCode = 'invalid_name' | 'invalid_args' | 'unknown_participant' | 'not_joined' | 'already_joined' | 'already_done' | 'held' | 'capped' | 'throttled' | 'bell_quota' | 'behind' | 'io' | 'unavailable';
15
19
  export type InternalSquareErrorCode = SquareErrorCode | 'not_found' | 'cap_reached' | 'conflict' | 'pending_peer';
16
20
  export interface SquareErrorFacts {
@@ -40,11 +44,10 @@ export type StoredAct = Act & {
40
44
  at: number;
41
45
  };
42
46
  export type StoredActHead = StoredAct extends infer T ? T extends StoredAct ? Omit<T, 'body' | 'through' | 'index'> : never : never;
43
- export type ObservationState = 'notified' | 'seen';
47
+ export type ObservationState = 'seen';
44
48
  export interface ActivityObservation {
45
49
  state: ObservationState;
46
50
  at: number;
47
- ownerId?: string;
48
51
  }
49
52
  export interface WatchLeaseFilter {
50
53
  participants?: string[];
@@ -52,8 +55,6 @@ export interface WatchLeaseFilter {
52
55
  }
53
56
  export interface WatchLease {
54
57
  leaseId: string;
55
- /** Machine-local owner that may claim automatic delivery for this lease. */
56
- ownerId?: string;
57
58
  heartbeatAt: number;
58
59
  expiresAt: number;
59
60
  filter?: WatchLeaseFilter;
@@ -69,22 +70,13 @@ export interface InboxNotification {
69
70
  export interface InboxMembership {
70
71
  name: string;
71
72
  squarePath: string;
72
- ownerId?: string;
73
73
  notifications: InboxNotification[];
74
74
  catchLease?: WatchLease;
75
75
  }
76
- export interface NotifyLease {
77
- leaseId: string;
78
- expiresAt: number;
79
- phase: 'claimed' | 'dispatching';
80
- attemptN?: number;
81
- routeKind?: WakeRouteKind;
82
- }
83
76
  export interface SquareRuntimeState {
84
77
  nextActIndex: number;
85
78
  observations: Record<string, Record<string, ActivityObservation>>;
86
79
  leases: Record<string, WatchLease>;
87
- notifyLeases: Record<string, NotifyLease>;
88
80
  }
89
81
  export interface SquareState {
90
82
  hardCap: HardCap;
@@ -92,17 +84,18 @@ export interface SquareState {
92
84
  preamble: string[];
93
85
  warmup: string[];
94
86
  acts: StoredAct[];
87
+ routes?: ReceiverRoute[];
95
88
  runtime: SquareRuntimeState;
96
89
  }
97
90
  export interface ActivitiesOptions {
98
91
  lastN?: number | null;
99
92
  participants?: string[];
100
- /** Exclusive upper bound on act.at (ms). */
101
- before?: number;
102
93
  /** Exclusive lower bound on act.at (ms). Alias of --since. */
103
94
  after?: number;
104
95
  /** Exclusive lower bound on stable act index (--after act/<index>). */
105
96
  afterIndex?: number;
97
+ /** Exclusive upper bound on stable act index (--before act/<index>). */
98
+ beforeIndex?: number;
106
99
  /** Center act indexes for context windows (--at). */
107
100
  atIndexes?: number[];
108
101
  beforeContext?: number;
@@ -111,7 +104,6 @@ export interface ActivitiesOptions {
111
104
  /** Undelivered mention/bell items for viewer only (read-only; requires viewer). */
112
105
  pending?: boolean;
113
106
  viewer?: string;
114
- full?: boolean;
115
107
  grep?: string;
116
108
  fixed?: string;
117
109
  order?: 'asc' | 'desc';
package/dist/model.js CHANGED
@@ -40,7 +40,7 @@ export function findParticipantName(participants, name) {
40
40
  return participants.find((participant) => sameName(participant, name));
41
41
  }
42
42
  export function validateName(name) {
43
- if (!name || !/^[\p{L}\p{N}_-]+(?:\/[\p{L}\p{N}_-]+)*$/u.test(name)) {
44
- throw new SquareError('invalid_name', 'Invalid name: names must contain non-empty slash-separated segments using only Unicode letters, digits, hyphens, and underscores.');
43
+ if (!name || !/^(?:[[\p{L}\p{N}\p{M}_\x2D]--[\p{Variation_Selector}]]|\p{RGI_Emoji})+(?:\/(?:[[\p{L}\p{N}\p{M}_\x2D]--[\p{Variation_Selector}]]|\p{RGI_Emoji})+)*$/v.test(name)) {
44
+ throw new SquareError('invalid_name', 'Invalid name: names must contain non-empty slash-separated segments using Unicode letters, digits, marks, hyphens, underscores, or complete RGI emoji graphemes.');
45
45
  }
46
46
  }
@@ -1,8 +1,8 @@
1
- import { planActNotifications, type DeliveryModel, type WakeAdapter } from './delivery.js';
1
+ import { planActNotifications, type WakeAdapter } from './delivery.js';
2
2
  import { type SquareState } from './model.js';
3
3
  import { matchesMentionTarget } from './runtime.js';
4
4
  import { type ActivityId } from './square-core.js';
5
- import type { WakeNotifier } from './square-facade.js';
5
+ import type { WakeTransportPort } from './ports.js';
6
6
  export type { PlannedNotification } from './delivery.js';
7
7
  export { planActNotifications, matchesMentionTarget };
8
8
  export { notificationMessageId } from './delivery.js';
@@ -17,17 +17,19 @@ interface ProcessNotificationOptions {
17
17
  env?: NodeJS.ProcessEnv;
18
18
  now?: () => number;
19
19
  }
20
- export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<void>;
21
- interface WorkerLaunchOptions {
22
- launchWorker?: (workerPath: string, args: string[]) => void;
20
+ export declare function defaultWakeAdapters(): Promise<WakeAdapter[]>;
21
+ export declare function createDefaultWakeTransport(hostLedger: import('./host-ledger.js').HostLedgerPort, clock: () => number, env?: NodeJS.ProcessEnv): Promise<WakeTransportPort>;
22
+ export declare function createWakeTransport(adapters: readonly WakeAdapter[], hostLedger: import('./host-ledger.js').HostLedgerPort, clock: () => number): WakeTransportPort;
23
+ export declare function processActNotificationsOnce(squarePath: string, actIndex: number, opts?: ProcessNotificationOptions): Promise<import("./ports.js").DeliveryResult>;
24
+ /** Privileged hook fallback: sweep indexed squares plus the current cwd's local squares. */
25
+ export declare function sweepPrivilegedPending(cwd: string, env?: NodeJS.ProcessEnv, suppliedAdapters?: WakeAdapter[]): Promise<void>;
26
+ export interface SweepPendingNotificationsOptions {
23
27
  env?: NodeJS.ProcessEnv;
24
- }
25
- export declare function wakeNotifierForSquare(squarePath: string, env?: NodeJS.ProcessEnv): WakeNotifier;
26
- export interface SweepPendingNotificationsOptions extends WorkerLaunchOptions {
27
28
  now?: number;
28
29
  limit?: number;
30
+ dispatchCandidate?: (actIndex: number) => void | Promise<void>;
29
31
  }
30
32
  /** Select sweep candidates from one frozen snapshot and one delivery replay. */
31
- export declare function pendingNotificationSweepFromState(squarePath: string, state: SquareState, now: number, env: NodeJS.ProcessEnv, limit: number, deriveDelivery?: (snapshot: SquareState) => DeliveryModel): Promise<number[]>;
32
- /** Reconsider old pending attention at a bounded action boundary using the existing worker. */
33
+ export declare function pendingNotificationSweepFromState(squarePath: string, state: SquareState, now: number, env: NodeJS.ProcessEnv, limit: number, deriveDelivery?: (snapshot: import('./model.js').SquareState) => ReturnType<typeof import('./delivery.js').deriveDeliveryModel>): Promise<number[]>;
34
+ /** Select old pending attention at a bounded action boundary for an explicit executor. */
33
35
  export declare function sweepPendingNotifications(squarePath: string, opts?: SweepPendingNotificationsOptions): Promise<number[]>;