@astrosheep/square 0.3.94 → 0.3.96
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.
- package/dist/artifact.js +1 -1
- package/dist/attention-presentation.d.ts +5 -4
- package/dist/attention-presentation.js +18 -8
- package/dist/attention.d.ts +19 -0
- package/dist/attention.js +30 -0
- package/dist/boundary-presentation.js +50 -48
- package/dist/catch-decisions.d.ts +1 -2
- package/dist/catch-decisions.js +41 -21
- package/dist/channel.d.ts +72 -0
- package/dist/channel.js +86 -0
- package/dist/claude-delivery.js +2 -1
- package/dist/cli/context.js +0 -2
- package/dist/cli/express-presentation.js +3 -3
- package/dist/cli/json.js +1 -1
- package/dist/cli/program.js +1 -1
- package/dist/cli/registry.js +1 -3
- package/dist/cli/square-commands.d.ts +0 -2
- package/dist/cli/square-commands.js +21 -27
- package/dist/decisions.d.ts +0 -5
- package/dist/decisions.js +0 -13
- package/dist/delivery-attempts.d.ts +52 -0
- package/dist/delivery-attempts.js +73 -0
- package/dist/delivery-effects.d.ts +139 -0
- package/dist/delivery-effects.js +163 -0
- package/dist/delivery-operations.js +43 -68
- package/dist/delivery-primitives.d.ts +5 -0
- package/dist/delivery-primitives.js +3 -0
- package/dist/delivery.d.ts +1 -1
- package/dist/delivery.js +8 -7
- package/dist/help.js +4 -6
- package/dist/http-delivery.d.ts +16 -0
- package/dist/http-delivery.js +101 -0
- package/dist/inbox.js +3 -1
- package/dist/mcp.js +65 -63
- package/dist/model.d.ts +10 -6
- package/dist/model.js +20 -1
- package/dist/notifications.js +2 -0
- package/dist/operation-presentation.d.ts +1 -2
- package/dist/operation-presentation.js +12 -20
- package/dist/ports.d.ts +8 -14
- package/dist/presentation-operations.d.ts +15 -19
- package/dist/presentation-operations.js +47 -57
- package/dist/presentation.d.ts +2 -9
- package/dist/presentation.js +13 -48
- package/dist/receive.d.ts +66 -0
- package/dist/receive.js +54 -0
- package/dist/runtime.d.ts +0 -1
- package/dist/runtime.js +2 -3
- package/dist/sqlite-square.d.ts +3 -2
- package/dist/sqlite-square.js +83 -57
- package/dist/square-api.d.ts +1 -1
- package/dist/square-api.js +1 -1
- package/dist/square-core.d.ts +1 -9
- package/dist/square-domain.js +29 -36
- package/dist/square-facade.d.ts +25 -23
- package/dist/square-legacy-framing.d.ts +2 -0
- package/dist/square-legacy-framing.js +8 -0
- package/dist/square-migration.d.ts +3 -1
- package/dist/square-migration.js +46 -13
- package/dist/square-receive.d.ts +6 -0
- package/dist/square-receive.js +18 -0
- package/dist/square-sqlite.d.ts +5 -3
- package/dist/square-sqlite.js +100 -92
- package/dist/square-tools.d.ts +1 -0
- package/dist/square-tools.js +12 -12
- package/dist/views.d.ts +2 -3
- package/dist/views.js +14 -19
- package/dist/wakes.d.ts +0 -3
- package/dist/wakes.js +3 -5
- package/examples/symmetric-domains.mjs +250 -0
- package/guides/application-facade-delivery-evidence.md +5 -5
- package/guides/attention-primitive.md +32 -0
- package/guides/change-waits.md +2 -2
- package/guides/codex-delivery.md +1 -1
- package/guides/delivery-primitives.md +180 -0
- package/guides/mcp.md +1 -1
- package/guides/migration.md +12 -6
- package/guides/participant-ownership.md +1 -1
- package/guides/pi-tools.md +2 -2
- package/guides/primitive-catch-consolidation.md +5 -5
- package/guides/primitive-history-consolidation.md +2 -2
- package/guides/primitive-status-consolidation.md +3 -3
- package/guides/primitive-storage-consolidation.md +1 -1
- package/guides/receive-primitive.md +90 -0
- package/guides/row-runtime-delivery-evidence.md +1 -1
- package/guides/row-storage-design.md +17 -23
- package/guides/square-api.md +77 -10
- package/guides/symmetric-domains.md +92 -0
- package/package.json +18 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/square/SKILL.md +2 -6
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/paseo/client/marble.ts +7 -0
- package/plugins/paseo/client/markdown.tsx +65 -9
- package/plugins/paseo/client/palette.ts +43 -20
- package/plugins/paseo/client/square-message.tsx +57 -48
- package/plugins/paseo/shared/message.ts +1 -2
- package/plugins/pi/square-pi.js +6 -4
- package/skills/square/SKILL.md +2 -6
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Delivery custody primitives
|
|
2
|
+
|
|
3
|
+
`@astrosheep/square/delivery` provides storage-independent attempt transitions, suppression predicates,
|
|
4
|
+
and four bound effect functions: `dispatchEffect`, `preparePresentation`, `presentPrepared`, and
|
|
5
|
+
`presentPreparedBatch`. It does not open a square, interpret identities, own transactions, or schedule
|
|
6
|
+
retries. Square's actual dispatch, single presentation and boundary batch adapters compose these same
|
|
7
|
+
lifecycles; its SQLite adapter uses the attempt transitions with existing tables. Ownership, membership,
|
|
8
|
+
cancellation and delivery-deferral policy remain in the bound application capability.
|
|
9
|
+
|
|
10
|
+
## Bind a series inside a transaction
|
|
11
|
+
|
|
12
|
+
`AttemptRows<D>` is a capability for **one logical item / recipient / authority / purpose series**.
|
|
13
|
+
The caller chooses those coordinates, including arbitrary opaque strings, and binds the store to them.
|
|
14
|
+
No Square name, seat, generation, activity-id codec or composite-key format is required.
|
|
15
|
+
|
|
16
|
+
- `list()` returns that series newest ordinal first.
|
|
17
|
+
- `byToken(token)` returns only a matching attempt in that series.
|
|
18
|
+
- `insert(attempt)` and `replace(attempt)` write within the caller's current transaction.
|
|
19
|
+
- Replacements preserve purpose, token, ordinal and the caller's external series coordinates.
|
|
20
|
+
|
|
21
|
+
The caller guarantees isolation against competing claims, token uniqueness within its token lookup
|
|
22
|
+
scope, atomic commit/rollback, and durable storage where needed. Run each operation and its reads and
|
|
23
|
+
writes inside that boundary; an asynchronous read followed later by an unguarded write is not custody.
|
|
24
|
+
Stores must not retain mutable references that allow a caller to change durable rows without a write.
|
|
25
|
+
`D` belongs entirely to the caller. The primitive does not merge, serialize or interpret it.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { claimAttempt, prepareAttempt, settleAttempt, type AttemptRows } from '@astrosheep/square/delivery';
|
|
29
|
+
|
|
30
|
+
type Payload = { route?: string; nativeToken?: string; ack?: string };
|
|
31
|
+
// Supplied by the application, already scoped and transaction-bound:
|
|
32
|
+
declare const rows: AttemptRows<Payload>;
|
|
33
|
+
|
|
34
|
+
const claim = claimAttempt(rows, {
|
|
35
|
+
purpose: 'dispatch', token: 'application-generated-unique-token',
|
|
36
|
+
at: 1000, leaseMs: 30_000, data: { route: 'opaque endpoint' },
|
|
37
|
+
});
|
|
38
|
+
if (claim.status === 'acquired') {
|
|
39
|
+
prepareAttempt(rows, { token: claim.token, data: { route: 'opaque endpoint', nativeToken: 'correlation' } });
|
|
40
|
+
}
|
|
41
|
+
// In a later transaction, only after external proof of acceptance:
|
|
42
|
+
settleAttempt(rows, {
|
|
43
|
+
token: 'application-generated-unique-token', outcome: 'accepted', at: 1100,
|
|
44
|
+
data: { route: 'opaque endpoint', nativeToken: 'correlation', ack: 'external proof' },
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The example shows only transaction-scoped transitions. Commit a successful claim before external I/O;
|
|
49
|
+
settle its exact token in a new transaction after observing the result. The bound effect capability
|
|
50
|
+
below connects those operations without introducing a generic transaction runtime. Authority fencing,
|
|
51
|
+
currentness policy and the meaning of external proof remain the application's responsibility.
|
|
52
|
+
An `accepted` dispatch is not proof of presentation or consumption. Only the responsible presentation
|
|
53
|
+
boundary may assert `presented`; consuming an item is a separate application operation.
|
|
54
|
+
|
|
55
|
+
## Transitions
|
|
56
|
+
|
|
57
|
+
An `Attempt<D>` has `purpose: 'dispatch' | 'presentation'`, `token`, zero-based `ordinal`, `outcome`,
|
|
58
|
+
finite `at`, optional `expiresAt`, and `data`.
|
|
59
|
+
|
|
60
|
+
- `claimAttempt` first returns terminal evidence: dispatch `accepted`/`unknown`, presentation
|
|
61
|
+
`presented`/`unknown`. Otherwise a live `dispatching` attempt is `busy`; missing expiry is live.
|
|
62
|
+
- At exact expiry or later, an interrupted `dispatching` attempt becomes `unknown`, keeps its original
|
|
63
|
+
payload, loses expiry, and returns `terminal` with `interrupted: true`. There is no new attempt and
|
|
64
|
+
**no automatic replay of uncertainty**. Square maps that flag to its interruption diagnostic.
|
|
65
|
+
- With neither terminal nor dispatching evidence, claim inserts `dispatching` at the next ordinal.
|
|
66
|
+
Failed/released attempts can therefore be retried. Purpose-specific terminal meanings are not
|
|
67
|
+
inferred from other completion labels.
|
|
68
|
+
- `prepareAttempt` replaces only the data of the exact `dispatching` token. Pass the complete merged
|
|
69
|
+
payload. It returns false for an absent or no-longer-dispatching token. Callers that already know
|
|
70
|
+
the payload is unchanged may skip the replacement; core performs no JSON equality checks.
|
|
71
|
+
- `settleAttempt` allows `dispatching` to any defined completion, and late `unknown` to `accepted`.
|
|
72
|
+
It clears expiry and sets time/outcome/data. `accepted` to `accepted` returns true **without any
|
|
73
|
+
write or payload/time mutation**. All other transitions return false, including `unknown` to
|
|
74
|
+
`presented`. Missing or foreign tokens cannot settle another series.
|
|
75
|
+
|
|
76
|
+
Invalid purpose/completion/token/time, non-positive or unsafe lease durations, non-finite expiry, and
|
|
77
|
+
unsafe next ordinals reject before mutation with `TypeError` or `RangeError`, not `SquareError`.
|
|
78
|
+
The caller supplies valid stored attempts and consistently scoped, ordered rows.
|
|
79
|
+
|
|
80
|
+
## Suppression without payloads
|
|
81
|
+
|
|
82
|
+
`presentationBlocksDispatch(attempts, now)` and `automaticDispatchEligible(attempts, now)` accept only
|
|
83
|
+
`purpose`, `outcome`, and optional `expiresAt`; no dummy payload or identity is needed. These predicates
|
|
84
|
+
may see both purposes for the same logical delivery.
|
|
85
|
+
|
|
86
|
+
Presentation `presented`, `clipped`, `unknown`, or live `dispatching` blocks dispatch. Expired
|
|
87
|
+
presentation dispatching alone does not. Automatic dispatch additionally requires no dispatch
|
|
88
|
+
`accepted`, `unknown`, or `dispatching`; even expired dispatch custody blocks automatic replay.
|
|
89
|
+
These are preselection predicates, not substitutes for a transactional claim or application gates.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Bound effects: one captured capability, four functions
|
|
93
|
+
|
|
94
|
+
`EffectPort<C>` is bound by the caller to **one captured work item / recipient / authority / purpose**.
|
|
95
|
+
It exposes only:
|
|
96
|
+
|
|
97
|
+
- `claim(signal?)`: the application's existing atomic claim, returning `{ token, ordinal }` or
|
|
98
|
+
`undefined` when busy, terminal, stale or deferred. The runner does not claim the attempt twice.
|
|
99
|
+
- `current(signal?)`: pre-effect policy; a rejected check is unverifiable and treated as false.
|
|
100
|
+
- `settle(claim, completion)`: one captured settlement operation, with no request signal. Return true
|
|
101
|
+
only when it commits, false when not recorded (not necessarily stale), or throw on persistence error.
|
|
102
|
+
|
|
103
|
+
The application owns tokens, leases, semantic timestamps, authority, proof/diagnostic payloads and
|
|
104
|
+
resource lifetimes. There is no public transaction type, series-key codec or extra persisted lifecycle.
|
|
105
|
+
`Settlement<C>` keeps the selected completion separate from persistence: `recorded`, `not-recorded`,
|
|
106
|
+
or `error` with the original error. Observations are never erased by persistence refusal/error.
|
|
107
|
+
|
|
108
|
+
### Dispatch
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { dispatchEffect, type EffectPort, type DispatchCompletion } from '@astrosheep/square/delivery';
|
|
112
|
+
|
|
113
|
+
declare const port: EffectPort<DispatchCompletion>; // bound claim/current/settle
|
|
114
|
+
// A sender must check its absolute deadline/cancellation immediately before external mutation.
|
|
115
|
+
const report = await dispatchEffect(port, async context => {
|
|
116
|
+
if (!await context.beforeSend()) return { outcome: 'not-capable' };
|
|
117
|
+
if (context.signal?.aborted || Date.now() >= context.deadline) return { outcome: 'unknown' };
|
|
118
|
+
// Call the application's transport here, passing the remaining budget and captured claim.
|
|
119
|
+
return { outcome: 'accepted', data: { proof: 'application acknowledgement' } };
|
|
120
|
+
}, { timeoutMs: 5000 });
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`dispatchEffect` owns claim → initial currentness → send → settlement. Cancellation suppresses
|
|
124
|
+
pre-effect work. It starts its timer immediately before invoking the sender, not during claim,
|
|
125
|
+
initial policy reads or persistence. Exactly one returned/thrown/timeout decision is frozen before
|
|
126
|
+
settlement. A sender exception defaults to `unknown`, not failed; returned `not-capable` releases
|
|
127
|
+
custody. A denied final gate releases with `not-current / final` under the sender's obligation to
|
|
128
|
+
obey it. No automatic retry occurs.
|
|
129
|
+
|
|
130
|
+
`beforeSend()` is **policy currentness, not an elapsed-budget gate**. A stalled policy check may
|
|
131
|
+
return true after the outer timeout. The sender must recheck `deadline` and `signal` after that await
|
|
132
|
+
and immediately before I/O; true does not authorize a late send. Outer timeout stays unknown even
|
|
133
|
+
when no I/O is known to have started. Late gates and late promise results cannot rewrite the frozen
|
|
134
|
+
settlement. Separately correlated native proof may still use the attempt transition's permitted late
|
|
135
|
+
unknown → accepted path; the timed-out runner does not reconcile itself.
|
|
136
|
+
|
|
137
|
+
### Prepared presentation
|
|
138
|
+
|
|
139
|
+
`preparePresentation({ payload, coverage, port }, { signal? })` acquires custody without running a
|
|
140
|
+
sink. A returned `PreparedPresentation<P>` exposes `payload`, pre-effect `eligible(signal?)`, and
|
|
141
|
+
promise-cached `release()` for abandonment. It is a local one-shot capability, not a durable row and
|
|
142
|
+
not a public success writer.
|
|
143
|
+
|
|
144
|
+
`presentPrepared(handle, sink, control?)` specializes the batch lifecycle to one item.
|
|
145
|
+
`presentPreparedBatch(handles, render, sink, control?)` takes all supplied custody before its first
|
|
146
|
+
await. It rejects duplicate, foreign or used handles before any effect, checks eligibility, then calls
|
|
147
|
+
synchronous side-effect-free `render(eligible)` returning `{ payload, included }`. Included handles
|
|
148
|
+
must be a unique exact subset of those eligible handles; invalid rendering releases custody and
|
|
149
|
+
rejects without presentation evidence. No included items means no sink call.
|
|
150
|
+
|
|
151
|
+
Cancellation is checked immediately before the one sink invocation. There is **no presentation timer**
|
|
152
|
+
and no post-effect cancellation, deferral or currentness veto. The runner awaits the sink and marks
|
|
153
|
+
**all included handles** effect-observed before starting asynchronous settlements. Full coverage
|
|
154
|
+
settles `presented`; clipped coverage settles `clipped`. A thrown sink defaults to `unknown`;
|
|
155
|
+
`classifyError` may explicitly return `failed` (classifier failure stays unknown). Unused handles are
|
|
156
|
+
released, all sibling settlements and cleanup drain even on persistence failure, and later cleanup
|
|
157
|
+
cannot overwrite success or uncertainty.
|
|
158
|
+
|
|
159
|
+
### Mandatory atomic full-consumption settlement
|
|
160
|
+
|
|
161
|
+
The presentation binding's single `settle` operation must enforce:
|
|
162
|
+
|
|
163
|
+
| Completion | Atomic persistence |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `presented` | Complete the captured attempt **and all captured full-consumption receipts in the same transaction**. Return true only when the combined operation commits. |
|
|
166
|
+
| `clipped` | Complete the attempt; no full-consumption receipt. |
|
|
167
|
+
| `failed`, `unknown`, `released` | Complete the attempt; no success consumption receipt. |
|
|
168
|
+
|
|
169
|
+
If receipt writing throws, both receipt writes and attempt completion must roll back. Do not reselect
|
|
170
|
+
items or split `complete` and `recordConsumed` into separately awaited callbacks. Captured ownership
|
|
171
|
+
still fences settlement; request cancellation and new delivery deferrals do not. TypeScript cannot
|
|
172
|
+
supply isolation for a caller, so this is a mandatory port contract, tested in Square's real transaction.
|
|
173
|
+
|
|
174
|
+
Presentation reports distinguish observed sink behavior from durable persistence. A returned sink
|
|
175
|
+
with `not-recorded` or `error` still returned successfully; that alone proves only the supplied sink's
|
|
176
|
+
documented effect, not model consumption or human display. Square explicitly classifies its existing
|
|
177
|
+
rejected sinks as failed and rethrows the original exception after draining. Its single result stays
|
|
178
|
+
`{ presented: true, activity }` only on recorded success, false on ownership refusal; unexpected
|
|
179
|
+
success-settlement errors propagate. Batch returns its original sink value after all settlements,
|
|
180
|
+
with the same error propagation. No schema, storage format or public Square result changes are needed.
|
package/guides/mcp.md
CHANGED
|
@@ -4,7 +4,7 @@ Square provides a stdio MCP server through `square mcp-server`.
|
|
|
4
4
|
|
|
5
5
|
Set `SQUARE_LOCATION` to the default `.square` artifact path; calls may override it with `location`. Relative paths use the server's startup working directory. Join with an explicit `as` name. Later calls may omit `as` only when the artifact recognizes exactly one current name held by the call's exact opaque owner; zero or multiple matches refuse and require explicit selection. An explicit name selects a voice but never grants custody. Request metadata supplies the live Codex (`threadId`) or OpenCode (`ai.opencode/sessionID`) coordinate when present, encoded through `harnessOwner`; otherwise the server-configured owner applies. CLI startup resolves `--owner`/`SQUARE_OWNER`, a complete harness coordinate, or the local user owner in that order, refusing incomplete harness identity. Owner is never a model tool argument. Read-only calls do not need an owner.
|
|
6
6
|
|
|
7
|
-
The server exposes `join`, `express`, `catch`, `history`, `attention`, `
|
|
7
|
+
The server exposes `join`, `express`, `catch`, `history`, `attention`, `done`, and `status`. `attention` takes `action: listen | unlisten | ignore`; `status` also reports who you listen to when a name resolves. `catch` consumes activities. `history` is read-only and accepts stable `act/<index>` cursors. All seven tools return the same human-readable text as the CLI in `content`, without `outputSchema` or `structuredContent`. Square failures set `isError: true` and return readable refusal and recovery text in `content`. Clients keep their native MCP result envelope; machine-readable domain results remain available through the SDK.
|
|
8
8
|
|
|
9
9
|
Claude's bundled plugin configures this server automatically. Its mod supplies live session/cwd/subagent attribution through an out-of-band tool-use-ID association, not AI-visible arguments; see [Claude call identity](claude-native.md#mcp-tools-and-call-identity). The bundled endpoint requires that association rather than falling back to its startup environment.
|
|
10
10
|
|
package/guides/migration.md
CHANGED
|
@@ -4,7 +4,8 @@ Square stores its authority in one versioned SQLite artifact. Format 1 kept a sn
|
|
|
4
4
|
format 2 introduced typed facts; format 3 added `unlisten`; format 4 moved participant custody
|
|
5
5
|
and delivery evidence into the artifact; format 5 added independent delivery deferrals.
|
|
6
6
|
**Format 6 separates participant membership from host attachment; format 7 replaces harness Body
|
|
7
|
-
coordinates with opaque owners
|
|
7
|
+
coordinates with opaque owners; format 8 removes Square hold/resume activities and held state.**
|
|
8
|
+
Existing artifacts are never converted implicitly.
|
|
8
9
|
|
|
9
10
|
Stop all processes using the artifact, make an offline backup, then run:
|
|
10
11
|
|
|
@@ -13,12 +14,16 @@ square --location /path/to/SQUARE.square migrate
|
|
|
13
14
|
square --location /path/to/SQUARE.square doctor
|
|
14
15
|
```
|
|
15
16
|
|
|
16
|
-
The command handles supported formats 2–
|
|
17
|
+
The command handles supported formats 2–7 in place and publishes only final format 8, in one
|
|
17
18
|
transaction. It does not make a backup, stop processes, install a runtime or update another
|
|
18
19
|
artifact. For formats 2/3, also freeze and back up the legacy HostLedger used for owner/evidence
|
|
19
20
|
import. A legacy ledger needing its own conversion must be prepared separately with its old
|
|
20
21
|
runtime's offline tooling. Snapshot format 1 is not accepted by this conversion.
|
|
21
22
|
|
|
23
|
+
Format 7 to 8 deletes hold/resume activities and rows keyed to them, clears replies that point to
|
|
24
|
+
deleted activities, and preserves every surviving activity index. Gaps remain legal; `lastActIndex`
|
|
25
|
+
is the greatest surviving index and `nextActIndex` never reuses a deleted index.
|
|
26
|
+
|
|
22
27
|
## Membership and attachment after conversion
|
|
23
28
|
|
|
24
29
|
Membership owns a participant's join/done history, read horizon and outgoing listens. Attachment
|
|
@@ -101,9 +106,10 @@ not import. Evidence without current or verified completed ownership is skipped
|
|
|
101
106
|
read-only legacy ledger remains available for offline diagnosis; an absent ledger permits route-
|
|
102
107
|
derived custody, but an unreadable or unsupported ledger refuses before changing the square.
|
|
103
108
|
|
|
104
|
-
One transaction imports verified authority/evidence, adds deferral and attachment support
|
|
105
|
-
publishes format
|
|
106
|
-
|
|
109
|
+
One transaction imports verified authority/evidence, adds deferral and attachment support, applies
|
|
110
|
+
the format-7-to-8 deletion, and publishes format 8. Existing conversation and membership facts are
|
|
111
|
+
preserved apart from the deleted hold/resume rows and cleared replies; no intermediate format is
|
|
112
|
+
published. Legacy catch ownership is generation-bound only for exact standing owner
|
|
107
113
|
spellings; otherwise it stays unbound. Legacy routes are consumed only during migration and are
|
|
108
114
|
not a live authority source. The new delivery revision starts at zero. Format 2 first adds support
|
|
109
115
|
for `unlisten`, then follows the same conversion.
|
|
@@ -142,7 +148,7 @@ rows are ignored. Rejoin with the exact migrated owner to republish discovery (o
|
|
|
142
148
|
harness reconnect). This preserves generation, listens and unread activity; do not use takeover
|
|
143
149
|
merely to rebuild the index.
|
|
144
150
|
|
|
145
|
-
Upgrade all attached runtimes before reopening format
|
|
151
|
+
Upgrade all attached runtimes before reopening format 8; older runtimes must not be mixed with it.
|
|
146
152
|
Updating a package does not migrate an artifact, and migration does not install upgraded runtimes.
|
|
147
153
|
After conversion, run read-only `doctor` before restarting clients. To roll back a committed
|
|
148
154
|
conversion, stop all clients and restore the offline backup with its compatible older runtime;
|
|
@@ -53,7 +53,7 @@ for resource lifetimes and adapter selection.
|
|
|
53
53
|
failed reattachment does not block the others. A new or forked session has a different owner and
|
|
54
54
|
restores nothing. Hosts never infer restoration from a historical departure.
|
|
55
55
|
- Participant mutations require both the captured generation and an attached current seat.
|
|
56
|
-
Detach suspends existing handles; they cannot express, catch, listen,
|
|
56
|
+
Detach suspends existing handles; they cannot express, catch, listen, leave or change
|
|
57
57
|
deferrals until reattachment. Rejoin/takeover fences old handles permanently, even if the same
|
|
58
58
|
owner later reacquires the name. Host cleanup checks owner and generation inside its transaction;
|
|
59
59
|
stale, foreign, done or already-detached detach changes nothing. Host `cancelDeliveries` also
|
package/guides/pi-tools.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Pi native tools
|
|
2
2
|
|
|
3
|
-
The existing Square Pi extension registers `square_join`, `square_express`, `square_catch`, `square_history`, `square_attention`, `
|
|
3
|
+
The existing Square Pi extension registers `square_join`, `square_express`, `square_catch`, `square_history`, `square_attention`, `square_done`, and `square_status`. `square_attention` covers listen, unlisten and ignore; `square_status` also shows who you listen to. No additional MCP server or subprocess is needed.
|
|
4
4
|
|
|
5
5
|
Tools use the `square` namespace with codemode exposure. Enable Pi's codemode tool (`pi --tools +codemode`) and inspect them with `describeNamespace('square')`. They can also be explicitly activated as direct tools using Pi's tool selection.
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ overview if there are zero or multiple. The extension encodes the live Pi sessio
|
|
|
22
22
|
`harnessOwner({channel: 'pi', session})`, never a model-provided session id, without mutating
|
|
23
23
|
the process environment.
|
|
24
24
|
|
|
25
|
-
All
|
|
25
|
+
All seven tools return the CLI's human-readable text, without an `outputSchema` or
|
|
26
26
|
`structuredContent`. In Pi codemode, a successful call resolves to a `string`:
|
|
27
27
|
use `text(result)`, not `text(result.text)`. Failures are marked as failed tool results;
|
|
28
28
|
codemode rejects with the readable error and recovery commands rather than returning
|
|
@@ -20,7 +20,7 @@ Deliverer evidence only, **not independent review or acceptance**.
|
|
|
20
20
|
|
|
21
21
|
| Removed | Canonical owner / retained boundary |
|
|
22
22
|
| --- | --- |
|
|
23
|
-
| `CatchDecision`, its unused `changed`, and its all-full perception map | `CatchSelection` contains raw selected activities, participant, cursor/remaining, say ordinals, clock, count/
|
|
23
|
+
| `CatchDecision`, its unused `changed`, and its all-full perception map | `CatchSelection` contains raw selected activities, participant, cursor/remaining, say ordinals, clock, count/cap/terminal facts. Pure `decideCatch` selects and writes receipts through `SquareWrite`, then captures these facts in that transaction. |
|
|
24
24
|
| `CatchSelectionResult` combining public activities with a second raw observation | `catchUp` admits the owner, checks the lease ID and invokes `decideCatch` in one receipt transaction, publishes presence best effort, and returns that exact selection. It no longer performs public conversion. |
|
|
25
25
|
| `CatchSelectionObservation` and `WatchPresentation` | `catchOwned` carries the same selection through completion, alongside actual lifecycle stop, waitStarted and replaced facts. No second selected-record wrapper or public page is built inside the lifecycle. |
|
|
26
26
|
| Completion's separate empty-result construction | `observeCatchSelection` captures the same concrete contract using `SquareRead` without marking seen. Only a completion without a committed selection calls it; it does not reopen or rehydrate a committed page. Empty ordinals are `{}` without an unnecessary selector call. |
|
|
@@ -34,7 +34,7 @@ Necessary abstractions remain: typed transaction capabilities, pure selection, o
|
|
|
34
34
|
## Preserved lifecycle and observation timing
|
|
35
35
|
|
|
36
36
|
- Lease acquisition retains its own transaction. Lease-ID validation, selection, markSeen, cursor, remaining and selected-page facts share the `catchUp` receipt transaction. A replaced waiter cannot insert a receipt in the gap after its heartbeat.
|
|
37
|
-
- Revision is still captured before evaluation. Heartbeats,
|
|
37
|
+
- Revision is still captured before evaluation. Heartbeats, lease-paused quiet expiry, replacement and ID-fenced signal-free cleanup remain unchanged. Already-active/replaced/capped/quorum remain distinct from empty-now/stale.
|
|
38
38
|
- Successful selection never falls back to a postcommit page/context read. Presence publication, lease release and notification enrichment remain best effort after authoritative consumption. Optional nearby presence can be unavailable without erasing the selected page.
|
|
39
39
|
- Empty terminal/quiet completion reads authoritative cursor and filtered remaining without markSeen. It never invents a null cursor after consumption. Seen holes, continuous cursor, historical catch and notification latest-join semantics remain unchanged.
|
|
40
40
|
- Public conversion now occurs later, at each API exit, rather than in the action/lifecycle. Selection facts still reflect the receipt transaction, not optional presence time. Empty completion's clock is captured when constructing that read-only selection; no selected body is hydrated. No SDK default or wire result changes are intended.
|
|
@@ -80,9 +80,9 @@ The first full run exposed an unnecessary `sayOrdinals([])` read on empty SDK co
|
|
|
80
80
|
|
|
81
81
|
Boundary evidence:
|
|
82
82
|
|
|
83
|
-
- `performance`: real raw selection hydrates only its bounded page; remaining uses directedCount; presence/rendering never rehydrates it. A new postcommit mutation fixture changes own count
|
|
84
|
-
- `application-boundary`: a real delivered receipt triggers failing host publication and a failing postcommit clock/presence read; catch still returns the consumed public page and its original projection facts, with enrichmentUnavailable and no raw activities projection. A later catch is empty. Existing real leased replacement, cancellation cleanup
|
|
85
|
-
- `presentation`: public/raw rendering parity checks multiline body, activity ID, reply ID, mention metadata, done and listen; presence omits bodies. Raw read remains empty
|
|
83
|
+
- `performance`: real raw selection hydrates only its bounded page; remaining uses directedCount; presence/rendering never rehydrates it. A new postcommit mutation fixture changes own count and pending rows after selection and rejects any action-level read: returned ordinals/cursor/remaining/count/clock still match the receipt transaction. A mismatched lease ID returns null without revision/receipt change.
|
|
84
|
+
- `application-boundary`: a real delivered receipt triggers failing host publication and a failing postcommit clock/presence read; catch still returns the consumed public page and its original projection facts, with enrichmentUnavailable and no raw activities projection. A later catch is empty. Existing real leased replacement, cancellation cleanup and quiet expiry fixtures pass, including the preserved consumed cursor after an actual say.
|
|
85
|
+
- `presentation`: public/raw rendering parity checks multiline body, activity ID, reply ID, mention metadata, done and listen; presence omits bodies. Raw read remains empty.
|
|
86
86
|
- `row-domain`, `core`, `delivery`, `perception-projection`: filter-before-limit, exact repeat, original receipt timestamp, gap/cursor and latest-join differences remain tested. Obsolete changed assertions were replaced by actual receipts, or removed only where the immediately adjacent unchanged receiptAssignments equality already proves no write. No boundary assertion was weakened to preserve a retired mechanism.
|
|
87
87
|
- `operation-cancellation`, `square-facade`: commit survives response abort; SDK returns only its established CatchResult, no application body projections. CLI process coverage retains filtered continuation, mention/body visibility, stable IDs and lifecycle feedback. MCP continues serializing data only.
|
|
88
88
|
- Production reference search for `CatchDecision|CatchSelectionResult|CatchSelectionObservation|WatchPresentation|exposeCaught` returned no matches (excluding dist/node_modules); `git diff --check` passed. CLI has no `projection.activities.find` or raw reconstruction.
|
|
@@ -57,9 +57,9 @@ 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
|
|
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. 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
|
-
- **Projection:** ordinals, presence anchors,
|
|
62
|
+
- **Projection:** ordinals, presence anchors, roster 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.
|
|
64
64
|
|
|
65
65
|
## Verification
|
|
@@ -63,14 +63,14 @@ For completeness, **whole integrated source** against fixed `501ddc2` is 110 fil
|
|
|
63
63
|
|
|
64
64
|
Full versus filtered roster is a real distinction: status data omits never-joined historical actor names, while participants data retains them. `knownParticipantCount` separately preserves the complete-roster continuation count; it is not `status.data.participants.length` or the standing count.
|
|
65
65
|
|
|
66
|
-
The amended guidance's reachable-latest clause is applied: the selector remains newest `say`/`done`. Both require an actor in valid storage, whereas
|
|
66
|
+
The amended guidance's reachable-latest clause is applied: the selector remains newest `say`/`done`. Both require an actor in valid storage, whereas `read` is not selected. Therefore status has no reachable raw/public latest distinction. The conversion guard remains conservative, but no hypothetical duplicate projection is retained. History and other operations' genuine raw/public distinctions are untouched by this lane.
|
|
67
67
|
|
|
68
68
|
## Behavior and timing evidence
|
|
69
69
|
|
|
70
|
-
- `test/projections.test.js`: exact canonical status data, full versus filtered roster, absent duplicate projections,
|
|
70
|
+
- `test/projections.test.js`: exact canonical status data, full versus filtered roster, absent duplicate projections, cap/throttle fields, and read exclusion from latest selection. Existing viewer perception, exact-spelling rejoin and bounded hydration assertions remain. Shared watching/recent/lingering policy remains read-only.
|
|
71
71
|
- `test/application-boundary.test.js`: configured named, discovered (including blank environment name), explicit blank, explicit override and ambient viewer; body perception and attention names; unchanged artifact state and ownership/presence ledger after status.
|
|
72
72
|
- `test/core.test.js`: status and participants continue sharing actual authored and receipt times, including a fresh rejoin and watcher.
|
|
73
|
-
- `test/process/square-cli-render.test.js`: the compact ten-person preview now includes a valid historical never-joined actor in the artifact. Status still hides that actor but its executable continuation uses the full count 14 rather than filtered count 13; participants prints the complete roster. Existing
|
|
73
|
+
- `test/process/square-cli-render.test.js`: the compact ten-person preview now includes a valid historical never-joined actor in the artifact. Status still hides that actor but its executable continuation uses the full count 14 rather than filtered count 13; participants prints the complete roster. Existing exact rejoin, attention, clipping/public-id continuation and presence feedback remain covered.
|
|
74
74
|
|
|
75
75
|
No observation timing change is intended: optional viewer discovery still precedes status's resource read; the clock is sampled once inside the transaction, and all domain data, classification, perception and rendering annotations are assembled in that read. Queries perform no I/O or mutations themselves. SDK participant/snapshot shapes and MCP serialization of data remain unchanged. No join/claim is introduced.
|
|
76
76
|
|
|
@@ -25,7 +25,7 @@ Deliverer evidence, not independent review or acceptance.
|
|
|
25
25
|
| `square-state.ts` legacy SQLite framing | `square-sqlite.ts`: read-only owned-v1 recognition beside row framing/codecs |
|
|
26
26
|
| `square-state.ts` legacy payload validation | `square-migration.ts`: explicit legacy envelope, order/gap and assigned-reference checks, permissive finite route data and path-specific nonfinite rejection |
|
|
27
27
|
| General-model snapshot/runtime DTOs | `square-sqlite.ts`: explicit import/export DTOs, not runtime transaction state |
|
|
28
|
-
| Dead `StoredActHead`, `
|
|
28
|
+
| Dead `StoredActHead`, `findParticipantName`, empty `ReceiverRoute` alias | Deleted; interchange routes use the existing `WakeRoute` type |
|
|
29
29
|
|
|
30
30
|
There are no forwarding stubs. The renamed build preparation is the actual implementation, not an alias. File SDK build, synchronous memory build and application build share it. Application build returns the normalized configuration from canonical creation rather than reconstructing it. Ordinary storage/resource imports perform no guide reads; the first build reads only its selected guides and caches them.
|
|
31
31
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Transaction-local receive and consumption
|
|
2
|
+
|
|
3
|
+
`@astrosheep/square/receive` admits items and their settled audience, selects
|
|
4
|
+
received heads without consumption, and records sparse first-write-wins receipts.
|
|
5
|
+
It has no runtime dependencies, Square membership, SQLite or transport requirement.
|
|
6
|
+
For computing an audience before admission, see [attention](attention-primitive.md).
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { receive, consumeReceived } from '@astrosheep/square/receive';
|
|
10
|
+
|
|
11
|
+
// Both callbacks belong to your storage implementation, not this package.
|
|
12
|
+
store.transaction(tx => receive(tx, {
|
|
13
|
+
item: { key: 'opaque:west/7?hello', data: { text: 'Hello' } },
|
|
14
|
+
audience: [{ recipient: 'east:bob', via: 'link' }],
|
|
15
|
+
}));
|
|
16
|
+
const page = store.transaction(tx => consumeReceived(tx, 'east:bob', {
|
|
17
|
+
kind: 'page', query: { sender: 'west:alice' }, limit: 10,
|
|
18
|
+
}, Date.now()));
|
|
19
|
+
// { items: [{ key, data, via }], newlyConsumed, remaining }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`store` and `tx` above are caller-owned storage, not exports. Implement
|
|
23
|
+
`ReceiveRead<K,D,V,Q>` / `ReceiveWrite<K,D,V,Q>` structurally; each function only
|
|
24
|
+
requires the `Pick` of methods it uses. `K extends string | number` is an opaque
|
|
25
|
+
equality identity: no ordering, parsing, numeric sequence, or `act/N` convention
|
|
26
|
+
is imposed. The storage defines head order and query semantics. `D`, route `V`,
|
|
27
|
+
and query `Q` are caller data. Recipients are strings; the caller owns canonical
|
|
28
|
+
identity and eligibility. Item and address keys must be unique in storage.
|
|
29
|
+
|
|
30
|
+
## Capabilities and ownership
|
|
31
|
+
|
|
32
|
+
- `insertItem({key,data})` and `insertAddress(key,{recipient,via},order)` admit an
|
|
33
|
+
item and its audience in supplied order. `receive` permits an empty audience.
|
|
34
|
+
Supply unique recipient keys; duplicate items/addresses must throw, never
|
|
35
|
+
overwrite or silently deduplicate. Roll back the whole admission on failure.
|
|
36
|
+
- `heads(recipient,query,{unconsumed,limit})` applies the query and consumption
|
|
37
|
+
predicate **before** limiting, returning ordered `{key,via}` heads.
|
|
38
|
+
`addressed(recipient,key)` ignores receipt state, but checks addressedness.
|
|
39
|
+
- `load(keys)` hydrates the selected keys once as a `ReadonlyMap<K,D>`.
|
|
40
|
+
Missing keys are errors; an explicitly stored `undefined` value is not missing.
|
|
41
|
+
`count(recipient,query,unconsumed)` counts the same selection without a limit.
|
|
42
|
+
- `receipt({recipient,item})` reads `{at}` or `undefined`.
|
|
43
|
+
`insertReceipt(ref,at)` returns true only for a new coordinate and preserves the
|
|
44
|
+
first timestamp. The identity is `(recipient,item)`, not a cursor or generation.
|
|
45
|
+
|
|
46
|
+
All functions are synchronous. Supply capabilities from **one isolated,
|
|
47
|
+
caller-owned transaction**, with storage uniqueness constraints and rollback on
|
|
48
|
+
any thrown error, including failures during hydration, receipt insertion or the
|
|
49
|
+
final count. No capability or selected page should escape that transaction for
|
|
50
|
+
later consumption. The leaf does not start, commit, retry or emulate transactions.
|
|
51
|
+
Its atomicity depends on this caller obligation.
|
|
52
|
+
|
|
53
|
+
## Selection and receipts
|
|
54
|
+
|
|
55
|
+
`selectReceivedHeads(tx,recipient,selection)` never hydrates or writes. A page is
|
|
56
|
+
`{kind:'page',query,limit}` and always selects unconsumed heads; `limit` must be a
|
|
57
|
+
positive safe integer, with no policy maximum. An exact selection is
|
|
58
|
+
`{kind:'exact',key,remainingQuery}` and remains repeatable after consumption.
|
|
59
|
+
|
|
60
|
+
`consumeReceived` selects inside the supplied transaction, hydrates all selected
|
|
61
|
+
keys before any receipt insertion, preserves head order, records the captured
|
|
62
|
+
coordinates and counts matching unconsumed items. Exact remaining uses
|
|
63
|
+
`remainingQuery`; page remaining uses `query`. Repeating exact consumption returns
|
|
64
|
+
the same item with `newlyConsumed: 0`, not a second receipt.
|
|
65
|
+
|
|
66
|
+
`recordConsumed(tx,refs,at)` only needs `insertReceipt`. It records captured
|
|
67
|
+
coordinates without reselecting, loading or checking eligibility. Duplicate refs
|
|
68
|
+
are idempotent through storage and cannot change the first timestamp. Timestamps
|
|
69
|
+
must be finite numbers (negative/fractional timestamps are allowed). Nonnumber
|
|
70
|
+
limits/timestamps throw `TypeError`; out-of-range numbers throw `RangeError`.
|
|
71
|
+
`ReceiveError` exposes `code: 'not_addressed' | 'missing_item'` and the opaque `key`.
|
|
72
|
+
Storage errors propagate unchanged; they still require caller rollback.
|
|
73
|
+
|
|
74
|
+
This is not a remote message protocol, replay envelope, permission system,
|
|
75
|
+
ordering service, billing ledger or exactly-once external effect guarantee.
|
|
76
|
+
Delivery attempts and presentation are separate from consumption. The
|
|
77
|
+
[symmetric domains example](symmetric-domains.md) composes all three public
|
|
78
|
+
primitive entrypoints without constructing Square.
|
|
79
|
+
|
|
80
|
+
## Square composition
|
|
81
|
+
|
|
82
|
+
Square uses these functions for production landing, catch and `markSeen` against
|
|
83
|
+
its existing activity, audience and receipt tables. Numeric activity indexes stay
|
|
84
|
+
internal keys; the primitive does not know Square IDs. Square retains validation,
|
|
85
|
+
limits, filtering, perception, ownership, leases, hints and error mapping. The
|
|
86
|
+
empty-catch read probe does not hydrate or acquire a writer; a nonempty probe is
|
|
87
|
+
reselected inside the writer. Ordinary catch sees historical receipt holes,
|
|
88
|
+
including before rejoin; proactive pending still starts after the latest join.
|
|
89
|
+
The artifact schema/format and receipt identity are unchanged. See the
|
|
90
|
+
[Square API](square-api.md) for product operations.
|
|
@@ -10,7 +10,7 @@ Candidate implementation: `833d6f15c9071767eb49a9562a4c42a93c6f4000` plus post-r
|
|
|
10
10
|
| Whole-history fold on normal operations; replay delivery/perception closures | `square-domain.ts::deriveLanding` maintains participant, attention and ordered audience indices once at landing; `runtime.ts` computes cursor/presence/terminal from narrow domain facts. |
|
|
11
11
|
| `FromState`/delta bridges and old core append/observation update helpers | Removed. `SquareWrite.land/markSeen/putLease/removeLease/replaceRoutes` are the finite domain mutations. Memory uses the same SQLite driver in `:memory:`, not a second selector/policy implementation. |
|
|
12
12
|
| Renderer `.state` inputs and replay-based ordinal/perception lookup | `views.ts`, `perception-projection.ts` and presentation operations settle selected bodies, ordinals, counts and perceptions inside the transaction; renderers receive detached values. |
|
|
13
|
-
| Join/status/
|
|
13
|
+
| Join/status/done snapshot loads for counts | `joinFacts`, standing counts, roster/status aggregates and header reads. Public SDK snapshot is no longer used by these production callers. |
|
|
14
14
|
| Global whole-history notification/wake enumeration | Bodyless `pendingAudience` groups with a captured activity upper bound and recipient join coordinates; receivers use their own `directed` relation. Scans advance past withheld groups and do not restart on unrelated writes. |
|
|
15
15
|
| Whole-history native/Claude currentness and cancellation | Exact pending facts, ordered routes, lease and captured host fences; cancellation selects activity heads by descending coordinate and tests timestamp. Host/network work stays outside artifact transactions. |
|
|
16
16
|
| Preliminary full load before file-backed open/probe/wait | Validated header/schema boundary, revision-only observer; selected row validation on access. Full doctor is explicit. |
|