@astrosheep/square 0.3.93 → 0.3.94

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 (116) hide show
  1. package/dist/activity-feed.d.ts +3 -5
  2. package/dist/activity-feed.js +16 -14
  3. package/dist/artifact.js +2 -2
  4. package/dist/boundary-presentation.d.ts +2 -2
  5. package/dist/catch-decisions.d.ts +4 -6
  6. package/dist/catch-decisions.js +4 -4
  7. package/dist/claude-delivery-status.js +10 -4
  8. package/dist/claude-delivery.js +19 -11
  9. package/dist/claude-mod.js +24 -53
  10. package/dist/cli/context.d.ts +9 -4
  11. package/dist/cli/context.js +30 -25
  12. package/dist/cli/express-presentation.d.ts +3 -1
  13. package/dist/cli/express-presentation.js +26 -14
  14. package/dist/cli/json.d.ts +3 -0
  15. package/dist/cli/json.js +14 -0
  16. package/dist/cli/mcp-server-command.js +2 -2
  17. package/dist/cli/observation-commands.d.ts +1 -3
  18. package/dist/cli/observation-commands.js +43 -56
  19. package/dist/cli/program.js +2 -2
  20. package/dist/cli/registry.js +6 -3
  21. package/dist/cli/square-commands.d.ts +1 -1
  22. package/dist/cli/square-commands.js +46 -54
  23. package/dist/codex-hook.d.ts +3 -2
  24. package/dist/codex-hook.js +13 -4
  25. package/dist/codex-queue.js +4 -4
  26. package/dist/decisions.d.ts +5 -11
  27. package/dist/decisions.js +9 -20
  28. package/dist/delivery-deferral.js +2 -2
  29. package/dist/delivery-health.d.ts +0 -1
  30. package/dist/delivery-health.js +1 -3
  31. package/dist/delivery-operations.d.ts +2 -2
  32. package/dist/delivery-operations.js +38 -38
  33. package/dist/delivery.d.ts +1 -1
  34. package/dist/delivery.js +1 -1
  35. package/dist/help.js +12 -10
  36. package/dist/inbox.d.ts +9 -22
  37. package/dist/inbox.js +23 -27
  38. package/dist/index.d.ts +1 -3
  39. package/dist/index.js +1 -1
  40. package/dist/mcp.d.ts +3 -0
  41. package/dist/mcp.js +23 -24
  42. package/dist/model.d.ts +8 -15
  43. package/dist/model.js +4 -7
  44. package/dist/notifications.d.ts +1 -1
  45. package/dist/notifications.js +6 -5
  46. package/dist/operation-presentation.d.ts +5 -4
  47. package/dist/operation-presentation.js +50 -45
  48. package/dist/owner.d.ts +11 -0
  49. package/dist/owner.js +32 -0
  50. package/dist/paseo-delivery.d.ts +4 -1
  51. package/dist/paseo-delivery.js +7 -12
  52. package/dist/paseo-state.d.ts +2 -2
  53. package/dist/paseo-state.js +6 -4
  54. package/dist/plugins/opencode/delivery.js +27 -15
  55. package/dist/ports.d.ts +13 -33
  56. package/dist/presentation-operations.js +4 -4
  57. package/dist/presentation.d.ts +5 -8
  58. package/dist/presentation.js +33 -43
  59. package/dist/runtime.d.ts +1 -7
  60. package/dist/runtime.js +0 -14
  61. package/dist/seats.d.ts +2 -3
  62. package/dist/seats.js +7 -15
  63. package/dist/session-lifecycle.d.ts +6 -2
  64. package/dist/session-lifecycle.js +39 -11
  65. package/dist/sqlite-square.d.ts +36 -22
  66. package/dist/sqlite-square.js +138 -161
  67. package/dist/square-api.d.ts +15 -10
  68. package/dist/square-api.js +26 -22
  69. package/dist/square-core.d.ts +0 -5
  70. package/dist/square-core.js +0 -9
  71. package/dist/square-domain.d.ts +4 -2
  72. package/dist/square-domain.js +56 -21
  73. package/dist/square-facade.d.ts +45 -87
  74. package/dist/square-index.d.ts +5 -13
  75. package/dist/square-index.js +13 -38
  76. package/dist/square-location.d.ts +1 -14
  77. package/dist/square-location.js +4 -70
  78. package/dist/square-migration-host-ledger.d.ts +2 -2
  79. package/dist/square-migration-host-ledger.js +6 -5
  80. package/dist/square-migration.d.ts +2 -1
  81. package/dist/square-migration.js +52 -30
  82. package/dist/square-sqlite.d.ts +6 -2
  83. package/dist/square-sqlite.js +54 -28
  84. package/dist/square-tools.d.ts +7 -10
  85. package/dist/square-tools.js +22 -54
  86. package/dist/stream.js +4 -5
  87. package/dist/views.d.ts +21 -10
  88. package/dist/views.js +38 -38
  89. package/dist/wakes.d.ts +1 -2
  90. package/dist/wakes.js +1 -1
  91. package/guides/application-facade-delivery-evidence.md +1 -1
  92. package/guides/claude-native.md +18 -9
  93. package/guides/codex-delivery.md +17 -6
  94. package/guides/mcp-connection-lifetime.md +1 -1
  95. package/guides/mcp.md +3 -3
  96. package/guides/migration.md +142 -151
  97. package/guides/operation-cancellation.md +1 -1
  98. package/guides/participant-ownership.md +78 -47
  99. package/guides/pi-tools.md +33 -4
  100. package/guides/primitive-history-consolidation.md +1 -1
  101. package/guides/row-storage-design.md +8 -8
  102. package/guides/square-api.md +244 -88
  103. package/package.json +1 -1
  104. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  105. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  106. package/plugins/opencode/delivery.ts +27 -17
  107. package/plugins/paseo/client/palette.ts +18 -18
  108. package/plugins/paseo/client/square-message.tsx +17 -23
  109. package/plugins/pi/square-pi.js +17 -17
  110. package/dist/square-backend.d.ts +0 -13
  111. package/dist/square-backend.js +0 -1
  112. package/dist/square-stdio.d.ts +0 -22
  113. package/dist/square-stdio.js +0 -235
  114. package/dist/stdio-server.d.ts +0 -3
  115. package/dist/stdio-server.js +0 -212
  116. package/guides/backends.md +0 -193
