pushwork 1.1.3 → 2.0.0-a.sub.0
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/CLAUDE.md +9 -5
- package/dist/cli/commands.d.ts +71 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +794 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli.js +48 -55
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +5 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +262 -263
- package/dist/commands.js.map +1 -1
- package/dist/config/index.d.ts +71 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +314 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/change-detection.d.ts +2 -2
- package/dist/core/change-detection.d.ts.map +1 -1
- package/dist/core/change-detection.js +82 -109
- package/dist/core/change-detection.js.map +1 -1
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +14 -57
- package/dist/core/config.js.map +1 -1
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -21
- package/dist/core/index.js.map +1 -1
- package/dist/core/move-detection.d.ts +2 -2
- package/dist/core/move-detection.d.ts.map +1 -1
- package/dist/core/move-detection.js +9 -13
- package/dist/core/move-detection.js.map +1 -1
- package/dist/core/snapshot.d.ts +1 -1
- package/dist/core/snapshot.d.ts.map +1 -1
- package/dist/core/snapshot.js +9 -46
- package/dist/core/snapshot.js.map +1 -1
- package/dist/core/sync-engine.d.ts +1 -1
- package/dist/core/sync-engine.d.ts.map +1 -1
- package/dist/core/sync-engine.js +126 -151
- package/dist/core/sync-engine.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -20
- package/dist/index.js.map +1 -1
- package/dist/types/config.d.ts +7 -6
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +1 -5
- package/dist/types/config.js.map +1 -1
- package/dist/types/documents.js +4 -7
- package/dist/types/documents.js.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -19
- package/dist/types/index.js.map +1 -1
- package/dist/types/snapshot.js +1 -2
- package/dist/utils/content-similarity.d.ts +53 -0
- package/dist/utils/content-similarity.d.ts.map +1 -0
- package/dist/utils/content-similarity.js +155 -0
- package/dist/utils/content-similarity.js.map +1 -0
- package/dist/utils/content.js +4 -8
- package/dist/utils/content.js.map +1 -1
- package/dist/utils/directory.js +5 -9
- package/dist/utils/directory.js.map +1 -1
- package/dist/utils/fs.d.ts +1 -1
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +34 -84
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/index.d.ts +4 -4
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -20
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/mime-types.js +5 -43
- package/dist/utils/mime-types.js.map +1 -1
- package/dist/utils/network-sync.d.ts +13 -8
- package/dist/utils/network-sync.d.ts.map +1 -1
- package/dist/utils/network-sync.js +65 -137
- package/dist/utils/network-sync.js.map +1 -1
- package/dist/utils/node-polyfills.d.ts +9 -0
- package/dist/utils/node-polyfills.d.ts.map +1 -0
- package/dist/utils/node-polyfills.js +9 -0
- package/dist/utils/node-polyfills.js.map +1 -0
- package/dist/utils/output.js +32 -39
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/repo-factory.d.ts +8 -2
- package/dist/utils/repo-factory.d.ts.map +1 -1
- package/dist/utils/repo-factory.js +38 -47
- package/dist/utils/repo-factory.js.map +1 -1
- package/dist/utils/string-similarity.js +1 -5
- package/dist/utils/string-similarity.js.map +1 -1
- package/dist/utils/text-diff.js +5 -43
- package/dist/utils/text-diff.js.map +1 -1
- package/dist/utils/trace.js +6 -11
- package/dist/utils/trace.js.map +1 -1
- package/package.json +7 -5
- package/src/cli.ts +25 -34
- package/src/commands.ts +75 -11
- package/src/core/change-detection.ts +25 -10
- package/src/core/config.ts +2 -12
- package/src/core/index.ts +5 -5
- package/src/core/move-detection.ts +4 -4
- package/src/core/snapshot.ts +3 -3
- package/src/core/sync-engine.ts +24 -17
- package/src/index.ts +4 -4
- package/src/types/config.ts +8 -8
- package/src/types/index.ts +3 -3
- package/src/utils/directory.ts +1 -1
- package/src/utils/fs.ts +6 -4
- package/src/utils/index.ts +4 -4
- package/src/utils/network-sync.ts +62 -115
- package/src/utils/node-polyfills.ts +8 -0
- package/src/utils/repo-factory.ts +55 -10
- package/src/utils/trace.ts +1 -1
- package/tsconfig.json +2 -1
package/CLAUDE.md
CHANGED
|
@@ -103,20 +103,24 @@ Stored in `.pushwork/config.json` (local) and `~/.pushwork/config.json` (global)
|
|
|
103
103
|
|
|
104
104
|
Key fields:
|
|
105
105
|
- `sync_enabled: boolean` - Whether to do network sync
|
|
106
|
-
- `sync_server: string` - WebSocket relay URL (default: `wss://
|
|
107
|
-
- `sync_server_storage_id: StorageId` - Server identity for sync verification
|
|
106
|
+
- `sync_server: string` - WebSocket relay URL (default: `wss://subduction.sync.inkandswitch.com`)
|
|
108
107
|
- `exclude_patterns: string[]` - Gitignore-style patterns (default: `.git`, `node_modules`, `*.tmp`, `.pushwork`, `.DS_Store`)
|
|
109
108
|
- `sync.move_detection_threshold: number` - Similarity threshold for move detection (0-1, default 0.7)
|
|
110
109
|
|
|
111
|
-
## Network sync details
|
|
110
|
+
## Network sync details (Subduction)
|
|
112
111
|
|
|
113
|
-
|
|
112
|
+
Pushwork uses Subduction for network sync. Subduction replaces the old `BrowserWebSocketClientAdapter` with a Subduction transport layer that handles sync automatically.
|
|
113
|
+
|
|
114
|
+
- **Repo setup** (`src/utils/repo-factory.ts`): Creates a `WebCryptoSigner`, wraps `NodeFSStorageAdapter` in `SubductionStorageBridge`, hydrates `Subduction`, and calls `connectDiscover()` to the sync server. The `Repo` receives `{ subduction, storage }` instead of `{ storage, network }`.
|
|
115
|
+
- **Sync verification**: Uses head-stability polling instead of `StorageId`-based `getSyncInfo()`. Both `waitForSync()` and `waitForBidirectionalSync()` poll document heads until they stabilize.
|
|
116
|
+
- Uses `waitForSync()` to verify documents reach the server by polling head stability
|
|
114
117
|
- Uses `waitForBidirectionalSync()` to poll until document heads stabilize (no more incoming changes)
|
|
115
118
|
- Accepts optional `handles` param to check only specific handles instead of full tree traversal (used post-push in `sync()`)
|
|
116
119
|
- Timeout scales dynamically: `max(timeoutMs, 5000 + docCount * 50)` so large trees don't prematurely time out
|
|
117
120
|
- Tree traversal (`collectHeadsRecursive`) fetches siblings concurrently via `Promise.all`
|
|
118
121
|
- Documents sync level-by-level, deepest first, so children are on the server before their parents
|
|
119
122
|
- `handlesByPath` map tracks which documents changed and need syncing
|
|
123
|
+
- Default sync server: `wss://subduction.sync.inkandswitch.com`
|
|
120
124
|
|
|
121
125
|
## Leaf-first ordering
|
|
122
126
|
|
|
@@ -132,6 +136,6 @@ Used throughout sync-engine: if heads are available, calls `handle.changeAt(head
|
|
|
132
136
|
- **Avoid diffing artifact files.** `diffChars()` is O(n*m) and pointless for artifact directories since they use RawString (immutable snapshots). Artifact files should always be replaced with a fresh document rather than diffed+spliced. This applies to `updateRemoteFile()`, `applyMoveToRemote()`, and change detection. `ChangeDetector` skips `getContentAtHead()` and `getCurrentRemoteContent()` for artifact paths — it uses a SHA-256 `contentHash` stored in the snapshot to detect local changes, and checks heads to detect remote changes. If neither changed, the artifact is skipped entirely. The `contentHash` field on `SnapshotFileEntry` is optional and only populated for artifact files.
|
|
133
137
|
- **Sync timeout recovery.** `waitForSync()` returns `{ failed: DocHandle[] }` instead of throwing. When documents fail to sync (timeout or unavailable), `recreateFailedDocuments()` creates new Automerge docs with the same content, updates snapshot entries and parent directory references, then retries once. If documents still fail after recreation, it's reported as an error (not a warning) so the sync shows as "PARTIAL" rather than "SYNCED".
|
|
134
138
|
- **Document availability during clone.** `repo.find()` rejects with "Document X is unavailable" if the sync server doesn't have the document yet. `DocHandle.doc()` is synchronous and throws if the handle isn't ready. For clone scenarios, `sync()` retries `repo.find()` for the root document with exponential backoff (up to 6 attempts). `ChangeDetector.findDocument()` wraps `repo.find()` + `doc()` with retry logic for all document fetches during change detection.
|
|
135
|
-
- **Server load.** `
|
|
139
|
+
- **Server load.** `waitForSync` processes documents in batches of 10 (`SYNC_BATCH_SIZE`) to avoid flooding the server with concurrent sync messages. Without batching, syncing 100+ documents simultaneously can overwhelm the sync server.
|
|
136
140
|
- **`waitForBidirectionalSync` on large trees.** Full tree traversal (`getAllDocumentHeads`) is expensive because it `repo.find()`s every document. For post-push stabilization, pass the `handles` option to only check documents that actually changed. The initial pre-pull call still needs the full scan to discover remote changes. The dynamic timeout adds the first scan's duration on top of the base timeout, since the first scan is just establishing baseline — its duration shouldn't count against stability-wait time.
|
|
137
141
|
- **Versioned URLs and `repo.find()`.** `repo.find(versionedUrl)` returns a view handle whose `.heads()` returns the VERSION heads, not the current document heads. Always use `getPlainUrl()` when you need the current/mutable state. The snapshot head update loop at the end of `sync()` must use `getPlainUrl(snapshotEntry.url)` — without this, artifact directories (which store versioned URLs) get stale heads written to the snapshot, causing `changeAt()` to fork from the wrong point on the next sync. This was the root cause of the artifact deletion resurrection bug: `batchUpdateDirectory` would `changeAt` from an empty directory state where the file entry didn't exist yet, so the splice found nothing to delete.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Repo } from "@automerge/automerge-repo";
|
|
2
|
+
import { CloneOptions, SyncOptions, DiffOptions, LogOptions, CheckoutOptions, DirectoryConfig } from "../types";
|
|
3
|
+
import { SyncEngine } from "../core";
|
|
4
|
+
/**
|
|
5
|
+
* Shared context that commands can use
|
|
6
|
+
*/
|
|
7
|
+
export interface CommandContext {
|
|
8
|
+
repo: Repo;
|
|
9
|
+
syncEngine: SyncEngine;
|
|
10
|
+
config: DirectoryConfig;
|
|
11
|
+
workingDir: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Shared pre-action that ensures repository and sync engine are properly initialized
|
|
15
|
+
* This function always works, with or without network connectivity
|
|
16
|
+
*/
|
|
17
|
+
export declare function setupCommandContext(workingDir?: string, customSyncServer?: string, customStorageId?: string, enableNetwork?: boolean): Promise<CommandContext>;
|
|
18
|
+
/**
|
|
19
|
+
* Safely shutdown a repository with proper error handling
|
|
20
|
+
*/
|
|
21
|
+
export declare function safeRepoShutdown(repo: Repo, context?: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Common progress message helpers
|
|
24
|
+
*/
|
|
25
|
+
export declare const ProgressMessages: {
|
|
26
|
+
directoryFound: () => void;
|
|
27
|
+
configLoaded: () => void;
|
|
28
|
+
repoConnected: () => void;
|
|
29
|
+
syncServer: (server: string) => void;
|
|
30
|
+
storageId: (id: string) => void;
|
|
31
|
+
rootUrl: (url: string) => void;
|
|
32
|
+
changesWritten: () => void;
|
|
33
|
+
syncCompleted: (duration: number) => void;
|
|
34
|
+
directoryStructureCreated: () => void;
|
|
35
|
+
configSaved: () => void;
|
|
36
|
+
repoCreated: () => void;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Initialize sync in a directory
|
|
40
|
+
*/
|
|
41
|
+
export declare function init(targetPath: string, syncServer?: string, syncServerStorageId?: string): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Run bidirectional sync
|
|
44
|
+
*/
|
|
45
|
+
export declare function sync(options: SyncOptions): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Show differences between local and remote
|
|
48
|
+
*/
|
|
49
|
+
export declare function diff(targetPath: string | undefined, options: DiffOptions): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Show sync status
|
|
52
|
+
*/
|
|
53
|
+
export declare function status(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Show sync history
|
|
56
|
+
*/
|
|
57
|
+
export declare function log(targetPath: string | undefined, options: LogOptions): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Checkout/restore from previous sync
|
|
60
|
+
*/
|
|
61
|
+
export declare function checkout(syncId: string, targetPath: string | undefined, options: CheckoutOptions): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Clone an existing synced directory from an AutomergeUrl
|
|
64
|
+
*/
|
|
65
|
+
export declare function clone(rootUrl: string, targetPath: string, options: CloneOptions): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Get the root URL for the current pushwork repository
|
|
68
|
+
*/
|
|
69
|
+
export declare function url(targetPath?: string): Promise<void>;
|
|
70
|
+
export declare function commit(targetPath: string, dryRun?: boolean): Promise<void>;
|
|
71
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAA2B,MAAM,2BAA2B,CAAC;AAI1E,OAAO,EAEL,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,eAAe,EACf,eAAe,EAEhB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAMrC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,GAAE,MAAsB,EAClC,gBAAgB,CAAC,EAAE,MAAM,EACzB,eAAe,CAAC,EAAE,MAAM,EACxB,aAAa,GAAE,OAAc,GAC5B,OAAO,CAAC,cAAc,CAAC,CAqCzB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;yBAON,MAAM;oBAEX,MAAM;mBACP,MAAM;;8BAKK,MAAM;;;;CAOjC,CAAC;AA+DF;;GAEG;AACH,wBAAsB,IAAI,CACxB,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE,MAAM,GAC3B,OAAO,CAAC,IAAI,CAAC,CA6Hf;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgM9D;AAED;;GAEG;AACH,wBAAsB,IAAI,CACxB,UAAU,oBAAM,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA6Df;AAED;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CA6H5C;AAED;;GAEG;AACH,wBAAsB,GAAG,CACvB,UAAU,oBAAM,EAChB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,UAAU,oBAAM,EAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;GAEG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CA6Hf;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,UAAU,SAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCzD;AAED,wBAAsB,MAAM,CAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,IAAI,CAAC,CAgEf"}
|