@astrosheep/square 0.3.86 → 0.3.87

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 (141) hide show
  1. package/dist/artifact.d.ts +6 -1
  2. package/dist/artifact.js +79 -10
  3. package/dist/boundary-presentation.d.ts +5 -4
  4. package/dist/boundary-presentation.js +21 -25
  5. package/dist/catch-decisions.js +2 -1
  6. package/dist/claude-delivery-status.d.ts +8 -2
  7. package/dist/claude-delivery-status.js +26 -10
  8. package/dist/claude-delivery.d.ts +8 -4
  9. package/dist/claude-delivery.js +114 -104
  10. package/dist/claude-mcp-context.js +2 -2
  11. package/dist/claude-mod.js +119 -105
  12. package/dist/cli/context.d.ts +3 -1
  13. package/dist/cli/context.js +25 -1
  14. package/dist/cli/express-presentation.d.ts +3 -1
  15. package/dist/cli/express-presentation.js +14 -10
  16. package/dist/cli/mcp-server-command.js +2 -2
  17. package/dist/cli/observation-commands.js +1 -0
  18. package/dist/cli/registry.js +0 -2
  19. package/dist/cli/square-commands.d.ts +4 -2
  20. package/dist/cli/square-commands.js +21 -6
  21. package/dist/codex-hook.d.ts +3 -3
  22. package/dist/codex-hook.js +4 -4
  23. package/dist/codex-queue.d.ts +5 -6
  24. package/dist/codex-queue.js +9 -5
  25. package/dist/decisions.d.ts +3 -2
  26. package/dist/decisions.js +18 -6
  27. package/dist/delivery-health.d.ts +32 -2
  28. package/dist/delivery-health.js +108 -45
  29. package/dist/delivery-operations.d.ts +1 -2
  30. package/dist/delivery-operations.js +155 -196
  31. package/dist/delivery.d.ts +14 -23
  32. package/dist/delivery.js +48 -18
  33. package/dist/file-lock.d.ts +8 -1
  34. package/dist/file-lock.js +2 -0
  35. package/dist/help.js +8 -11
  36. package/dist/inbox.d.ts +35 -9
  37. package/dist/inbox.js +228 -144
  38. package/dist/index.d.ts +3 -4
  39. package/dist/index.js +1 -3
  40. package/dist/list.js +9 -4
  41. package/dist/mcp.js +12 -1
  42. package/dist/model.d.ts +39 -5
  43. package/dist/model.js +84 -0
  44. package/dist/notifications.d.ts +8 -6
  45. package/dist/notifications.js +56 -143
  46. package/dist/operation-presentation.js +3 -4
  47. package/dist/participant-identity.d.ts +0 -3
  48. package/dist/participant-identity.js +0 -31
  49. package/dist/paseo-delivery.d.ts +5 -6
  50. package/dist/paseo-delivery.js +13 -8
  51. package/dist/paseo.d.ts +1 -1
  52. package/dist/paseo.js +1 -1
  53. package/dist/plugins/opencode/delivery.d.ts +8 -3
  54. package/dist/plugins/opencode/delivery.js +187 -132
  55. package/dist/plugins/opencode/index.js +12 -38
  56. package/dist/ports.d.ts +112 -40
  57. package/dist/presentation-operations.d.ts +1 -1
  58. package/dist/presentation-operations.js +51 -35
  59. package/dist/presentation.js +8 -3
  60. package/dist/seats.d.ts +7 -0
  61. package/dist/seats.js +27 -0
  62. package/dist/session-lifecycle.d.ts +2 -2
  63. package/dist/session-lifecycle.js +10 -12
  64. package/dist/sqlite-square.d.ts +20 -9
  65. package/dist/sqlite-square.js +471 -339
  66. package/dist/square-api.d.ts +1 -0
  67. package/dist/square-api.js +3 -4
  68. package/dist/square-core.d.ts +3 -2
  69. package/dist/square-domain.d.ts +12 -5
  70. package/dist/square-domain.js +163 -7
  71. package/dist/square-facade.d.ts +14 -10
  72. package/dist/square-index.d.ts +24 -0
  73. package/dist/square-index.js +131 -0
  74. package/dist/square-legacy-framing.d.ts +9 -0
  75. package/dist/square-legacy-framing.js +56 -0
  76. package/dist/square-migration-host-ledger.d.ts +26 -0
  77. package/dist/square-migration-host-ledger.js +168 -0
  78. package/dist/square-migration.d.ts +5 -5
  79. package/dist/square-migration.js +373 -71
  80. package/dist/square-sqlite.d.ts +9 -9
  81. package/dist/square-sqlite.js +329 -79
  82. package/dist/square-stdio.d.ts +1 -1
  83. package/dist/square-stdio.js +12 -7
  84. package/dist/square-tools.js +29 -2
  85. package/dist/stdio-server.js +4 -2
  86. package/dist/stream.d.ts +3 -2
  87. package/dist/stream.js +9 -10
  88. package/dist/views.d.ts +9 -14
  89. package/dist/views.js +50 -70
  90. package/dist/wakes.d.ts +6 -5
  91. package/dist/wakes.js +20 -17
  92. package/guides/application-facade-delivery-evidence.md +1 -1
  93. package/guides/claude-native.md +9 -9
  94. package/guides/mcp.md +1 -1
  95. package/guides/migration.md +107 -67
  96. package/guides/row-storage-design.md +1 -1
  97. package/guides/square-api.md +61 -28
  98. package/package.json +1 -1
  99. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  100. package/plugins/claude/hooks/register.js +1 -1
  101. package/plugins/claude/skills/square/SKILL.md +1 -1
  102. package/plugins/claude/types.d.ts +1 -1
  103. package/plugins/codex/.codex-plugin/plugin.json +1 -1
  104. package/plugins/opencode/delivery.ts +170 -118
  105. package/plugins/opencode/index.ts +12 -30
  106. package/plugins/pi/square-pi.js +55 -17
  107. package/skills/square/SKILL.md +1 -1
  108. package/dist/cli/ledger-command.d.ts +0 -12
  109. package/dist/cli/ledger-command.js +0 -72
  110. package/dist/host-ledger-file-adapter.d.ts +0 -47
  111. package/dist/host-ledger-file-adapter.js +0 -384
  112. package/dist/host-ledger-migration.d.ts +0 -27
  113. package/dist/host-ledger-migration.js +0 -264
  114. package/dist/host-ledger-root.d.ts +0 -2
  115. package/dist/host-ledger-root.js +0 -9
  116. package/dist/host-ledger-sqlite.d.ts +0 -65
  117. package/dist/host-ledger-sqlite.js +0 -368
  118. package/dist/host-ledger.d.ts +0 -195
  119. package/dist/host-ledger.js +0 -1
  120. package/dist/ledger-maintenance.d.ts +0 -30
  121. package/dist/ledger-maintenance.js +0 -110
  122. package/dist/open-square.d.ts +0 -38
  123. package/dist/open-square.js +0 -81
  124. package/dist/participant-host.d.ts +0 -23
  125. package/dist/participant-host.js +0 -92
  126. package/dist/registry.d.ts +0 -55
  127. package/dist/registry.js +0 -123
  128. package/dist/routes.d.ts +0 -39
  129. package/dist/routes.js +0 -99
  130. package/dist/square-actions.d.ts +0 -56
  131. package/dist/square-actions.js +0 -353
  132. package/dist/square-projections.d.ts +0 -31
  133. package/dist/square-projections.js +0 -64
  134. package/dist/wake-attempts.d.ts +0 -10
  135. package/dist/wake-attempts.js +0 -39
  136. package/dist/wake-eligibility.d.ts +0 -53
  137. package/dist/wake-eligibility.js +0 -123
  138. package/dist/wake-evidence.d.ts +0 -33
  139. package/dist/wake-evidence.js +0 -32
  140. package/guides/host-ledger.md +0 -58
  141. package/guides/indexed-host-ledger-performance.md +0 -39