@@ -1,60 +1,91 @@
1
1
  # Participant ownership
2
2
 
3
- A participant has one current artifact-owned seat: its normalized participant name, exact Body
4
- (`channel`, `session`, optional `agent`), establishing join generation, and optional wake address.
5
- Display spelling and discovery-index entries never grant write authority. The artifact transaction
6
- is the sole custody authority; there is no writable HostLedger ownership layer.
7
-
8
- ## Captured handles and lifecycle
9
-
10
- `Square.at` captures an explicit Body for writes. `participant(name?)` selects a handle without
11
- joining; `recognize()` returns current handles held by that exact Body. A name alone is not
12
- permission to mutate. Read-only archive operations need no Body. See [square-api.md](square-api.md)
13
- for the public resource lifetime and selection contract.
14
-
15
- - `join(name)` atomically lands the join and stores its seat. Same-body reconnect preserves its
16
- generation and may refresh the wake address. A foreign Body receives `already_joined` rather
17
- than taking ownership implicitly.
18
- - `join(name, {takeover:true})` explicitly completes the captured old seat and establishes a new
19
- one with `done -> join` in one transaction. Its compare-and-set generation prevents a concurrent
20
- takeover from being silently replaced.
21
- - Participant mutations carry the captured seat into the transaction. The gate checks both Body
22
- and generation, including when the same Body later reacquires the name. An old handle never
23
- becomes fresh because a name matches again.
24
- - `done` retires only the current captured seat, catch lease and delivery deferrals. A later join
25
- establishes a fresh generation. Completed coordinates retained for exact-body diagnostics are
26
- not current write authority. Owner-session cleanup uses the same fence and cannot complete a
27
- replacement seat.
28
- - Stdio retains the selected Participant in a connection-local reference. Each operation uses that
29
- captured handle instead of reselecting authority by name. Rejoin/takeover therefore fences old
30
- remote handles just as it does local SDK handles.
31
-
32
- The HOME discovery index is rebuildable candidate-path data. Losing it can delay discovery but
33
- cannot transfer a seat or erase delivery evidence. A wake address is only transport readiness for
34
- an existing seat, not an alternative ownership fact.
3
+ Membership and host attachment are different facts. Membership says a participant is in the
4
+ square; it owns their join history, read horizon and outgoing listens. Attachment says whether
5
+ an exact opaque owner is executing for that participant now.
6
+ A standing seat may be attached or detached. The artifact transaction is the sole custody
7
+ authority; display spelling, wake addresses and the rebuildable HOME discovery index never
8
+ grant ownership. There is no writable HostLedger ownership layer.
9
+
10
+ Owners are opaque non-secret strings, not harness coordinates or authentication. Harness adapters
11
+ encode their own identity; terminal owners use `user:<OS user>@<host>` and are never automatically
12
+ detached or ended by a harness. A seat's optional wake route is self-contained transport readiness,
13
+ not an owner or an alternative custody fact.
14
+
15
+ ## Three endings
16
+
17
+ - **The participant leaves:** `Participant.done()` ends membership, removes its seat, catch
18
+ lease and delivery deferrals, and removes outgoing listens. A later explicit `join` establishes
19
+ a fresh generation and read horizon. No host start or resume brings a voluntary leave back.
20
+ - **The host session ends:** `detach(name, {owner, generation})` detaches only that exact owner and
21
+ join generation. It clears wake readiness, catch ownership and delivery deferrals, without landing
22
+ an activity or changing membership, listens or the read horizon. A detached participant is
23
+ **away**, still receives normal landed audience and accumulates unread activity, but cannot write
24
+ or receive proactive delivery. Away has no timeout; a session that never returns simply stays away.
25
+ - **The host confirms permanent deletion:** `endHeld(name, {owner, generation})` ends membership
26
+ with a fenced `done`, including for a detached seat. OpenCode's `session.deleted` uses this path.
27
+ Pi shutdown, Codex SessionEnd and Claude session end do not prove permanent deletion and therefore
28
+ detach.
29
+
30
+ An explicit takeover remains `done -> join` in one transaction, whether the old seat is attached
31
+ or detached. It transfers the name to the new owner with a fresh generation; old cleanup and
32
+ recovery cannot reclaim it.
33
+
34
+ ## Captured handles and restoration
35
+
36
+ A `Square` captures no participant identity. `participant(name, {owner})` selects an attached,
37
+ standing seat held by that exact owner without joining; never-joined, done, foreign and detached
38
+ seats refuse with join recovery facts, not ghost handles. `seatsOf(owner)` is a read-only discovery
39
+ surface for the owner's standing seats as `{name, generation, attachment}`. It includes attached and
40
+ detached seats, but does not join or return done participants. See [square-api.md](square-api.md)
41
+ for resource lifetimes and adapter selection.
42
+
43
+ - `join(name, {owner, wakeAddress?})` atomically establishes membership and its seat when absent.
44
+ A same-owner reconnect preserves the establishing generation. On a detached seat it also
45
+ reattaches, using the operation's supplied wake address, and returns `reconnected`, with no
46
+ activity, new read horizon or listening changes. A foreign owner gets `already_joined`; takeover
47
+ must be explicit.
48
+ - `reattach(name, {owner, wakeAddress?})` returns a handle for an exact-owner standing seat, or
49
+ `null` for absent, foreign or done custody; it never creates membership. A foreign takeover racing
50
+ the transaction can instead refuse. It can also refresh an attached seat's wake address subject to
51
+ native-route preference. Host start/resume restores only detached seats found through
52
+ `seatsOf(owner)` before arming delivery. One unavailable location or
53
+ failed reattachment does not block the others. A new or forked session has a different owner and
54
+ restores nothing. Hosts never infer restoration from a historical departure.
55
+ - Participant mutations require both the captured generation and an attached current seat.
56
+ Detach suspends existing handles; they cannot express, catch, listen, hold, leave or change
57
+ deferrals until reattachment. Rejoin/takeover fences old handles permanently, even if the same
58
+ owner later reacquires the name. Host cleanup checks owner and generation inside its transaction;
59
+ stale, foreign, done or already-detached detach changes nothing. Host `cancelDeliveries` also
60
+ requires the captured owner/generation and an attached current seat; it does not consume activity.
61
+
62
+ The HOME index supplies candidate paths only. Successful file-backed joins and non-null
63
+ reattachments attempt best-effort publication; opening or expressing does not publish. Losing the
64
+ index may delay restoration or delivery but cannot transfer a seat, erase delivery evidence or
65
+ consume unread activity. A wake address is transport readiness for an attached seat, not an
66
+ alternative ownership fact.
35
67
 
