@astrosheep/square 0.3.93 → 0.3.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/activity-feed.d.ts +3 -5
- package/dist/activity-feed.js +16 -14
- package/dist/artifact.js +3 -3
- package/dist/attention.d.ts +19 -0
- package/dist/attention.js +30 -0
- package/dist/boundary-presentation.d.ts +2 -2
- package/dist/boundary-presentation.js +33 -40
- package/dist/catch-decisions.d.ts +5 -8
- package/dist/catch-decisions.js +45 -25
- package/dist/claude-delivery-status.js +10 -4
- package/dist/claude-delivery.js +19 -11
- package/dist/claude-mod.js +24 -53
- package/dist/cli/context.d.ts +9 -4
- package/dist/cli/context.js +30 -27
- package/dist/cli/express-presentation.d.ts +3 -1
- package/dist/cli/express-presentation.js +28 -16
- package/dist/cli/json.d.ts +3 -0
- package/dist/cli/json.js +14 -0
- package/dist/cli/mcp-server-command.js +2 -2
- package/dist/cli/observation-commands.d.ts +1 -3
- package/dist/cli/observation-commands.js +43 -56
- package/dist/cli/program.js +3 -3
- package/dist/cli/registry.js +7 -6
- package/dist/cli/square-commands.d.ts +0 -2
- package/dist/cli/square-commands.js +30 -44
- package/dist/codex-hook.d.ts +3 -2
- package/dist/codex-hook.js +13 -4
- package/dist/codex-queue.js +4 -4
- package/dist/decisions.d.ts +5 -16
- package/dist/decisions.js +9 -33
- package/dist/delivery-attempts.d.ts +52 -0
- package/dist/delivery-attempts.js +73 -0
- package/dist/delivery-deferral.js +2 -2
- package/dist/delivery-effects.d.ts +139 -0
- package/dist/delivery-effects.js +163 -0
- package/dist/delivery-health.d.ts +0 -1
- package/dist/delivery-health.js +1 -3
- package/dist/delivery-operations.d.ts +2 -2
- package/dist/delivery-operations.js +76 -101
- 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 +7 -6
- package/dist/help.js +14 -14
- package/dist/http-delivery.d.ts +16 -0
- package/dist/http-delivery.js +101 -0
- package/dist/inbox.d.ts +9 -22
- package/dist/inbox.js +23 -27
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.js +23 -24
- package/dist/model.d.ts +12 -21
- package/dist/model.js +5 -8
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.js +8 -5
- package/dist/operation-presentation.d.ts +6 -6
- package/dist/operation-presentation.js +55 -58
- package/dist/owner.d.ts +11 -0
- package/dist/owner.js +32 -0
- package/dist/paseo-delivery.d.ts +4 -1
- package/dist/paseo-delivery.js +7 -12
- package/dist/paseo-state.d.ts +2 -2
- package/dist/paseo-state.js +6 -4
- package/dist/plugins/opencode/delivery.js +27 -15
- package/dist/ports.d.ts +18 -47
- package/dist/presentation-operations.d.ts +14 -19
- package/dist/presentation-operations.js +51 -61
- package/dist/presentation.d.ts +7 -17
- package/dist/presentation.js +46 -91
- package/dist/receive.d.ts +66 -0
- package/dist/receive.js +54 -0
- package/dist/runtime.d.ts +1 -8
- package/dist/runtime.js +2 -17
- package/dist/seats.d.ts +2 -3
- package/dist/seats.js +7 -15
- package/dist/session-lifecycle.d.ts +6 -2
- package/dist/session-lifecycle.js +39 -11
- package/dist/sqlite-square.d.ts +36 -23
- package/dist/sqlite-square.js +162 -211
- package/dist/square-api.d.ts +16 -11
- package/dist/square-api.js +27 -23
- package/dist/square-core.d.ts +0 -14
- package/dist/square-core.js +0 -9
- package/dist/square-domain.d.ts +4 -2
- package/dist/square-domain.js +65 -52
- package/dist/square-facade.d.ts +47 -105
- package/dist/square-index.d.ts +5 -13
- package/dist/square-index.js +13 -38
- package/dist/square-legacy-framing.d.ts +2 -0
- package/dist/square-legacy-framing.js +8 -0
- package/dist/square-location.d.ts +1 -14
- package/dist/square-location.js +4 -70
- package/dist/square-migration-host-ledger.d.ts +2 -2
- package/dist/square-migration-host-ledger.js +6 -5
- package/dist/square-migration.d.ts +4 -1
- package/dist/square-migration.js +93 -38
- package/dist/square-receive.d.ts +6 -0
- package/dist/square-receive.js +18 -0
- package/dist/square-sqlite.d.ts +9 -3
- package/dist/square-sqlite.js +139 -114
- package/dist/square-tools.d.ts +7 -10
- package/dist/square-tools.js +21 -61
- package/dist/stream.js +4 -5
- package/dist/views.d.ts +23 -13
- package/dist/views.js +47 -53
- package/dist/wakes.d.ts +1 -5
- package/dist/wakes.js +4 -6
- package/examples/symmetric-domains.mjs +250 -0
- package/guides/application-facade-delivery-evidence.md +6 -6
- package/guides/attention-primitive.md +32 -0
- package/guides/change-waits.md +2 -2
- package/guides/claude-native.md +18 -9
- package/guides/codex-delivery.md +17 -6
- package/guides/delivery-primitives.md +180 -0
- package/guides/mcp-connection-lifetime.md +1 -1
- package/guides/mcp.md +3 -3
- package/guides/migration.md +148 -151
- package/guides/operation-cancellation.md +1 -1
- package/guides/participant-ownership.md +78 -47
- package/guides/pi-tools.md +34 -5
- 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 +22 -28
- package/guides/square-api.md +314 -91
- package/guides/symmetric-domains.md +92 -0
- package/package.json +14 -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/opencode/delivery.ts +27 -17
- package/plugins/paseo/client/palette.ts +18 -18
- package/plugins/paseo/client/square-message.tsx +17 -23
- package/plugins/pi/square-pi.js +17 -17
- package/skills/square/SKILL.md +2 -6
- package/dist/square-backend.d.ts +0 -13
- package/dist/square-backend.js +0 -1
- package/dist/square-stdio.d.ts +0 -22
- package/dist/square-stdio.js +0 -235
- package/dist/stdio-server.d.ts +0 -3
- package/dist/stdio-server.js +0 -212
- package/guides/backends.md +0 -193
package/dist/square-migration.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
3
|
import { openExistingSquareDatabase } from './artifact.js';
|
|
3
4
|
import { inSqliteTransaction } from './sqlite-transaction.js';
|
|
4
5
|
import { canonicalPath, canonicalPathSync } from './canonical-path.js';
|
|
5
|
-
import {
|
|
6
|
+
import { harnessOwner, decodeHarnessOwner } from './owner.js';
|
|
7
|
+
import { formatActivityId, isWakeRouteKind, nameKey } from './model.js';
|
|
6
8
|
import { parseActivityId } from './square-core.js';
|
|
7
9
|
import { readLegacyHostData } from './square-migration-host-ledger.js';
|
|
8
10
|
import { legacyRowFramingIssue, FORMAT4_ADDED_OBJECTS } from './square-legacy-framing.js';
|
|
9
|
-
import { APPLICATION_ID, ACTIVITIES_TABLE_SQL, ACTIVITY_INDEXES_SQL, CURRENT_USER_VERSION, V2_USER_VERSION, V3_USER_VERSION, V4_USER_VERSION, SCHEMA_SQL, FORMAT4_SCHEMA_SQL, DELIVERY_DEFERRALS_SQL, validateRowFraming, inspectSqlite, createSqliteDriver, invalidArtifact, validateStoredActivity } from './square-sqlite.js';
|
|
11
|
+
import { APPLICATION_ID, ACTIVITIES_TABLE_SQL, ACTIVITY_INDEXES_SQL, CURRENT_USER_VERSION, V2_USER_VERSION, V3_USER_VERSION, V4_USER_VERSION, V5_USER_VERSION, V6_USER_VERSION, V7_USER_VERSION, SCHEMA_SQL, FORMAT4_SCHEMA_SQL, DELIVERY_DEFERRALS_SQL, validateRowFraming, inspectSqlite, createSqliteDriver, invalidArtifact, validateStoredActivity, exportSqliteState, initializeSqlite } from './square-sqlite.js';
|
|
10
12
|
function isObject(value) {
|
|
11
13
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
12
14
|
}
|
|
@@ -23,6 +25,9 @@ function isNonNegativeInteger(value) {
|
|
|
23
25
|
function isStringArray(value) {
|
|
24
26
|
return Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
25
27
|
}
|
|
28
|
+
function sameCoordinate(left, right) {
|
|
29
|
+
return left.channel === right.channel && left.session === right.session && left.agent === right.agent;
|
|
30
|
+
}
|
|
26
31
|
function validateRecord(value, item) {
|
|
27
32
|
return isObject(value) && Object.entries(value).every(([key, candidate]) => key.length > 0 && item(candidate));
|
|
28
33
|
}
|
|
@@ -130,19 +135,48 @@ function standing(database) {
|
|
|
130
135
|
return createSqliteDriver(database).roster().filter((participant) => participant.joined).length;
|
|
131
136
|
}
|
|
132
137
|
const ACTIVITY_INDEX_NAMES = ['activity_kind_index', 'activity_actor_index', 'activity_say_actor_index', 'activity_say_time', 'activity_bell_actor_time'];
|
|
133
|
-
function
|
|
138
|
+
function migrateActivities(database) {
|
|
139
|
+
// Only activity identity references are deleted. Range watermarks (read.through and
|
|
140
|
+
// delivery cancellation boundaries) remain meaningful even when their endpoint is gone.
|
|
141
|
+
for (const table of ['landed_audience', 'receipts', 'delivery_evidence']) {
|
|
142
|
+
database.exec(`DELETE FROM ${table} WHERE act_index IN (SELECT act_index FROM activities WHERE kind IN ('hold','resume'));`);
|
|
143
|
+
}
|
|
134
144
|
database.exec([
|
|
145
|
+
"UPDATE activities SET reply_index=NULL WHERE reply_index IN (SELECT act_index FROM activities WHERE kind IN ('hold','resume'));",
|
|
135
146
|
...ACTIVITY_INDEX_NAMES.map((name) => `DROP INDEX ${name};`),
|
|
136
|
-
'ALTER TABLE activities RENAME TO
|
|
147
|
+
'ALTER TABLE activities RENAME TO activities_legacy;',
|
|
137
148
|
ACTIVITIES_TABLE_SQL,
|
|
138
|
-
|
|
139
|
-
'DROP TABLE
|
|
149
|
+
"INSERT INTO activities(act_index,at,kind,actor_json,actor_key_json,reach,reply_index,payload_json) SELECT act_index,at,kind,actor_json,actor_key_json,reach,reply_index,payload_json FROM activities_legacy WHERE kind NOT IN ('hold','resume') ORDER BY act_index;",
|
|
150
|
+
'DROP TABLE activities_legacy;',
|
|
140
151
|
...ACTIVITY_INDEXES_SQL.map((sql) => `${sql};`),
|
|
141
152
|
].join('\n'));
|
|
153
|
+
// Actor-bearing deleted activities and cleared replies can change maintained indices.
|
|
154
|
+
// Replay surviving facts only, without lowering the authoritative next allocator.
|
|
155
|
+
const names = database.prepare('SELECT name_key_json,name_json FROM participants').all();
|
|
156
|
+
const rebuilt = new DatabaseSync(':memory:');
|
|
157
|
+
try {
|
|
158
|
+
initializeSqlite(rebuilt, exportSqliteState(database));
|
|
159
|
+
// Canonical spelling is an established identity fact, not the spelling of
|
|
160
|
+
// whichever actor activity happens to survive this migration first.
|
|
161
|
+
const retainName = rebuilt.prepare('UPDATE participants SET name_json=? WHERE name_key_json=?');
|
|
162
|
+
for (const row of names)
|
|
163
|
+
retainName.run(row.name_json, row.name_key_json);
|
|
164
|
+
for (const table of ['participants', 'attention', 'landed_audience']) {
|
|
165
|
+
database.exec(`DELETE FROM ${table};`);
|
|
166
|
+
for (const row of rebuilt.prepare(`SELECT * FROM ${table}`).all()) {
|
|
167
|
+
const columns = Object.keys(row);
|
|
168
|
+
database.prepare(`INSERT INTO ${table}(${columns.join(',')}) VALUES(${columns.map(() => '?').join(',')})`)
|
|
169
|
+
.run(...Object.values(row));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
rebuilt.close();
|
|
175
|
+
}
|
|
142
176
|
}
|
|
143
177
|
function validateCurrentFraming(database, location) {
|
|
144
178
|
validateRowFraming(database, CURRENT_USER_VERSION, location);
|
|
145
|
-
|
|
179
|
+
inspectSqlite(database);
|
|
146
180
|
}
|
|
147
181
|
function assertSource(condition, detail = 'row is malformed.') {
|
|
148
182
|
if (!condition)
|
|
@@ -190,12 +224,12 @@ function decodeLegacyRoute(row) {
|
|
|
190
224
|
assertSource(row.participant_key_json === JSON.stringify(nameKey(participant)), 'route participant key is malformed.');
|
|
191
225
|
const sessionId = decodeJsonString(row.session_json);
|
|
192
226
|
sourceFinite(row.updated_at);
|
|
193
|
-
const
|
|
194
|
-
|
|
227
|
+
const coordinate = { channel: parsed.channel, session: sessionId, ...(parsed.extra.agent === undefined ? {} : { agent: parsed.extra.agent }) };
|
|
228
|
+
harnessOwner(coordinate);
|
|
195
229
|
const address = parsed.address;
|
|
196
230
|
if (row.kind === 'claude-native')
|
|
197
231
|
assertSource(address.sessionId === undefined || address.sessionId === sessionId, 'native route session conflicts with its body.');
|
|
198
|
-
return { location: parsed.location, participant,
|
|
232
|
+
return { location: parsed.location, participant, coordinate,
|
|
199
233
|
wakeAddress: { kind: row.kind, address: { ...address, ...(row.kind === 'claude-native' ? { sessionId } : {}) } } };
|
|
200
234
|
}
|
|
201
235
|
function validateLegacyLease(value) {
|
|
@@ -235,14 +269,15 @@ function planSeats(location, roster, routes, owners, driver) {
|
|
|
235
269
|
const joined = establishingJoin(driver, participant);
|
|
236
270
|
const candidates = localRoutes.filter((route) => nameKey(route.participant) === nameKey(participant.name));
|
|
237
271
|
const owner = owners.find(row => nameKey(row.participant) === nameKey(participant.name));
|
|
238
|
-
const
|
|
239
|
-
if (
|
|
272
|
+
const coordinates = [...candidates.map(route => route.coordinate), ...(owner === undefined ? [] : [owner.coordinate])];
|
|
273
|
+
if (coordinates.length === 0 || !coordinates.every(coordinate => sameCoordinate(coordinate, coordinates[0])))
|
|
240
274
|
continue;
|
|
241
275
|
const address = uniqueSeatAddress(candidates);
|
|
242
276
|
seats.push({
|
|
243
277
|
participant: participant.name,
|
|
244
|
-
|
|
278
|
+
owner: harnessOwner(coordinates[0]),
|
|
245
279
|
generation: formatActivityId(joined),
|
|
280
|
+
attachment: 'attached',
|
|
246
281
|
...(address === undefined ? {} : { wakeAddress: address }),
|
|
247
282
|
});
|
|
248
283
|
}
|
|
@@ -277,7 +312,7 @@ function inspectLegacyRowArtifact(database, location, host) {
|
|
|
277
312
|
const driver = createSqliteDriver(database);
|
|
278
313
|
let activityCount = 0;
|
|
279
314
|
let previous = -1;
|
|
280
|
-
for (const row of database.prepare(
|
|
315
|
+
for (const row of database.prepare("SELECT act_index FROM activities WHERE kind NOT IN ('hold','resume') ORDER BY act_index").iterate()) {
|
|
281
316
|
const index = sourceInteger(row.act_index);
|
|
282
317
|
assertSource(index > previous && index < nextActIndex, 'activity index is malformed or unassigned.');
|
|
283
318
|
const activity = driver.activity(index);
|
|
@@ -321,7 +356,7 @@ function inspectLegacyRowArtifact(database, location, host) {
|
|
|
321
356
|
routes: routes.length,
|
|
322
357
|
recoveredSeats: seats.length,
|
|
323
358
|
unownedStanding: standingCount - seats.length,
|
|
324
|
-
sharedBodySeats: seats.filter(seat => seats.some(other => other !== seat &&
|
|
359
|
+
sharedBodySeats: seats.filter(seat => seats.some(other => other !== seat && other.owner === seat.owner)).length,
|
|
325
360
|
skippedEvidence: host.evidence.length - deliveries.length,
|
|
326
361
|
};
|
|
327
362
|
const sourceToken = legacySourceToken(database);
|
|
@@ -373,26 +408,26 @@ function planLegacyDeliveries(records, seats, driver) {
|
|
|
373
408
|
const native = source.kind === 'wake' && source.nativeDelivery !== undefined;
|
|
374
409
|
if (!participant?.joined && !(participant?.done && native))
|
|
375
410
|
continue;
|
|
376
|
-
|
|
377
|
-
|
|
411
|
+
const seatCoordinate = seat === undefined ? undefined : decodeHarnessOwner(seat.owner);
|
|
412
|
+
if (participant.joined && (seatCoordinate === undefined || seatCoordinate.session !== source.session
|
|
413
|
+
|| seatCoordinate.agent !== source.agent || source.channel !== undefined && seatCoordinate.channel !== source.channel))
|
|
378
414
|
continue;
|
|
379
415
|
const harness = source.nativeDelivery?.harness;
|
|
380
|
-
if (native &&
|
|
381
|
-
|
|
416
|
+
if (native && source.channel !== undefined && source.channel !== (harness === 'claude' ? 'claude-code' : 'opencode'))
|
|
417
|
+
continue;
|
|
418
|
+
if (native && seat !== undefined && harness !== undefined && seat.owner !== harnessOwner({ channel: harness === 'claude' ? 'claude-code' : 'opencode', session: source.session, ...(source.agent === undefined ? {} : { agent: source.agent }) }))
|
|
382
419
|
continue;
|
|
383
420
|
const joined = establishingJoin(driver, participant);
|
|
384
421
|
const generation = formatActivityId(joined);
|
|
385
|
-
if (index <= joined || driver.
|
|
422
|
+
if (index <= joined || driver.activityHeads({ indexes: [index], kinds: ['say'] }, { edge: 'oldest', limit: 1 }).items.length === 0 || driver.directedAt(participant.name, index) === undefined)
|
|
386
423
|
continue;
|
|
387
424
|
if (participant.done) {
|
|
388
425
|
const done = driver.activityHeads({ actors: [participant.name], kinds: ['done'] }, { edge: 'newest', limit: 1 }).items[0];
|
|
389
426
|
if (done === undefined || index >= done.index)
|
|
390
427
|
continue;
|
|
391
|
-
const
|
|
392
|
-
...(source.agent === undefined ? {} : { agent: source.agent }) };
|
|
393
|
-
|
|
394
|
-
continue;
|
|
395
|
-
const coordinate = JSON.stringify([body.channel, body.session, body.agent]);
|
|
428
|
+
const owner = harnessOwner({ channel: harness === 'claude' ? 'claude-code' : 'opencode', session: source.session,
|
|
429
|
+
...(source.agent === undefined ? {} : { agent: source.agent }) });
|
|
430
|
+
const coordinate = JSON.stringify([owner]);
|
|
396
431
|
const key = nameKey(participant.name), previous = completedBodies.get(key);
|
|
397
432
|
completedBodies.set(key, previous === undefined || previous === coordinate ? coordinate : null);
|
|
398
433
|
}
|
|
@@ -429,7 +464,6 @@ function planLegacyDeliveries(records, seats, driver) {
|
|
|
429
464
|
}
|
|
430
465
|
return deliveries.filter(row => row.claimToken === undefined || tokens.get(row.claimToken) === 1);
|
|
431
466
|
}
|
|
432
|
-
const V4_REBUILT_TABLES = ['square_meta', 'catch_leases'];
|
|
433
467
|
function tableDefinition(name) {
|
|
434
468
|
const definition = SCHEMA_SQL.split(';').map((statement) => statement.trim()).find((statement) => statement.startsWith(`CREATE TABLE ${name} (`));
|
|
435
469
|
if (definition === undefined)
|
|
@@ -439,16 +473,32 @@ function tableDefinition(name) {
|
|
|
439
473
|
function currentAdditionStatements() {
|
|
440
474
|
return SCHEMA_SQL.split(';').map((statement) => statement.trim()).filter((statement) => {
|
|
441
475
|
const match = /^(?:CREATE (?:UNIQUE )?TABLE|CREATE (?:UNIQUE )?INDEX)\s+([a-z_]+)/i.exec(statement);
|
|
442
|
-
return match !== null && FORMAT4_ADDED_OBJECTS.has(match[1]);
|
|
476
|
+
return match !== null && (FORMAT4_ADDED_OBJECTS.has(match[1]) || match[1] === 'seat_owner');
|
|
443
477
|
}).map((statement) => `${statement};`);
|
|
444
478
|
}
|
|
479
|
+
function migrateSeatOwnership(database, source) {
|
|
480
|
+
const rows = database.prepare('SELECT * FROM seats ORDER BY participant_key_json').all();
|
|
481
|
+
database.exec('ALTER TABLE seats RENAME TO seats_legacy;');
|
|
482
|
+
database.exec(tableDefinition('seats'));
|
|
483
|
+
database.exec('CREATE INDEX seat_owner ON seats(owner_json);');
|
|
484
|
+
const insert = database.prepare('INSERT INTO seats(participant_key_json,participant_json,owner_json,generation_json,wake_address_json,attachment) VALUES(?,?,?,?,?,?)');
|
|
485
|
+
for (const row of rows) {
|
|
486
|
+
const channel = decodeJsonString(row.channel_json, true), session = decodeJsonString(row.session_json, true);
|
|
487
|
+
const agent = row.agent_json === null ? undefined : decodeJsonString(row.agent_json, true);
|
|
488
|
+
const owner = harnessOwner({ channel, session, ...(agent === undefined ? {} : { agent }) });
|
|
489
|
+
const attachment = source === 6 ? row.attachment : 'attached';
|
|
490
|
+
assertSource(attachment === 'attached' || attachment === 'detached', 'seat attachment is malformed.');
|
|
491
|
+
insert.run(row.participant_key_json, row.participant_json, JSON.stringify(owner), row.generation_json, row.wake_address_json, attachment);
|
|
492
|
+
}
|
|
493
|
+
database.exec('DROP TABLE seats_legacy;');
|
|
494
|
+
}
|
|
445
495
|
function importOwnershipAndEvidence(database, plan) {
|
|
446
496
|
for (const generation of plan.leaseGenerations) {
|
|
447
497
|
database.prepare('UPDATE catch_leases SET generation_json=? WHERE owner_json=?').run(JSON.stringify(generation.generation), generation.ownerJson);
|
|
448
498
|
}
|
|
449
|
-
const insertSeat = database.prepare('INSERT INTO seats(participant_key_json,participant_json,
|
|
499
|
+
const insertSeat = database.prepare('INSERT INTO seats(participant_key_json,participant_json,owner_json,generation_json,wake_address_json,attachment) VALUES(?,?,?,?,?,?)');
|
|
450
500
|
for (const seat of plan.seats) {
|
|
451
|
-
insertSeat.run(JSON.stringify(nameKey(seat.participant)), JSON.stringify(seat.participant), JSON.stringify(seat.
|
|
501
|
+
insertSeat.run(JSON.stringify(nameKey(seat.participant)), JSON.stringify(seat.participant), JSON.stringify(seat.owner), JSON.stringify(seat.generation), seat.wakeAddress === undefined ? null : JSON.stringify(seat.wakeAddress), seat.attachment);
|
|
452
502
|
}
|
|
453
503
|
const insertDelivery = database.prepare('INSERT INTO delivery_evidence(participant_key_json,participant_json,generation_json,act_index,kind,attempt_n,outcome,at,expires_at,claim_token_json,payload_json) VALUES(?,?,?,?,?,?,?,?,?,?,?)');
|
|
454
504
|
for (const evidence of plan.deliveries) {
|
|
@@ -468,6 +518,7 @@ function upgradeRowArtifact(database, location, plan) {
|
|
|
468
518
|
importOwnershipAndEvidence(database, plan);
|
|
469
519
|
database.exec('DROP TABLE routes;');
|
|
470
520
|
database.exec(DELIVERY_DEFERRALS_SQL);
|
|
521
|
+
migrateActivities(database);
|
|
471
522
|
database.exec(`PRAGMA user_version = ${CURRENT_USER_VERSION};`);
|
|
472
523
|
validateCurrentFraming(database, location);
|
|
473
524
|
}
|
|
@@ -481,10 +532,9 @@ function validateMigrationSource(database, location) {
|
|
|
481
532
|
throw invalidArtifact(issue);
|
|
482
533
|
return before.userVersion;
|
|
483
534
|
}
|
|
484
|
-
if (before.userVersion === V4_USER_VERSION) {
|
|
485
|
-
validateRowFraming(database,
|
|
486
|
-
|
|
487
|
-
return V4_USER_VERSION;
|
|
535
|
+
if (before.userVersion === V4_USER_VERSION || before.userVersion === V5_USER_VERSION || before.userVersion === V6_USER_VERSION || before.userVersion === V7_USER_VERSION) {
|
|
536
|
+
validateRowFraming(database, before.userVersion, location);
|
|
537
|
+
return before.userVersion;
|
|
488
538
|
}
|
|
489
539
|
if (before.userVersion === CURRENT_USER_VERSION) {
|
|
490
540
|
validateCurrentFraming(database, location);
|
|
@@ -495,7 +545,10 @@ function validateMigrationSource(database, location) {
|
|
|
495
545
|
/**
|
|
496
546
|
* Explicit conversion of the supported legacy formats. Row-backed versions 2 and 3 are
|
|
497
547
|
* preflighted read-only, then receive ownership/evidence and deferral storage in one
|
|
498
|
-
* format-
|
|
548
|
+
* format-8 transaction. Formats 4/5 gain attachment; format 4 also gains empty deferrals.
|
|
549
|
+
* All legacy seats are encoded as opaque owners, preserving format-6 attachment.
|
|
550
|
+
* Every source drops obsolete activities and their identity references, clears dangling
|
|
551
|
+
* replies and rebuilds derived indices; surviving ids and allocation watermarks remain stable.
|
|
499
552
|
* Legacy delivery evidence is copied from HostLedger only when its owner/session mapping is
|
|
500
553
|
* unique; no source record is retired. Version 1 is not a supported source for this format transition.
|
|
501
554
|
*/
|
|
@@ -506,11 +559,15 @@ export async function migrateSquareFile(location, signal, env = process.env) {
|
|
|
506
559
|
const source = await inSqliteTransaction(database, false, () => validateMigrationSource(database, squarePath), value => value, signal);
|
|
507
560
|
if (source === undefined)
|
|
508
561
|
return { status: 'already-current', standing: standing(database) };
|
|
509
|
-
if (source === V4_USER_VERSION) {
|
|
562
|
+
if (source === V4_USER_VERSION || source === V5_USER_VERSION || source === V6_USER_VERSION || source === V7_USER_VERSION) {
|
|
510
563
|
return await inSqliteTransaction(database, true, () => {
|
|
511
564
|
assertSource(validateMigrationSource(database, squarePath) === source, 'source format changed during migration preflight.');
|
|
512
565
|
}, () => {
|
|
513
|
-
|
|
566
|
+
if (source === V4_USER_VERSION)
|
|
567
|
+
database.exec(DELIVERY_DEFERRALS_SQL);
|
|
568
|
+
if (source !== V7_USER_VERSION)
|
|
569
|
+
migrateSeatOwnership(database, source);
|
|
570
|
+
migrateActivities(database);
|
|
514
571
|
database.exec(`PRAGMA user_version = ${CURRENT_USER_VERSION};`);
|
|
515
572
|
validateCurrentFraming(database, squarePath);
|
|
516
573
|
return { status: 'migrated', standing: standing(database) };
|
|
@@ -530,8 +587,6 @@ export async function migrateSquareFile(location, signal, env = process.env) {
|
|
|
530
587
|
assertSource(lockedPlan.sourceToken === plan.sourceToken, 'source changed during migration preflight.');
|
|
531
588
|
result.plan = lockedPlan;
|
|
532
589
|
}, () => {
|
|
533
|
-
if (source === 2)
|
|
534
|
-
rebuildV2Activities(database);
|
|
535
590
|
const migratedPlan = result.plan;
|
|
536
591
|
upgradeRowArtifact(database, squarePath, migratedPlan);
|
|
537
592
|
result.outcome = { status: 'migrated', standing: migratedPlan.standing, counts: migratedPlan.counts };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AudienceRoute } from './attention.js';
|
|
2
|
+
import type { StoredAct } from './model.js';
|
|
3
|
+
import type { DirectedFilter, SquareRead } from './ports.js';
|
|
4
|
+
import type { ReceiveRead } from './receive.js';
|
|
5
|
+
/** Transaction-local projections only; the artifact still owns indexed selection and bodies. */
|
|
6
|
+
export declare function squareReceiveRead(facts: SquareRead): ReceiveRead<number, StoredAct, AudienceRoute, DirectedFilter>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Transaction-local projections only; the artifact still owns indexed selection and bodies. */
|
|
2
|
+
export function squareReceiveRead(facts) {
|
|
3
|
+
const filter = (query, unconsumed) => {
|
|
4
|
+
const { unseenOnly: _, ...rest } = query;
|
|
5
|
+
return unconsumed ? { ...rest, unseenOnly: true } : rest;
|
|
6
|
+
};
|
|
7
|
+
return {
|
|
8
|
+
heads: (recipient, query, options) => facts.directed(recipient, filter(query, options.unconsumed), { edge: 'oldest', limit: options.limit })
|
|
9
|
+
.items.map(item => ({ key: item.index, via: item.route })),
|
|
10
|
+
addressed(recipient, index) {
|
|
11
|
+
const head = facts.directedAt(recipient, index);
|
|
12
|
+
return head === undefined ? undefined : { key: head.index, via: head.route };
|
|
13
|
+
},
|
|
14
|
+
load: keys => new Map(facts.activities(keys).map(item => [item.index, item])),
|
|
15
|
+
count: (recipient, query, unconsumed) => facts.directedCount(recipient, filter(query, unconsumed)),
|
|
16
|
+
receipt: ref => facts.receipt(ref.recipient, ref.item),
|
|
17
|
+
};
|
|
18
|
+
}
|
package/dist/square-sqlite.d.ts
CHANGED
|
@@ -21,7 +21,10 @@ export declare const APPLICATION_ID = 1397838405;
|
|
|
21
21
|
export declare const V2_USER_VERSION = 2;
|
|
22
22
|
export declare const V3_USER_VERSION = 3;
|
|
23
23
|
export declare const V4_USER_VERSION = 4;
|
|
24
|
-
export declare const
|
|
24
|
+
export declare const V5_USER_VERSION = 5;
|
|
25
|
+
export declare const V6_USER_VERSION = 6;
|
|
26
|
+
export declare const V7_USER_VERSION = 7;
|
|
27
|
+
export declare const CURRENT_USER_VERSION = 8;
|
|
25
28
|
export declare const V1_SNAPSHOT_TABLE = "square_snapshot";
|
|
26
29
|
export interface LegacyFraming {
|
|
27
30
|
readonly applicationId: number;
|
|
@@ -35,15 +38,18 @@ export interface LegacyFraming {
|
|
|
35
38
|
* migration. Anything else is unrelated or unsupported, not repaired.
|
|
36
39
|
*/
|
|
37
40
|
export declare function validateLegacyFraming(database: DatabaseSync, applicationId: number, location?: string): LegacyFraming;
|
|
38
|
-
export declare const ACTIVITIES_TABLE_SQL = "CREATE TABLE activities (\n act_index INTEGER PRIMARY KEY CHECK (act_index BETWEEN 0 AND 9007199254740991),\n at REAL NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('join','done','say','
|
|
41
|
+
export declare const ACTIVITIES_TABLE_SQL = "CREATE TABLE activities (\n act_index INTEGER PRIMARY KEY CHECK (act_index BETWEEN 0 AND 9007199254740991),\n at REAL NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('join','done','say','read','listen','ignore','unlisten')),\n actor_json TEXT COLLATE BINARY NOT NULL,\n actor_key_json TEXT COLLATE BINARY NOT NULL,\n reach TEXT CHECK (reach = 'bell'),\n reply_index INTEGER CHECK (reply_index >= 0 AND reply_index < act_index),\n payload_json TEXT NOT NULL CHECK (json_valid(payload_json)),\n CHECK (kind = 'say' OR (reach IS NULL AND reply_index IS NULL))\n);";
|
|
39
42
|
export declare const ACTIVITY_INDEXES_SQL: readonly ["CREATE INDEX activity_kind_index ON activities(kind, act_index)", "CREATE INDEX activity_actor_index ON activities(actor_key_json, act_index)", "CREATE INDEX activity_say_actor_index ON activities(actor_key_json, act_index) WHERE kind='say'", "CREATE INDEX activity_say_time ON activities(at, act_index) WHERE kind='say'", "CREATE INDEX activity_bell_actor_time ON activities(actor_key_json, at, act_index) WHERE kind='say' AND reach='bell'"];
|
|
40
43
|
export declare const DELIVERY_DEFERRALS_SQL = "CREATE TABLE delivery_deferrals (\n participant_key_json TEXT COLLATE BINARY NOT NULL,\n participant_json TEXT NOT NULL,\n generation_json TEXT NOT NULL,\n deferral_id_json TEXT NOT NULL,\n match_json TEXT NOT NULL CHECK (json_valid(match_json)),\n expires_at REAL NOT NULL,\n PRIMARY KEY (participant_key_json,generation_json,deferral_id_json)\n) WITHOUT ROWID;\nCREATE INDEX delivery_deferral_expiry ON delivery_deferrals(participant_key_json,generation_json,expires_at);";
|
|
41
44
|
export declare const SCHEMA_SQL: string;
|
|
45
|
+
export declare const FORMAT7_SCHEMA_SQL: string;
|
|
46
|
+
export declare const FORMAT6_SCHEMA_SQL: string;
|
|
47
|
+
export declare const FORMAT5_SCHEMA_SQL: string;
|
|
42
48
|
export declare const FORMAT4_SCHEMA_SQL: string;
|
|
43
49
|
export declare function invalidArtifact(detail: string): SquareError;
|
|
44
50
|
export declare function validateStoredActivity(value: unknown): StoredAct;
|
|
45
51
|
export declare function validateWatchLease(value: unknown): WatchLease;
|
|
46
|
-
export declare function validateRowFraming(db: DatabaseSync, version: 2 | 3 | 4 | 5, location?: string): void;
|
|
52
|
+
export declare function validateRowFraming(db: DatabaseSync, version: 2 | 3 | 4 | 5 | 6 | 7 | 8, location?: string): void;
|
|
47
53
|
export declare function validateSqliteHeader(db: DatabaseSync, location?: string): SquareHeader;
|
|
48
54
|
export interface SqliteDriver extends SquareRead, LandingWriter {
|
|
49
55
|
readonly changed: boolean;
|