@@ -0,0 +1,168 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { pathToFileURL } from 'node:url';
6
+ import { canonicalPath } from './canonical-path.js';
7
+ import { inSqliteTransaction } from './sqlite-transaction.js';
8
+ import { nameKey, validateBody } from './model.js';
9
+ const LEDGER_FILENAME = 'host-ledger.sqlite';
10
+ const LEDGER_APPLICATION_ID = 0x5351484c;
11
+ const LEDGER_VERSION = 2;
12
+ const tableSchema = {
13
+ host_meta: 'CREATE TABLE host_meta (id INTEGER PRIMARY KEY CHECK(id=1), presence_revision INTEGER NOT NULL, evidence_revision INTEGER NOT NULL)',
14
+ host_presence: 'CREATE TABLE host_presence (seq INTEGER PRIMARY KEY AUTOINCREMENT, location_key TEXT NOT NULL, participant_key TEXT NOT NULL, session_key TEXT NOT NULL, channel_key TEXT NOT NULL, effective_at REAL NOT NULL, row_json TEXT NOT NULL)',
15
+ host_evidence: 'CREATE TABLE host_evidence (seq INTEGER PRIMARY KEY AUTOINCREMENT, location_key TEXT NOT NULL, participant_key TEXT NOT NULL, session_key TEXT NOT NULL, activity_key TEXT NOT NULL, kind TEXT NOT NULL, outcome TEXT NOT NULL, claim_token_key TEXT, effective_at REAL NOT NULL, row_json TEXT NOT NULL)',
16
+ host_native_tokens: "CREATE TABLE host_native_tokens (harness TEXT NOT NULL CHECK(harness='claude'), session_key TEXT NOT NULL, token_key TEXT NOT NULL, PRIMARY KEY(harness,session_key,token_key)) WITHOUT ROWID",
17
+ };
18
+ const indexes = {
19
+ host_presence_identity: ['host_presence', 'location_key', 'participant_key', 'seq'],
20
+ host_presence_session: ['host_presence', 'session_key', 'seq'],
21
+ host_presence_time: ['host_presence', 'effective_at'],
22
+ host_evidence_attention: ['host_evidence', 'location_key', 'participant_key', 'activity_key', 'kind', 'session_key', 'seq'],
23
+ host_evidence_kind_session: ['host_evidence', 'kind', 'session_key', 'seq'],
24
+ host_evidence_session: ['host_evidence', 'session_key', 'seq'],
25
+ host_evidence_token: ['host_evidence', 'location_key', 'participant_key', 'activity_key', 'session_key', 'claim_token_key', 'seq'],
26
+ host_evidence_outcome_time: ['host_evidence', 'outcome', 'effective_at'],
27
+ host_evidence_time: ['host_evidence', 'effective_at'],
28
+ host_evidence_native_token: ['host_evidence', 'session_key', 'claim_token_key', 'seq'],
29
+ };
30
+ const LEGACY_FILES = ['presence.ndjsonl', 'evidence.ndjsonl'];
31
+ function indexSql(name, fields) {
32
+ return `CREATE INDEX ${name} ON ${fields[0]} (${fields.slice(1).join(',')})`;
33
+ }
34
+ function normalizedSql(sql) {
35
+ return sql.replace(/\s+/g, '').replace(/;$/, '');
36
+ }
37
+ function recordKey(value) { return JSON.stringify(value); }
38
+ function validateLedger(database) {
39
+ const application = database.prepare('PRAGMA application_id').get().application_id;
40
+ const version = database.prepare('PRAGMA user_version').get().user_version;
41
+ if (application !== LEDGER_APPLICATION_ID || version !== LEDGER_VERSION)
42
+ throw invalid('unsupported format.');
43
+ if (database.prepare('PRAGMA journal_mode').get().journal_mode !== 'delete')
44
+ throw invalid('unsupported journal mode.');
45
+ const expected = new Map([
46
+ ...Object.entries(tableSchema),
47
+ ...Object.entries(indexes).map(([name, fields]) => [name, indexSql(name, fields)]),
48
+ ]);
49
+ const schema = database.prepare("SELECT name,sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%'").all();
50
+ if (schema.length !== expected.size || schema.some((row) => typeof row.name !== 'string' || typeof row.sql !== 'string'
51
+ || !expected.has(row.name) || normalizedSql(row.sql) !== normalizedSql(expected.get(row.name))))
52
+ throw invalid('schema or indexes are malformed.');
53
+ const meta = database.prepare('SELECT id,presence_revision,evidence_revision FROM host_meta').all();
54
+ if (meta.length !== 1 || meta[0].id !== 1 || ![meta[0].presence_revision, meta[0].evidence_revision].every((value) => Number.isSafeInteger(value) && value >= 0))
55
+ throw invalid('revision header is malformed.');
56
+ const integrity = database.prepare('PRAGMA integrity_check').all();
57
+ if (integrity.length !== 1 || integrity[0].integrity_check !== 'ok')
58
+ throw invalid('integrity check failed.');
59
+ // Token-only tombstones have no artifact coordinate. Never guess or discard replay protection.
60
+ if (database.prepare('SELECT 1 FROM host_native_tokens LIMIT 1').get() !== undefined)
61
+ throw invalid('native token tombstones cannot be mapped safely; preserve replay protection and resolve the ledger offline.');
62
+ }
63
+ function ledgerRoot(env) {
64
+ return path.resolve(env.SQUARE_HOST_LEDGER_ROOT
65
+ ?? (env.SQUARE_REGISTRY === undefined ? path.join(env.HOME ?? os.homedir(), '.square', 'host-ledger') : path.dirname(env.SQUARE_REGISTRY)));
66
+ }
67
+ function invalid(detail) {
68
+ return new Error(`Invalid legacy host ledger: ${detail}`);
69
+ }
70
+ function finite(value) {
71
+ return typeof value === 'number' && Number.isFinite(value);
72
+ }
73
+ function decodeEvidence(value) {
74
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
75
+ throw invalid('evidence record is not an object.');
76
+ const row = value;
77
+ if (row.v !== 1 || typeof row.location !== 'string' || typeof row.participant !== 'string' || typeof row.session !== 'string'
78
+ || typeof row.activity !== 'string' || !['wake', 'presentation', 'lifecycle'].includes(row.kind)
79
+ || typeof row.outcome !== 'string')
80
+ throw invalid('evidence record fields are malformed.');
81
+ if (row.at !== undefined && !finite(row.at))
82
+ throw invalid('evidence time is malformed.');
83
+ if (row.expiresAt !== undefined && !finite(row.expiresAt))
84
+ throw invalid('evidence expiry is malformed.');
85
+ if (row.attemptN !== undefined && (!Number.isSafeInteger(row.attemptN) || row.attemptN < 0))
86
+ throw invalid('evidence attempt is malformed.');
87
+ if (row.claimToken !== undefined && (typeof row.claimToken !== 'string' || row.claimToken.length === 0))
88
+ throw invalid('evidence claim token is malformed.');
89
+ return row;
90
+ }
91
+ function record(row) {
92
+ if (!Number.isSafeInteger(row.seq) || row.seq < 1 || typeof row.row_json !== 'string')
93
+ throw invalid('row framing is malformed.');
94
+ let value;
95
+ try {
96
+ value = JSON.parse(row.row_json);
97
+ }
98
+ catch {
99
+ throw invalid('record JSON is malformed.');
100
+ }
101
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
102
+ throw invalid('record is not an object.');
103
+ return value;
104
+ }
105
+ function projections(row, expected) {
106
+ if (Object.entries(expected).some(([key, value]) => row[key] !== value))
107
+ throw invalid('record projections are malformed.');
108
+ }
109
+ /** One frozen snapshot, latest owners only; no age, expiry, or ownership history inference. */
110
+ export async function readLegacyHostData(location, env = process.env, signal) {
111
+ if (signal?.aborted)
112
+ throw signal.reason;
113
+ const root = ledgerRoot(env);
114
+ const file = path.join(root, LEDGER_FILENAME);
115
+ try {
116
+ await fs.promises.stat(file);
117
+ }
118
+ catch (error) {
119
+ if (error.code !== 'ENOENT')
120
+ throw error;
121
+ for (const legacy of LEGACY_FILES) {
122
+ try {
123
+ await fs.promises.stat(path.join(root, legacy));
124
+ throw invalid('legacy line sources require separate host-ledger migration.');
125
+ }
126
+ catch (nested) {
127
+ if (nested.code !== 'ENOENT')
128
+ throw nested;
129
+ }
130
+ }
131
+ return { owners: [], evidence: [] };
132
+ }
133
+ const uri = pathToFileURL(file);
134
+ uri.searchParams.set('mode', 'ro');
135
+ const database = new DatabaseSync(uri.href);
136
+ try {
137
+ const canonical = await canonicalPath(location);
138
+ return await inSqliteTransaction(database, false, () => validateLedger(database), () => {
139
+ const owners = database.prepare(`SELECT * FROM (
140
+ SELECT *,row_number() OVER (PARTITION BY participant_key ORDER BY effective_at DESC,seq DESC) AS ordinal
141
+ FROM host_presence WHERE location_key=?) WHERE ordinal=1`).all(recordKey(canonical)).map(row => {
142
+ const value = record(row);
143
+ const at = value.at ?? value.updatedAt;
144
+ if (value.v !== 1 || value.location !== canonical || typeof value.participant !== 'string'
145
+ || !finite(at))
146
+ throw invalid('owner fields are malformed.');
147
+ const body = { channel: value.channel, session: value.session, ...(value.agent === undefined ? {} : { agent: value.agent }) };
148
+ validateBody(body);
149
+ projections(row, { location_key: recordKey(canonical), participant_key: recordKey(nameKey(value.participant)),
150
+ channel_key: recordKey(body.channel), session_key: recordKey(body.session), effective_at: at });
151
+ return { participant: value.participant, body };
152
+ });
153
+ const evidence = database.prepare("SELECT * FROM host_evidence WHERE location_key=? AND kind IN ('wake','presentation') ORDER BY seq").all(recordKey(canonical)).map(row => {
154
+ const value = decodeEvidence(record(row));
155
+ if (value.location !== canonical || !finite(value.at))
156
+ throw invalid('evidence fields are malformed.');
157
+ projections(row, { location_key: recordKey(canonical), participant_key: recordKey(nameKey(value.participant)), session_key: recordKey(value.session),
158
+ activity_key: recordKey(value.activity), kind: value.kind, outcome: value.outcome,
159
+ claim_token_key: value.claimToken === undefined ? null : recordKey(value.claimToken), effective_at: value.at });
160
+ return value;
161
+ });
162
+ return { owners, evidence };
163
+ }, signal);
164
+ }
165
+ finally {
166
+ database.close();
167
+ }
168
+ }
@@ -14,9 +14,9 @@ export interface MigrationOutcome {
14
14
  readonly counts?: MigrationCounts;
15
15
  }
16
16
  /**
17
- * Explicit in-place conversion of a version 1 snapshot or version 2 row
18
- * artifact. Each source is validated before and under the write lock; v1 is
19
- * imported through the normal current row initializer, while v2 rebuilds only
20
- * activities and its indexes before publishing the new format version.
17
+ * Explicit conversion of the supported legacy formats. Row-backed versions 2 and 3 are
18
+ * preflighted read-only, then receive the format-4 ownership/evidence rows in one transaction.
19
+ * Legacy delivery evidence is copied from HostLedger only when its owner/session mapping is
20
+ * unique; no source record is retired. Version 1 is not a supported source for this format transition.
21
21
  */
22
- export declare function migrateSquareFile(location: string, signal?: AbortSignal): Promise<MigrationOutcome>;
22
+ export declare function migrateSquareFile(location: string, signal?: AbortSignal, env?: NodeJS.ProcessEnv): Promise<MigrationOutcome>;