36
68
  ## Independent delivery deferrals
37
69
 
38
- `deferDelivery`, `renewDeliveryDeferral`, and `releaseDeliveryDeferral` require that same captured
39
- current seat. Deferrals live in the artifact, keyed by normalized participant, generation and fresh
40
- UUID, independently of the single catch lease and of delivery claims/receipts. A lease contains
41
- only its validated metadata match and expiry; it is not an acknowledgement intent or an activity.
70
+ `deferDelivery`, `renewDeliveryDeferral`, and `releaseDeliveryDeferral` require the same captured,
71
+ attached current seat. Independent artifact-owned leases belong to one participant and generation,
72
+ separately from catch ownership, delivery claims and receipts. Each has a fresh opaque ID, validated
73
+ metadata match and expiry. It is not an acknowledgement intent or an activity.
42
74
 
43
75
  Each lease's nested own-property scalar equalities combine with AND; matching active leases combine
44
- with OR. Renewal cannot revive an expired lease. Release touches only its named live lease, and
76
+ with OR. Renewal cannot revive an expired lease. Release touches only its named live lease and
45
77
  returns false for an absent/expired ID. A current owner cannot use another participant's ID.
46
- Expired rows may be pruned during owner writes; read/claim eligibility always checks expiry and
47
- the current generation. Done/takeover/rejoin remove deferrals in the same transaction, and stale
48
- rows can never become active for a new generation.
78
+ Expiry is checked live. Detach, done, takeover and rejoin clear deferrals in the same transaction;
79
+ reattachment never revives an old lease.
49
80
 
