@vrtmrz/livesync-commonlib 0.1.0-rc.11 → 0.1.0-rc.12
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.
|
@@ -188,7 +188,8 @@ class ServiceFileHandlerBase extends ServiceModuleBase {
|
|
|
188
188
|
await this.conflict.queueCheckFor(file.path);
|
|
189
189
|
return true;
|
|
190
190
|
}
|
|
191
|
-
const
|
|
191
|
+
const currentEntry = entry || await this.db.fetchEntryMeta(file, void 0, true);
|
|
192
|
+
const currentRevision = currentEntry && currentEntry._rev;
|
|
192
193
|
if (!currentRevision) {
|
|
193
194
|
this._log(
|
|
194
195
|
`Could not preserve the unknown conflict branch for ${file.path}; no current revision is available`,
|
|
@@ -18,6 +18,12 @@ A1
|
|
|
18
18
|
|
|
19
19
|
Resolving a conflict writes the selected or merged result on one branch and deletes every losing live leaf which the resolver has observed. Deleted leaves remain part of the tree until compaction removes their bodies. A stale client can therefore receive the resolved branch and the tombstone for a branch whose old content is still present in its storage.
|
|
20
20
|
|
|
21
|
+
## Chunk reachability during conflicts
|
|
22
|
+
|
|
23
|
+
A host which collects unreferenced chunks must include the current winner, every other live conflict leaf, their available divergent revisions, and their nearest available shared ancestor in its reachability scan. This preserves the content and merge base required to review an unresolved conflict. Chunk identifiers are shared across documents, so one reachability set must cover the whole database.
|
|
24
|
+
|
|
25
|
+
After the conflict is resolved, the deleted losing branch and no-longer-needed merge ancestry stop protecting their unique chunks. An ordinary superseded linear revision also does not protect its former chunks. A host must keep garbage collection separate from repair because collection cannot reconstruct content which is already unavailable.
|
|
26
|
+
|
|
21
27
|
## Safety invariants
|
|
22
28
|
|
|
23
29
|
Commonlib follows these rules:
|
|
@@ -85,6 +91,8 @@ With a proven displayed revision:
|
|
|
85
91
|
|
|
86
92
|
When edit provenance cannot be reconstructed, the new bytes are preserved as another manual-resolution branch instead of being attached silently to the deterministic winner. A deletion has no remaining file body from which to reconstruct provenance, so an unproven deletion preserves every live branch and requests conflict review. A cross-path rename with an unproven source keeps the newly stored target and preserves every source branch for review.
|
|
87
93
|
|
|
94
|
+
If chunks needed to reconstruct the winning body are missing, the document metadata and revision tree may still identify the exact winning revision and its parent. In that case, an edited storage file is preserved as a sibling branch from the shared parent without treating the unavailable body as trusted content. A generation-one revision has no parent from which a sibling can be created. If the parent or revision metadata is unavailable, Commonlib refuses the write and requests conflict review rather than inventing a base revision. A host may offer a separately confirmed exact-revision discard: logical deletion needs the revision metadata, not its chunks, and a confirmed replacement can then be stored. This is a recovery decision and must not be performed automatically.
|
|
95
|
+
|
|
88
96
|
These fallbacks favour recoverability. They may temporarily leave a duplicate target or a still-visible source conflict, but they do not discard a branch whose relationship to the user's operation cannot be proved.
|
|
89
97
|
|
|
90
98
|
## Worked revision-tree scenarios
|
|
@@ -158,4 +166,4 @@ Do not:
|
|
|
158
166
|
|
|
159
167
|
## Verification ownership
|
|
160
168
|
|
|
161
|
-
Commonlib unit tests build real in-memory PouchDB trees and inject provenance fakes at the file-handler boundary. They cover unequal branch lengths, nearest shared ancestry, deterministic selection from multiple live leaves, reconstruction of a later manual pair after an earlier sensible merge, content retained below a deleted losing leaf, recorded and reconstructed branch identity, ambiguous content, conflict-time editing, logical deletion, case-only rename, cross-path rename, and safe unproven fallbacks. A maintained host should additionally verify its composition: persistent device-local provenance, real file events, replication of the resulting revision trees, and dialogue policy.
|
|
169
|
+
Commonlib unit tests build real in-memory PouchDB trees and inject provenance fakes at the file-handler boundary. They cover unequal branch lengths, nearest shared ancestry, deterministic selection from multiple live leaves, reconstruction of a later manual pair after an earlier sensible merge, content retained below a deleted losing leaf, recorded and reconstructed branch identity, ambiguous content, conflict-time editing, missing-body preservation from available parent metadata, refusal to invent a parent for a generation-one revision, exact logical deletion and replacement of an unreadable generation-one live leaf, case-only rename, cross-path rename, and safe unproven fallbacks. A maintained host should additionally verify its composition: persistent device-local provenance, real file events, replication of the resulting revision trees, and dialogue policy.
|
package/docs/development.md
CHANGED
|
@@ -57,7 +57,7 @@ The settings lifecycle has an additional focused unit table in `src/common/model
|
|
|
57
57
|
|
|
58
58
|
The multiple-remote profile contract has focused unit coverage in `src/serviceFeatures/remoteConfig.unit.spec.ts`. Extend it whenever profile identity, generated display names, activation, P2P selection, URI serialisation, or legacy migration changes. New hosts should import the reviewed primitives through `/remote-configurations`; `compat/serviceFeatures/remoteConfig` remains the wider migration surface used by existing clients.
|
|
59
59
|
|
|
60
|
-
The revision-tree safety rules are documented in [Conflict resolution and file provenance](conflict-resolution.md). `ConflictManager.unit.spec.ts` owns common-ancestor and conservative merge behaviour, deterministic pair selection for multiple live leaves, and reconstruction from the committed tree between stages. `ServiceDatabaseFileAccessBase.unit.spec.ts` owns all-branch content discovery and exact-revision logical deletion. `ServiceFileHandlerBase.unit.spec.ts` owns the injected provenance policy for edit, deletion, and rename operations. Extend the relevant sides when changing conflict resolution, compaction handling, provenance, or database-to-storage overwrite protection.
|
|
60
|
+
The revision-tree safety rules are documented in [Conflict resolution and file provenance](conflict-resolution.md). `ConflictManager.unit.spec.ts` owns common-ancestor and conservative merge behaviour, deterministic pair selection for multiple live leaves, and reconstruction from the committed tree between stages. `ServiceDatabaseFileAccessBase.unit.spec.ts` owns all-branch content discovery and exact-revision logical deletion. `ServiceFileHandlerBase.unit.spec.ts` owns the injected provenance policy for edit, deletion, and rename operations. `LiveSyncLocalDB.unit.spec.ts` owns chunk reachability across current winners, shared chunks, live conflicts, available merge ancestry, conflict resolution, and PouchDB replication of collection and recreation. Extend the relevant sides when changing conflict resolution, compaction handling, provenance, chunk collection, or database-to-storage overwrite protection.
|
|
61
61
|
|
|
62
62
|
`openSimpleStore()` may create an inert namespace handle during composition, before the backing key-value database has opened. Maintained hosts must complete their sequential settings lifecycle before scans, watchers, or replication invoke the handle. Operations fail on a lifecycle violation rather than waiting for readiness; do not introduce an implicit wait which can hang after failed initialisation or become self-referential from an initialisation handler. Treat database reset as a transient unavailable boundary and reconstruct derived local state after reopening.
|
|
63
63
|
|
package/docs/proven-in-use.md
CHANGED
|
@@ -12,7 +12,9 @@ The plug-in extends the neutral `ServiceContext` with Obsidian-owned capabilitie
|
|
|
12
12
|
|
|
13
13
|
The consumer contract in `test/contracts/serviceContext.ts` checks shared result semantics and exact context identity across the composed services. The real-Obsidian suite documented in `test/e2e-obsidian/README.md` then covers plug-in loading, representative Svelte dialogue mounts, Vault reflection, CouchDB and Object Storage synchronisation, a two-device P2P Setup URI round-trip, two-Vault behaviour, and other Obsidian-owned boundaries.
|
|
14
14
|
|
|
15
|
-
Commonlib's real-PouchDB and injected-boundary unit tests prove that conservative merge uses the nearest revision actually shared by both conflict leaves, multiple remaining leaves are selected in a deterministic order, each completed pair is reconstructed from the committed tree, storage content from a deleted losing branch remains recognisable after resolution, and conflict-time operations retain the exact displayed branch or preserve every branch when that identity cannot be proved. Self-hosted LiveSync supplies the host composition and persistent device-local provenance. Its optional two-Vault scopes cover post-resolution propagation and edit, logical deletion, case-only rename, and cross-path rename while conflicts remain active. The conflict-operation scope passes in real Obsidian against the exact locally packed Commonlib artefact, including replicated parent revisions and preservation of the other live branches.
|
|
15
|
+
Commonlib's real-PouchDB and injected-boundary unit tests prove that conservative merge uses the nearest revision actually shared by both conflict leaves, multiple remaining leaves are selected in a deterministic order, each completed pair is reconstructed from the committed tree, storage content from a deleted losing branch remains recognisable after resolution, and conflict-time operations retain the exact displayed branch or preserve every branch when that identity cannot be proved. They also verify that a local edit remains a readable sibling branch when the winning body is unavailable but its exact revision and parent metadata remain, that a generation-one revision without a parent is left unresolved, and that a separately confirmed exact deletion of that unreadable live leaf permits a replacement to be stored without reading the missing chunk. Self-hosted LiveSync supplies the host composition and persistent device-local provenance. Its optional two-Vault scopes cover post-resolution propagation and edit, logical deletion, case-only rename, and cross-path rename while conflicts remain active. The conflict-operation scope passes in real Obsidian against the exact locally packed Commonlib artefact, including replicated parent revisions and preservation of the other live branches.
|
|
16
|
+
|
|
17
|
+
Commonlib's chunk-reachability tests use real PouchDB revision trees. They verify that an ordinary superseded revision releases its unique chunks, a chunk shared by current files remains reachable, live conflict branches and their nearest available shared ancestor remain protected, and losing-branch ancestry becomes eligible after resolution. They also replicate a collected chunk deletion to another PouchDB database and verify that writing the same content can recreate and replicate the content-addressed chunk. Self-hosted LiveSync owns the CouchDB-specific Garbage Collection V3 workflow, including device checks, confirmation, deletion, push-only replication, and remote compaction.
|
|
16
18
|
|
|
17
19
|
Most replication and storage services used by the plug-in still enter through explicit `compat/*` paths. Those imports prove that the published compatibility boundary supports the current migration; they are not examples of a finished high-level client API.
|
|
18
20
|
|
package/package.json
CHANGED