amalgm 0.1.245 → 0.1.246
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/README.md +12 -0
- package/lib/cli.js +146 -8
- package/lib/layout.js +89 -4
- package/lib/shared-realtime-tunnel.js +384 -43
- package/lib/supervisor.js +0 -3
- package/package.json +2 -2
- package/runtime/scripts/amalgm-mcp/adapters/contract.js +197 -0
- package/runtime/scripts/amalgm-mcp/adapters/filesystem.js +135 -0
- package/runtime/scripts/amalgm-mcp/adapters/git.js +84 -0
- package/runtime/scripts/amalgm-mcp/adapters/index.js +43 -0
- package/runtime/scripts/amalgm-mcp/adapters/reference.js +31 -0
- package/runtime/scripts/amalgm-mcp/adapters/truth.js +19 -0
- package/runtime/scripts/amalgm-mcp/browser/cookie-jar.js +20 -68
- package/runtime/scripts/amalgm-mcp/index.js +4 -0
- package/runtime/scripts/amalgm-mcp/lib/layout.js +89 -4
- package/runtime/scripts/amalgm-mcp/observer/README.md +259 -0
- package/runtime/scripts/amalgm-mcp/observer/apply.js +150 -0
- package/runtime/scripts/amalgm-mcp/observer/continuity.js +111 -0
- package/runtime/scripts/amalgm-mcp/observer/edges.js +111 -0
- package/runtime/scripts/amalgm-mcp/observer/index.js +1146 -0
- package/runtime/scripts/amalgm-mcp/observer/scan.js +387 -0
- package/runtime/scripts/amalgm-mcp/observer/store.js +262 -0
- package/runtime/scripts/amalgm-mcp/observer/verify.js +200 -0
- package/runtime/scripts/amalgm-mcp/observer/watch.js +62 -0
- package/runtime/scripts/amalgm-mcp/project-context/store.js +19 -87
- package/runtime/scripts/amalgm-mcp/registration/classify.js +33 -0
- package/runtime/scripts/amalgm-mcp/registration/entity-cloud.js +456 -0
- package/runtime/scripts/amalgm-mcp/registration/entity-content.js +345 -0
- package/runtime/scripts/amalgm-mcp/registration/index.js +752 -0
- package/runtime/scripts/amalgm-mcp/registration/refusal.js +42 -0
- package/runtime/scripts/amalgm-mcp/registration/repo-followers.js +127 -0
- package/runtime/scripts/amalgm-mcp/registration/repo-states.js +109 -0
- package/runtime/scripts/amalgm-mcp/registration/service.js +310 -0
- package/runtime/scripts/amalgm-mcp/registration/tree.js +178 -0
- package/runtime/scripts/amalgm-mcp/registry/evidence.js +826 -0
- package/runtime/scripts/amalgm-mcp/registry/index.js +666 -0
- package/runtime/scripts/amalgm-mcp/registry/store.js +290 -0
- package/runtime/scripts/amalgm-mcp/repocard/README.md +103 -0
- package/runtime/scripts/amalgm-mcp/repocard/apply.js +111 -0
- package/runtime/scripts/amalgm-mcp/repocard/capture-worker.js +94 -0
- package/runtime/scripts/amalgm-mcp/repocard/capture.js +149 -0
- package/runtime/scripts/amalgm-mcp/repocard/follow.js +310 -0
- package/runtime/scripts/amalgm-mcp/repocard/git.js +48 -0
- package/runtime/scripts/amalgm-mcp/repocard/index.js +48 -0
- package/runtime/scripts/amalgm-mcp/server/local-service-router.js +2 -0
- package/runtime/scripts/amalgm-mcp/server/routes/entities.js +287 -0
- package/runtime/scripts/amalgm-mcp/server/routes/state.js +0 -13
- package/runtime/scripts/amalgm-mcp/state/attachments.js +11 -45
- package/runtime/scripts/amalgm-mcp/state/db.js +46 -215
- package/runtime/scripts/amalgm-mcp/state/docs.js +301 -1101
- package/runtime/scripts/amalgm-mcp/state/mutation-contracts.js +0 -99
- package/runtime/scripts/amalgm-mcp/state/mutations.js +130 -507
- package/runtime/scripts/amalgm-mcp/state/promotions.js +1 -21
- package/runtime/scripts/amalgm-mcp/state/replicas.js +13 -134
- package/runtime/scripts/amalgm-mcp/state/shared-rest.js +3 -46
- package/runtime/scripts/amalgm-mcp/tests/adapters.test.js +379 -0
- package/runtime/scripts/amalgm-mcp/tests/browser-cookie-cloud.test.js +0 -193
- package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.life.test.js +449 -0
- package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.rig.js +107 -0
- package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.watch.test.js +213 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/adapter.js +72 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/assert.js +497 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/bind.js +91 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/graph.js +1031 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/ledger.js +234 -0
- package/runtime/scripts/amalgm-mcp/tests/entity-oracle/referee.js +118 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.oracle.test.js +1365 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.registry.test.js +967 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.rig.js +239 -0
- package/runtime/scripts/amalgm-mcp/tests/entity.storm.test.js +486 -0
- package/runtime/scripts/amalgm-mcp/tests/fake-watch.js +35 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.links.test.js +289 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.rig.js +103 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.roots.test.js +505 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.storm.test.js +389 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.territory.test.js +845 -0
- package/runtime/scripts/amalgm-mcp/tests/observer.test.js +657 -0
- package/runtime/scripts/amalgm-mcp/tests/project-context.test.js +17 -32
- package/runtime/scripts/amalgm-mcp/tests/registration.service.test.js +256 -0
- package/runtime/scripts/amalgm-mcp/tests/registration.test.js +931 -0
- package/runtime/scripts/amalgm-mcp/tests/repocard.storm.test.js +284 -0
- package/runtime/scripts/amalgm-mcp/tests/repocard.test.js +371 -0
- package/runtime/scripts/amalgm-mcp/tests/repofollow.storm.test.js +435 -0
- package/runtime/scripts/amalgm-mcp/tests/repofollow.test.js +675 -0
- package/runtime/scripts/amalgm-mcp/tests/shared-tunnel-rehydration.test.js +0 -84
- package/runtime/scripts/amalgm-mcp/tests/state-docs.test.js +13 -376
- package/runtime/scripts/amalgm-mcp/tests/state-mutations.test.js +0 -309
- package/runtime/scripts/amalgm-mcp/tests/state-shared-replica.test.js +30 -758
- package/runtime/scripts/amalgm-mcp/tests/workspace-cards-store.test.js +3 -72
- package/runtime/scripts/amalgm-mcp/tests/workspace-cards.test.js +1 -89
- package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint-reducer.test.js +24 -55
- package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +141 -424
- package/runtime/scripts/amalgm-mcp/tests/workspace-object-tunnel.test.js +3 -171
- package/runtime/scripts/amalgm-mcp/tests/workspace-objects.test.js +7 -220
- package/runtime/scripts/amalgm-mcp/tests/workspace-publication-invariants.test.js +236 -179
- package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +326 -2228
- package/runtime/scripts/amalgm-mcp/tests/workspace-tree-cloud.test.js +3 -5319
- package/runtime/scripts/amalgm-mcp/tests/workspace-tree-core.test.js +1 -191
- package/runtime/scripts/amalgm-mcp/tests/workspace-tree-store.test.js +17 -3140
- package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +740 -137
- package/runtime/scripts/amalgm-mcp/workspace/access-store.js +1 -5
- package/runtime/scripts/amalgm-mcp/workspace/card.js +11 -35
- package/runtime/scripts/amalgm-mcp/workspace/cards.js +14 -39
- package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +147 -587
- package/runtime/scripts/amalgm-mcp/workspace/git.js +34 -406
- package/runtime/scripts/amalgm-mcp/workspace/merge.js +181 -102
- package/runtime/scripts/amalgm-mcp/workspace/objects.js +56 -221
- package/runtime/scripts/amalgm-mcp/workspace/reducer.js +538 -1964
- package/runtime/scripts/amalgm-mcp/workspace/rest.js +28 -49
- package/runtime/scripts/amalgm-mcp/workspace/store.js +4 -77
- package/runtime/scripts/amalgm-mcp/workspace/transition.js +192 -1734
- package/runtime/scripts/amalgm-mcp/workspace/tree/inclusion.js +1 -7
- package/runtime/scripts/amalgm-mcp/workspace/tree/local-state.js +61 -73
- package/runtime/scripts/amalgm-mcp/workspace/tree/reducer.js +6 -51
- package/runtime/scripts/amalgm-mcp/workspace/tree/snapshot.js +8 -79
- package/runtime/scripts/amalgm-mcp/workspace/tree-cloud.js +146 -3461
- package/runtime/scripts/amalgm-mcp/workspace/tree-store.js +71 -899
- package/runtime/scripts/amalgm-mcp/workspace/wall.js +538 -370
- package/runtime/scripts/local-gateway.js +1 -0
- package/runtime/scripts/amalgm-mcp/state/doc-disk.js +0 -550
- package/runtime/scripts/amalgm-mcp/tests/code-project-stream.test.js +0 -399
- package/runtime/scripts/amalgm-mcp/tests/fixtures/code-project-stream-v2.json +0 -1
- package/runtime/scripts/amalgm-mcp/tests/workspace-durable.test.js +0 -24
- package/runtime/scripts/amalgm-mcp/tests/workspace-local-intent.test.js +0 -1999
- package/runtime/scripts/amalgm-mcp/tests/workspace-native-file-transaction.test.js +0 -364
- package/runtime/scripts/amalgm-mcp/tests/workspace-provenance.test.js +0 -185
- package/runtime/scripts/amalgm-mcp/tests/workspace-reducer-liveness.test.js +0 -26
- package/runtime/scripts/amalgm-mcp/tests/workspace-sync-stats.test.js +0 -119
- package/runtime/scripts/amalgm-mcp/tests/workspace-transition.test.js +0 -1446
- package/runtime/scripts/amalgm-mcp/workspace/content.js +0 -32
- package/runtime/scripts/amalgm-mcp/workspace/durable.js +0 -45
- package/runtime/scripts/amalgm-mcp/workspace/intent.js +0 -535
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/BUILD.md +0 -31
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/darwin-arm64/amalgm-file-transaction +0 -0
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/linux-x64/amalgm-file-transaction +0 -0
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/build.mjs +0 -72
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/client.js +0 -165
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.mod +0 -5
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.sum +0 -2
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/main.go +0 -2201
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/manifest.json +0 -19
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_darwin.go +0 -18
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_linux.go +0 -18
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_darwin.go +0 -33
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_linux.go +0 -47
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/verify.mjs +0 -43
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_darwin.go +0 -114
- package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_linux.go +0 -84
- package/runtime/scripts/amalgm-mcp/workspace/project-stream.js +0 -771
- package/runtime/scripts/amalgm-mcp/workspace/provenance.js +0 -240
- package/runtime/scripts/amalgm-mcp/workspace/sync-stats.js +0 -240
- package/runtime/scripts/amalgm-mcp/workspace/tree/floor.js +0 -100
- package/runtime/scripts/amalgm-mcp/workspace/tree/observation-holds.js +0 -127
- package/runtime/scripts/amalgm-mcp/workspace/tree/path-state.js +0 -12
- package/runtime/scripts/amalgm-mcp/workspace/tree/root-binding.js +0 -125
- package/runtime/scripts/amalgm-mcp/workspace/tree/symlinks.js +0 -76
- package/runtime/scripts/amalgm-mcp/workspace/tree-materialization.js +0 -3766
|
@@ -8,36 +8,12 @@
|
|
|
8
8
|
* is already backed by this WAL database.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const fs = require('fs');
|
|
12
11
|
const path = require('path');
|
|
13
12
|
const { ensureDir } = require('../lib/storage');
|
|
14
13
|
const { LOCAL_DB_FILE, STORAGE_DIR } = require('../config');
|
|
15
14
|
|
|
16
15
|
let db = null;
|
|
17
16
|
|
|
18
|
-
const SHARED_RESOURCE_ATTACHMENTS_TABLE_SQL = `
|
|
19
|
-
CREATE TABLE IF NOT EXISTS shared_resource_attachments (
|
|
20
|
-
attachment_id TEXT PRIMARY KEY,
|
|
21
|
-
resource_id TEXT NOT NULL UNIQUE,
|
|
22
|
-
local_path TEXT NOT NULL UNIQUE,
|
|
23
|
-
attachment_state TEXT NOT NULL DEFAULT 'pending'
|
|
24
|
-
CHECK (attachment_state IN ('pending', 'syncing', 'attached', 'rejected')),
|
|
25
|
-
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
|
|
26
|
-
next_attempt_at TEXT,
|
|
27
|
-
last_error TEXT,
|
|
28
|
-
-- First-attachment fence: local document mutations after this cursor
|
|
29
|
-
-- are overlay work that the returned cloud snapshot cannot contain.
|
|
30
|
-
journal_cursor INTEGER NOT NULL DEFAULT 0,
|
|
31
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
32
|
-
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
33
|
-
);
|
|
34
|
-
`;
|
|
35
|
-
|
|
36
|
-
const SHARED_RESOURCE_ATTACHMENTS_INDEX_SQL = `
|
|
37
|
-
CREATE INDEX IF NOT EXISTS shared_resource_attachments_outbox_idx
|
|
38
|
-
ON shared_resource_attachments (attachment_state, next_attempt_at, created_at);
|
|
39
|
-
`;
|
|
40
|
-
|
|
41
17
|
// Prepared statements cached per database handle: preparing is a parse+plan
|
|
42
18
|
// every time, and the realtime hot paths (event insert, replay reads, mirror
|
|
43
19
|
// upserts, doc persistence) run the same fixed SQL for the process lifetime.
|
|
@@ -134,12 +110,10 @@ function migrate(database = openLocalDb()) {
|
|
|
134
110
|
)),
|
|
135
111
|
local_revision INTEGER,
|
|
136
112
|
materialized_at TEXT,
|
|
137
|
-
official_projected_at TEXT,
|
|
138
113
|
event_seq INTEGER,
|
|
139
114
|
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
|
|
140
115
|
next_attempt_at TEXT,
|
|
141
116
|
last_error TEXT,
|
|
142
|
-
failure_code TEXT,
|
|
143
117
|
cloud_committed_at TEXT,
|
|
144
118
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
145
119
|
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
@@ -228,6 +202,22 @@ function migrate(database = openLocalDb()) {
|
|
|
228
202
|
CREATE INDEX IF NOT EXISTS shared_resource_promotions_outbox_idx
|
|
229
203
|
ON shared_resource_promotions (promotion_state, next_attempt_at, created_at);
|
|
230
204
|
|
|
205
|
+
CREATE TABLE IF NOT EXISTS shared_resource_attachments (
|
|
206
|
+
attachment_id TEXT PRIMARY KEY,
|
|
207
|
+
resource_id TEXT NOT NULL UNIQUE,
|
|
208
|
+
local_path TEXT NOT NULL UNIQUE,
|
|
209
|
+
attachment_state TEXT NOT NULL DEFAULT 'pending'
|
|
210
|
+
CHECK (attachment_state IN ('pending', 'syncing', 'attached', 'rejected')),
|
|
211
|
+
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
|
|
212
|
+
next_attempt_at TEXT,
|
|
213
|
+
last_error TEXT,
|
|
214
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
215
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
CREATE INDEX IF NOT EXISTS shared_resource_attachments_outbox_idx
|
|
219
|
+
ON shared_resource_attachments (attachment_state, next_attempt_at, created_at);
|
|
220
|
+
|
|
231
221
|
CREATE TABLE IF NOT EXISTS local_meta (
|
|
232
222
|
key TEXT PRIMARY KEY,
|
|
233
223
|
value TEXT,
|
|
@@ -365,6 +355,36 @@ function migrate(database = openLocalDb()) {
|
|
|
365
355
|
CREATE INDEX IF NOT EXISTS workflow_cell_runs_run_idx
|
|
366
356
|
ON workflow_cell_runs(run_id);
|
|
367
357
|
|
|
358
|
+
CREATE TABLE IF NOT EXISTS automation_deliveries (
|
|
359
|
+
id TEXT PRIMARY KEY,
|
|
360
|
+
kind TEXT NOT NULL CHECK (kind IN ('scheduled', 'event')),
|
|
361
|
+
trigger_id TEXT,
|
|
362
|
+
scheduled_for TEXT,
|
|
363
|
+
payload_json TEXT NOT NULL,
|
|
364
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
365
|
+
CHECK (status IN ('pending', 'running', 'completed', 'rejected')),
|
|
366
|
+
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
|
|
367
|
+
next_attempt_at TEXT,
|
|
368
|
+
lease_expires_at TEXT,
|
|
369
|
+
completed_trigger_ids_json TEXT NOT NULL DEFAULT '[]',
|
|
370
|
+
result_json TEXT,
|
|
371
|
+
last_error TEXT,
|
|
372
|
+
created_at TEXT NOT NULL,
|
|
373
|
+
updated_at TEXT NOT NULL,
|
|
374
|
+
completed_at TEXT,
|
|
375
|
+
FOREIGN KEY(trigger_id) REFERENCES automation_triggers(id) ON DELETE SET NULL
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
CREATE UNIQUE INDEX IF NOT EXISTS automation_deliveries_scheduled_slot_idx
|
|
379
|
+
ON automation_deliveries(trigger_id, scheduled_for)
|
|
380
|
+
WHERE kind = 'scheduled';
|
|
381
|
+
|
|
382
|
+
CREATE INDEX IF NOT EXISTS automation_deliveries_pending_idx
|
|
383
|
+
ON automation_deliveries(status, next_attempt_at, created_at);
|
|
384
|
+
|
|
385
|
+
CREATE INDEX IF NOT EXISTS automation_deliveries_trigger_idx
|
|
386
|
+
ON automation_deliveries(trigger_id, created_at DESC);
|
|
387
|
+
|
|
368
388
|
CREATE TABLE IF NOT EXISTS scheduled_tasks (
|
|
369
389
|
id TEXT PRIMARY KEY,
|
|
370
390
|
name TEXT NOT NULL,
|
|
@@ -567,7 +587,6 @@ function migrate(database = openLocalDb()) {
|
|
|
567
587
|
device_id TEXT,
|
|
568
588
|
inode TEXT,
|
|
569
589
|
trashed_at TEXT,
|
|
570
|
-
trash_component_id TEXT,
|
|
571
590
|
purged_at TEXT,
|
|
572
591
|
missing_at TEXT,
|
|
573
592
|
created_at TEXT NOT NULL,
|
|
@@ -588,23 +607,6 @@ function migrate(database = openLocalDb()) {
|
|
|
588
607
|
ON workspace_nodes(workspace_id, device_id, inode)
|
|
589
608
|
WHERE device_id IS NOT NULL AND inode IS NOT NULL AND purged_at IS NULL;
|
|
590
609
|
|
|
591
|
-
-- A safe filesystem ambiguity is still a sync failure if it is visible
|
|
592
|
-
-- only in one observer's return value. Keep every nonterminal tree wait
|
|
593
|
-
-- durable and addressable so restart and Local Live diagnostics see the
|
|
594
|
-
-- same held state until a later observation clears it.
|
|
595
|
-
CREATE TABLE IF NOT EXISTS workspace_tree_observation_holds (
|
|
596
|
-
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
|
597
|
-
hold_key TEXT NOT NULL,
|
|
598
|
-
owner_kind TEXT NOT NULL DEFAULT 'observer',
|
|
599
|
-
owner_id TEXT NOT NULL DEFAULT 'workspace-tree-observer',
|
|
600
|
-
reason TEXT NOT NULL,
|
|
601
|
-
node_id TEXT,
|
|
602
|
-
operation_kind TEXT,
|
|
603
|
-
paths_json TEXT NOT NULL,
|
|
604
|
-
first_observed_at TEXT NOT NULL,
|
|
605
|
-
PRIMARY KEY (workspace_id, hold_key)
|
|
606
|
-
);
|
|
607
|
-
|
|
608
610
|
CREATE TABLE IF NOT EXISTS workspace_access_state (
|
|
609
611
|
workspace_id TEXT PRIMARY KEY REFERENCES workspaces(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
|
610
612
|
authority_epoch INTEGER NOT NULL DEFAULT 1 CHECK (authority_epoch > 0),
|
|
@@ -722,40 +724,15 @@ function migrate(database = openLocalDb()) {
|
|
|
722
724
|
ON browser_login_sessions(expires_at);
|
|
723
725
|
|
|
724
726
|
`);
|
|
725
|
-
database.exec(SHARED_RESOURCE_ATTACHMENTS_TABLE_SQL);
|
|
726
|
-
database.exec(SHARED_RESOURCE_ATTACHMENTS_INDEX_SQL);
|
|
727
727
|
|
|
728
728
|
// event_log is already present on every installed machine. These nullable
|
|
729
729
|
// projection fields are additive and leave every legacy row/wire shape
|
|
730
730
|
// untouched while new SDK mutations carry their stable identity.
|
|
731
731
|
ensureColumn(database, 'event_log', 'mutation_id', 'TEXT');
|
|
732
732
|
ensureColumn(database, 'event_log', 'shared_resource_id', 'TEXT');
|
|
733
|
-
ensureColumn(database, 'mutation_journal', 'failure_code', 'TEXT');
|
|
734
|
-
ensureColumn(database, 'mutation_journal', 'official_projected_at', 'TEXT');
|
|
735
|
-
ensureColumn(database, 'workspace_nodes', 'trash_component_id', 'TEXT');
|
|
736
|
-
ensureColumn(
|
|
737
|
-
database,
|
|
738
|
-
'workspace_tree_observation_holds',
|
|
739
|
-
'owner_kind',
|
|
740
|
-
"TEXT NOT NULL DEFAULT 'observer'",
|
|
741
|
-
);
|
|
742
|
-
ensureColumn(
|
|
743
|
-
database,
|
|
744
|
-
'workspace_tree_observation_holds',
|
|
745
|
-
'owner_id',
|
|
746
|
-
"TEXT NOT NULL DEFAULT 'workspace-tree-observer'",
|
|
747
|
-
);
|
|
748
|
-
backfillWorkspaceTrashComponents(database);
|
|
749
733
|
// Wave-3 canaries created shared_resource_promotions before the fence
|
|
750
734
|
// cursor existed.
|
|
751
735
|
ensureColumn(database, 'shared_resource_promotions', 'journal_cursor', 'INTEGER NOT NULL DEFAULT 0');
|
|
752
|
-
ensureColumn(
|
|
753
|
-
database,
|
|
754
|
-
'shared_resource_attachments',
|
|
755
|
-
'journal_cursor',
|
|
756
|
-
'INTEGER NOT NULL DEFAULT 0',
|
|
757
|
-
);
|
|
758
|
-
enforceAttachmentJournalFence(database);
|
|
759
736
|
ensureColumn(
|
|
760
737
|
database,
|
|
761
738
|
'shared_resource_replicas',
|
|
@@ -772,108 +749,6 @@ function ensureColumn(database, tableName, columnName, declaration) {
|
|
|
772
749
|
database.exec(`ALTER TABLE ${tableName} ADD COLUMN ${columnName} ${declaration}`);
|
|
773
750
|
}
|
|
774
751
|
|
|
775
|
-
function backfillWorkspaceTrashComponents(database) {
|
|
776
|
-
database.prepare(`
|
|
777
|
-
UPDATE workspace_nodes
|
|
778
|
-
SET trash_component_id = NULL
|
|
779
|
-
WHERE purged_at IS NOT NULL AND trash_component_id IS NOT NULL
|
|
780
|
-
`).run();
|
|
781
|
-
const workspaces = database.prepare(
|
|
782
|
-
'SELECT id, path FROM workspaces WHERE path IS NOT NULL',
|
|
783
|
-
).all();
|
|
784
|
-
const update = database.prepare(`
|
|
785
|
-
UPDATE workspace_nodes SET trash_component_id = ? WHERE id = ?
|
|
786
|
-
`);
|
|
787
|
-
database.transaction(() => {
|
|
788
|
-
for (const workspace of workspaces) {
|
|
789
|
-
const allRows = database.prepare(`
|
|
790
|
-
SELECT id, parent_id, trashed_at
|
|
791
|
-
FROM workspace_nodes
|
|
792
|
-
WHERE workspace_id = ? AND trashed_at IS NOT NULL AND purged_at IS NULL
|
|
793
|
-
`).all(workspace.id);
|
|
794
|
-
const nodes = new Map(allRows.map((row) => [row.id, row]));
|
|
795
|
-
const unstamped = database.prepare(`
|
|
796
|
-
SELECT id FROM workspace_nodes
|
|
797
|
-
WHERE workspace_id = ? AND trashed_at IS NOT NULL
|
|
798
|
-
AND purged_at IS NULL AND trash_component_id IS NULL
|
|
799
|
-
`).all(workspace.id);
|
|
800
|
-
for (const { id } of unstamped) {
|
|
801
|
-
const row = nodes.get(id);
|
|
802
|
-
let current = row;
|
|
803
|
-
let physicalRoot = null;
|
|
804
|
-
while (current) {
|
|
805
|
-
const candidate = path.join(
|
|
806
|
-
path.dirname(path.resolve(workspace.path)),
|
|
807
|
-
`.amalgm-tree-trash-${workspace.id}`,
|
|
808
|
-
current.id,
|
|
809
|
-
);
|
|
810
|
-
if (fs.existsSync(candidate)) {
|
|
811
|
-
physicalRoot = current.id;
|
|
812
|
-
break;
|
|
813
|
-
}
|
|
814
|
-
current = nodes.get(current.parent_id) || null;
|
|
815
|
-
}
|
|
816
|
-
// Missing physical evidence is not permission to infer ownership
|
|
817
|
-
// from a timestamp. Recovery may temporarily hold the carrier in
|
|
818
|
-
// private staging; rerun this proof after recovery or remount.
|
|
819
|
-
if (physicalRoot) update.run(physicalRoot, row.id);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
})();
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
function enforceAttachmentJournalFence(database) {
|
|
826
|
-
const cursor = database.prepare('PRAGMA table_info(shared_resource_attachments)')
|
|
827
|
-
.all()
|
|
828
|
-
.find((column) => column.name === 'journal_cursor');
|
|
829
|
-
if (!cursor) {
|
|
830
|
-
throw new Error('shared attachment journal fence is missing');
|
|
831
|
-
}
|
|
832
|
-
database.prepare(`
|
|
833
|
-
UPDATE shared_resource_attachments
|
|
834
|
-
SET journal_cursor = 0
|
|
835
|
-
WHERE journal_cursor IS NULL
|
|
836
|
-
`).run();
|
|
837
|
-
if (cursor.notnull === 1 && String(cursor.dflt_value) === '0') return;
|
|
838
|
-
|
|
839
|
-
database.transaction(() => {
|
|
840
|
-
database.exec('DROP INDEX IF EXISTS shared_resource_attachments_outbox_idx');
|
|
841
|
-
database.exec(`
|
|
842
|
-
ALTER TABLE shared_resource_attachments
|
|
843
|
-
RENAME TO shared_resource_attachments_legacy_fence
|
|
844
|
-
`);
|
|
845
|
-
database.exec(SHARED_RESOURCE_ATTACHMENTS_TABLE_SQL);
|
|
846
|
-
database.exec(`
|
|
847
|
-
INSERT INTO shared_resource_attachments (
|
|
848
|
-
attachment_id,
|
|
849
|
-
resource_id,
|
|
850
|
-
local_path,
|
|
851
|
-
attachment_state,
|
|
852
|
-
attempt_count,
|
|
853
|
-
next_attempt_at,
|
|
854
|
-
last_error,
|
|
855
|
-
journal_cursor,
|
|
856
|
-
created_at,
|
|
857
|
-
updated_at
|
|
858
|
-
)
|
|
859
|
-
SELECT
|
|
860
|
-
attachment_id,
|
|
861
|
-
resource_id,
|
|
862
|
-
local_path,
|
|
863
|
-
attachment_state,
|
|
864
|
-
attempt_count,
|
|
865
|
-
next_attempt_at,
|
|
866
|
-
last_error,
|
|
867
|
-
COALESCE(journal_cursor, 0),
|
|
868
|
-
created_at,
|
|
869
|
-
updated_at
|
|
870
|
-
FROM shared_resource_attachments_legacy_fence
|
|
871
|
-
`);
|
|
872
|
-
database.exec('DROP TABLE shared_resource_attachments_legacy_fence');
|
|
873
|
-
database.exec(SHARED_RESOURCE_ATTACHMENTS_INDEX_SQL);
|
|
874
|
-
})();
|
|
875
|
-
}
|
|
876
|
-
|
|
877
752
|
// repo-card identity moved from the path to minted replica ids
|
|
878
753
|
// (repo-card@2). Cards are derived observations, so the v1 table is
|
|
879
754
|
// dropped rather than migrated — the next refresh rebuilds every card
|
|
@@ -919,47 +794,7 @@ function ensureDocStatesSchema(database = openLocalDb()) {
|
|
|
919
794
|
CREATE UNIQUE INDEX IF NOT EXISTS doc_states_node_id_idx
|
|
920
795
|
ON doc_states(node_id)
|
|
921
796
|
WHERE node_id IS NOT NULL;
|
|
922
|
-
|
|
923
|
-
CREATE TABLE IF NOT EXISTS doc_disk_materializations (
|
|
924
|
-
channel_id TEXT NOT NULL,
|
|
925
|
-
mutation_id TEXT NOT NULL,
|
|
926
|
-
local_resource TEXT NOT NULL,
|
|
927
|
-
root TEXT NOT NULL,
|
|
928
|
-
root_dev TEXT NOT NULL,
|
|
929
|
-
root_ino TEXT NOT NULL,
|
|
930
|
-
relative_path TEXT NOT NULL,
|
|
931
|
-
transaction_id TEXT NOT NULL,
|
|
932
|
-
operation_id TEXT NOT NULL,
|
|
933
|
-
expected_json TEXT,
|
|
934
|
-
observed_text TEXT,
|
|
935
|
-
mutation_source TEXT,
|
|
936
|
-
target_json TEXT,
|
|
937
|
-
target_content BLOB,
|
|
938
|
-
plan_kind TEXT NOT NULL DEFAULT 'mutation'
|
|
939
|
-
CHECK (plan_kind IN ('mutation', 'snapshot')),
|
|
940
|
-
snapshot_payload_json TEXT,
|
|
941
|
-
snapshot_event_seq INTEGER,
|
|
942
|
-
materialization_state TEXT NOT NULL DEFAULT 'based'
|
|
943
|
-
CHECK (materialization_state IN ('based', 'prepared', 'crossed', 'superseded')),
|
|
944
|
-
successor_channel_id TEXT,
|
|
945
|
-
successor_mutation_id TEXT,
|
|
946
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
947
|
-
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
948
|
-
PRIMARY KEY (channel_id, mutation_id)
|
|
949
|
-
);
|
|
950
|
-
|
|
951
|
-
CREATE INDEX IF NOT EXISTS doc_disk_materializations_resource_idx
|
|
952
|
-
ON doc_disk_materializations(local_resource, created_at);
|
|
953
797
|
`);
|
|
954
|
-
ensureColumn(
|
|
955
|
-
database,
|
|
956
|
-
'doc_disk_materializations',
|
|
957
|
-
'plan_kind',
|
|
958
|
-
"TEXT NOT NULL DEFAULT 'mutation' CHECK (plan_kind IN ('mutation', 'snapshot'))",
|
|
959
|
-
);
|
|
960
|
-
ensureColumn(database, 'doc_disk_materializations', 'snapshot_payload_json', 'TEXT');
|
|
961
|
-
ensureColumn(database, 'doc_disk_materializations', 'snapshot_event_seq', 'INTEGER');
|
|
962
|
-
ensureColumn(database, 'doc_disk_materializations', 'mutation_source', 'TEXT');
|
|
963
798
|
}
|
|
964
799
|
|
|
965
800
|
// App-registered resources (state/app-resources.js): the engine-side mirror
|
|
@@ -990,13 +825,9 @@ function closeLocalDb() {
|
|
|
990
825
|
}
|
|
991
826
|
|
|
992
827
|
module.exports = {
|
|
993
|
-
backfillWorkspaceTrashComponents,
|
|
994
828
|
cachedStatement,
|
|
995
829
|
closeLocalDb,
|
|
996
830
|
ensureAppResourcesSchema,
|
|
997
831
|
ensureDocStatesSchema,
|
|
998
832
|
openLocalDb,
|
|
999
|
-
_private: {
|
|
1000
|
-
migrate,
|
|
1001
|
-
},
|
|
1002
833
|
};
|