50
81
  Deferrals change only proactive eligibility. They preserve audience, history, unread counts and
51
- explicit catch. An explicit catch consumes normally and prevents later replay after release.
52
- All proactive paths recheck the same typed policy at claim and final send/presentation boundaries.
53
- An already-dispatched external message cannot be recalled by acquiring a lease.
82
+ explicit catch. A caught record is not replayed after release. Producers, observers, claims and
83
+ final send/presentation gates all require attached current custody and apply the same deferral
84
+ policy. Neither detach nor a deferral can recall an already-dispatched external message.
54
85
 
55
86
  ## Acceptance boundaries
56
87
 
57
- Tests exercise foreign and stale handles, same-body reconnection/rejoin, explicit takeover,
58
- transaction-scoped generation fences, independent leases, precise expiry, explicit catch and
59
- stdio parity. Assertions belong to the authoritative facts, not helper call ordering or display
60
- copy. Migration of old owner/route facts is offline and explicit; see [migration.md](migration.md).
88
+ Tests exercise foreign/stale/detached handles, same-owner restoration with unread activity intact,
89
+ voluntary leave, explicit takeover, permanent deletion, exact-owner adapter lifecycle, generation
90
+ fences and delivery eligibility. Assertions belong to authoritative facts, not helper ordering or
91
+ display copy. Migration is offline and explicit; see [migration.md](migration.md).
@@ -11,11 +11,40 @@ const result = await tools.square_express({
11
11
  body: 'A different angle on this.',
12
12
  mentions: ['aoi'],
13
13
  });
14
- text(result);
14
+ text(result); // CLI text: confirmation and bounded unread previews
15
15
  ```
16
16
 
17
- `location` defaults to `SQUARE_LOCATION`; relative paths use the current call's cwd. `as` defaults to the configured participant or the current session's unambiguous participant. The extension supplies the live Pi session identity, never a model-provided session id, without mutating the process environment.
17
+ `location` defaults to `SQUARE_LOCATION`; relative paths use the current call's cwd. Join requires
18
+ an explicit `as`. For later participant operations, an explicit `as` must name a current attached
19
+ seat of the live Pi owner; without it, exactly one such seat is required. Status checks an explicit
20
+ `as` the same way, but without `as` uses the sole attached seat as viewer or gives an unfiltered
21
+ overview if there are zero or multiple. The extension encodes the live Pi session with
22
+ `harnessOwner({channel: 'pi', session})`, never a model-provided session id, without mutating
23
+ the process environment.
18
24
 
19
- Codemode receives the operation's data object directly. Failures return `{ error: { code, message, facts?, operation? } }` and are marked as failed tool results; scripts must inspect `error`. `catch` consumes activity; `history` does not. Exact parameters and semantics come from the tool descriptions, shared with MCP through `square-tools.ts`.
25
+ All eight tools return the CLI's human-readable text, without an `outputSchema` or
26
+ `structuredContent`. In Pi codemode, a successful call resolves to a `string`:
27
+ use `text(result)`, not `text(result.text)`. Failures are marked as failed tool results;
28
+ codemode rejects with the readable error and recovery commands rather than returning
29
+ an error object. For machine-readable domain results, use the [SDK](square-api.md).
20
30
 
21
- Each operation owns and closes its connection through the facade, including cancellation cleanup. Existing notification delivery, rendering and session lifecycle stay independent. Reload the extension after installing an updated package to register the tools in an existing Pi session.
31
+ `express` confirms landing and reach warnings without echoing the sent body. Unread
32
+ context shows at most the latest five directed activities, in chronological order,
33
+ with at most 400 Unicode characters per preview. Already consumed activities are
34
+ excluded, including those beyond an earlier unread hole. Previews never consume
35
+ activity; the text supplies a `catch` command and the count of other unread activities.
36
+ Use `catch` for consumption or `history` for archives. Exact parameters and semantics
37
+ come from the tool descriptions, shared with MCP through `square-tools.ts`.
38
+
39
+ Each operation owns and closes its connection through the facade, including cancellation cleanup.
40
+ Pi `session_shutdown` detaches that exact owner's seats, not membership: no `done` lands, listens
41
+ and the read horizon remain, and mentions received while away stay unread. Catch ownership,
42
+ deferrals and wake readiness are cleared. Detached participants cannot write or receive proactive
43
+ delivery. On `session_start`, before watching, the extension uses `seatsOf(owner)` to discover only
44
+ that exact owner's detached standing seats and `reattach(name, {owner, wakeAddress?})` to restore them.
45
+ One failed seat/location does not block the others. New/forked harness owners restore nothing, voluntary
46
+ `done` is never revived, and away has no timeout. Permanent deletion is a separate host-confirmed
47
+ membership ending; Pi shutdown is not such proof. See [participant-ownership.md](participant-ownership.md).
48
+
49
+ Notification rendering remains independent of tool calls. Reload the extension after installing
50
+ an updated package to register the tools in an existing Pi session.
@@ -57,7 +57,7 @@ Entry still uses the actual selector with explicit `['say', 'done']` kinds and i
57
57
  ## Necessary distinctions retained
58
58
 
59
59
  - **Defaults:** SDK `Square.history` is unbounded. SDK `Participant.history` defaults to ten. Application/CLI/MCP default to ten, cap explicit limits at 100, and reject an implicit merged context larger than 100 with the original `operation.historyBounds` detail. Supplying a limit bounds that context. Application's stricter grep/fixed, non-empty search, finite since and safe nonnegative context validation is unchanged; SDK search remains intentionally looser.
60
- - **Three subsets:** raw selected records can contain reads and historical actorless lifecycle records; public `Activity` omits read/actorless records but retains listen/ignore; ordinary terminal visibility contains join/say/done/hold/resume. Hidden listener events still occupy page positions. Since/context windows still select raw bookkeeping; ordinary history excludes reads. JSON/field formatting continues using raw records. No third event model was introduced.
60
+ - **Three subsets:** raw selected records can contain reads and historical actorless lifecycle records; public `Activity` omits read/actorless records but retains listen/ignore; ordinary terminal visibility contains join/say/done/hold/resume. Hidden listener events still occupy page positions. Since/context windows still select raw bookkeeping; ordinary history excludes reads. Field formatting uses raw records; CLI JSON now serializes the public SDK result and omits bookkeeping records. No third event model was introduced.
61
61
  - **Paging:** cursor bounds remain exclusive stable IDs, sparse context counts existing positions, and from/mention/search intersect before applying the limit. An after cursor selects the oldest eligible page; otherwise the newest eligible page is selected. `order` only reverses the selected page. Continuation uses the terminal-visible subset and the same filtered candidate universe; a listener-only page has no invented terminal anchor. Audience paging continues through empty intersections.
62
62
  - **Projection:** ordinals, presence anchors, standing/held facts and final data come from the same read callback. The projection clock is now sampled within that callback instead of after the intermediate async presentation completed. It is still an observation-only operation with no receipt, presence or lease writes. Overflow is rejected before unnecessary anchor/ordinal enrichment.
63
63
  - CLI and MCP require no policy changes: CLI continues formatting raw/terminal records and owner-produced continuation; MCP serializes public data only. Catch's renderer-accessor changes are owned by its separate lane.
@@ -385,7 +385,7 @@ Presence anchor: if no join, return -1. E=max(J, largest own actor-bearing activ
385
385
  - Suffix/behind/unreadActivityCount use directed rows > continuous cursor, **including individually seen rows beyond a hole**. Notification pending instead requires joined, >latest join, individually unseen. Do not substitute one count for the other.
386
386
  - Hard cap uses lifetime sayCount. Quorum uses all known peers' done booleans (there must be at least one peer), not only currently standing peers.
387
387
  - Throttle: request newest `limit` global say times with at > now-THROTTLE_WINDOW_MS; if that many exist, releaseAt is the oldest returned + window, retry=max(1, releaseAt-now). Bell: newest 1 actor bell timestamp > now-1h; that timestamp +1h is nextAt. Neither query excludes future timestamps.
388
- - Behind summaries retain current per-sender counts/latest timestamp, last THREE suffix previews and their **suffix-relative** numbering. Lifetime sayOrdinals are for ordinary history/feed rendering; they are not substituted for unread-summary numbers. Block only when !force, suffix nonempty, and freshest summary age > UNREAD_BLOCK_GRACE_MS; max(0,now-at) remains the age. force bypasses behind only.
388
+ - Behind summaries retain per-sender counts, latest timestamp and one greatest-index suffix preview. The latest timestamp need not belong to that preview. Lifetime sayOrdinals are retained for history field formatting, not recovery previews. Block only when !force, suffix nonempty, and freshest summary age > UNREAD_BLOCK_GRACE_MS; max(0,now-at) remains the age. force bypasses behind only.
389
389
 
390
390
  ### Catch transaction
391
391
 
@@ -411,22 +411,22 @@ Keep filesystem hints plus the existing 2-second authoritative revision reconcil
411
411
 
412
412
  ## 7. Complete caller replacement map (including render dependencies)
413
413
 
414
- No production structure below carries `.state`, all `.activities`, or a deferred DB query. Renderers receive settled perceptions and numbers, never recompute audience from a partial SquareState.
414
+ No production structure below carries `.state`, all `.activities`, or a deferred DB query. Renderers receive settled perceptions, never recompute audience from a partial SquareState; history field formatting also receives selected ordinals.
415
415
 
416
416
  | Current callers | Exact facts/replacement |
417
417
  |---|---|
418
418
  | openSquare/openSquareArtifact, wait baselines, watch headers, cli/program | header/revision only; remove preliminary whole-state validation/load. Every normal selected-row decode remains validated. |
419
419
  | square-actions join/implicitJoin/takeover/done/endOwnedSession, registry-associated route cleanup | participant/roster as needed, routes, land/replaceRoutes; same host claim lock scopes and cleanup sequences. Takeover done+join is one txn. No full SDK snapshot. |
420
- | Join's before/after snapshot and CLI hold/resume/done count calls | Current `Square.join` returns its concrete receipt with a Participant handle; optional observations use transaction-captured counts, held state and time. Listener/lifecycle commit facts likewise come from the mutation transaction; join's extra entry history is best-effort. Known joined-or-done `participantCount` remains distinct from the standing count. See [Square/Participant API](square-api.md). |
421
- | express/decideAct and behind rendering (activity.ts) | header, actor fact, roster for longest standing-body mention resolution, hold, reply head/existence, recentSayTimes, continuous cursor, directed suffix. Admission normalization/error order unchanged. A valid reply coordinate is <nextActIndex, even if a gap: preserve current acceptance of assigned-but-missing reply. ActivityPresentation supplies own count/cap/hold/roster, suffix items with lifetime ordinals + settled full perception, and behind summaries. No whole history used just to number previews. |
420
+ | Join's before/after snapshot and CLI hold/resume/done count calls | `Square.join` returns a Participant handle and committed activity; optional observations use transaction-captured counts, held state and time. Listener/lifecycle commit facts likewise come from the mutation transaction; join's extra entry history is best-effort. See [Square/Participant API](square-api.md). |
421
+ | express/decideAct and behind rendering | header, actor fact, roster for longest standing-body mention resolution, hold, reply head/existence, recentSayTimes, continuous cursor, directed suffix. Admission normalization/error order unchanged. A valid reply coordinate is <nextActIndex, even if a gap: preserve current acceptance of assigned-but-missing reply. Recovery supplies own count/cap/hold and behind summaries with one full preview per sender. |
422
422
  | listen/ignore/listening, watch leases and terminal checks | actor fact, outgoing attention; roster only for quorum; land or lease methods. Unknown valid attention target still allowed. Pulse keeps hold-before-terminal priority. |
423
423
  | catch / native seen | directed selectors/activity exact, markSeen, cursor/counts in txn; native `current` becomes synchronous `(facts: SquareRead)=>boolean`, evaluated ONLY within reads/receipt txn. It cannot escape or call host I/O. |
424
- | entryPresentation / cli/square-commands join | bounded newest say/done heads then bodies; selected sayOrdinals; explicit per-index perceptions for the selected viewer; header context/scene; actor's join count from activityCount(kind join, actor identity). Supply `joinedBefore` rather than replaying `.state.acts`. `lastN=null` remains an explicit complete history request, not normal join's default. |
425
- | statusPresentation / cli/observation-commands status | roster+attention, hold, receiptFacts, continuous cursors and directed counts, fresh lease status; latest say/done + ordinal. Supply last THREE join events after latest public index, total number of such joins, and each `rejoined` boolean from existence of earlier done with EXACT actor spelling (current CLI equality). Latest line carries settled perception for context.name (including '' ambient viewer), not a SquareState. No receipts/history map hydrated. |
424
+ | entryPresentation / cli/square-commands join | bounded newest say/done heads then public activities with settled perceptions for the selected viewer; header context/scene; actor's join count from activityCount(kind join, actor identity). Supply `joinedBefore` rather than replaying `.state.acts`. `lastN=null` remains an explicit complete history request, not normal join's default. |
425
+ | statusPresentation / cli/observation-commands status | roster+attention, hold, receiptFacts, continuous cursors and directed counts, fresh lease status; latest say/done. Supply last THREE public join events after latest public index, total number of such joins, and each `rejoined` boolean from existence of earlier done with EXACT actor spelling (current CLI equality). Latest line carries settled perception for context.name (including '' ambient viewer), not a SquareState. No receipts/history map hydrated. |
426
426
  | participants/participantsPresentation/listPresentation | roster-derived status sorted by existing compareParticipantActivity; receipts/leases aggregates for participant statuses; list requires only active names, header preamble and say count. Change probeSquare to create a validated file-backed port, not full read then memory clone. |
427
427
  | history / participantHistory / historyPresentation | relational head filter + contextIndexes; hydrate filtered candidate bodies for JS search, otherwise page only; count before final limit; selected ordinals + detached presence anchors/perceptions. Retain CLI lifecycle archive/raw coordinate windows and facade non-read inclusion. See algorithm below. |
428
- | watchPresentation/watch.ts/renderWatchOutput | pass caught activity ids into projection; hydrate ONLY those rows, selected lifetime ordinals, caller-supplied caught perceptions, participant statuses/clock, count/cap/terminal. Finish/terminal-only call omits ids. No all-history lookup of caught ids. |
429
- | streamProjection/streamTailProjection | ordinary stream pages raw activity heads BEFORE recipient filtering (100 existing rows), advances cursor to last examined raw row even on empty recipient output. Recipient stream filters historical audience, not pending/seen/latest-join. Tail selects last N matching rows but cursor is artifact's last actual index. Includes raw lifecycle/read exactly where current stream does. |
428
+ | catch selection and rendering | hydrate ONLY selected rows, capture caught perceptions, participant status/clock, count/cap/terminal in the receipt transaction. Empty completion does not hydrate bodies. No all-history lookup of caught ids. |
429
+ | streamProjection/streamTailProjection | stream pages canonical activity heads before recipient filtering, advances its cursor even on empty recipient output, and returns public Activity or viewer-relative PerceivedActivity. Recipient filtering uses the historical landed audience, not pending/seen/latest-join. Tail selects last N matching activities and advances to the artifact head. |
430
430
  | sessionInbox/located seats/boundary | exact-body seats + establishing join time, recipient directed unseen pages + live lease; complete result using §6. Boundary's stale-activity fallback uses activity(index) existence, not `.acts.every`. |
431
431
  | deliverPending/sweep/delivery-health/notifications | pendingAudience groups or audience(activity)+joined/latestJoin+receipt checks for exact activity, ordered routes and detached host ledger evidence. Eligibility projection takes these typed facts instead of state. Sweep scans past suppressed candidates. Health can explicitly collect its complete pending summaries without bodies; renderer's existing detail cap stays. |
432
432
  | Claude cancellation/resume/route discovery | cancellation=max existing activity index with at<=cutoff (not assumed chronological time); use newest activity-head pages in one read txn, testing timestamps from greatest index downward and stopping at the first match. If none matches, cutoff is -1. Resume last join/done by EXACT actor spelling; no full snapshot. Routes keep first-match order. |