Cover stale-file recovery and bulk folder operations

Document exact file revision provenance and add real Obsidian scenarios for stale files after restart, parent-folder renames, and parent-folder deletion. Characterise replication queue delays during repeated writes to one document.

Companion to Commonlib c0a84a4. Validation used its packed artefact; the local file dependency remains uncommitted until a published Commonlib version is available.
This commit is contained in:
vorotamoroz
2026-09-17 11:06:53 +00:00
parent b3d01598ac
commit ef99cd8499
9 changed files with 454 additions and 23 deletions
+28 -6
View File
@@ -997,14 +997,26 @@ async function runMarkdownAutoMerge(
session = await startConfiguredSession(context, vaultA, conflictOverrides);
const baseOnA = await waitForLocalDatabaseEntry(context.cliBinary, session.cliEnv, conflictPath);
await storeFileRevision(context.cliBinary, session.cliEnv, conflictPath, left, baseOnA.rev);
await writeVaultFile(vaultA.path, conflictPath, left);
await writeNoteViaObsidian(context.cliBinary, session.cliEnv, conflictPath, left);
const storedLeft = await waitForConflictBranch(
context.cliBinary,
session.cliEnv,
conflictPath,
(branch) => branch.content === left
);
assertEqual(storedLeft.parentRev, baseOnA.rev, "Vault A's edit did not extend its displayed base.");
await pushLocalChanges(context.cliBinary, session.cliEnv);
await stopTrackedSession(context, session);
session = await startConfiguredSession(context, vaultB, conflictOverrides);
await storeFileRevision(context.cliBinary, session.cliEnv, conflictPath, right, baseOnB.rev);
await writeVaultFile(vaultB.path, conflictPath, right);
await writeNoteViaObsidian(context.cliBinary, session.cliEnv, conflictPath, right);
const storedRight = await waitForConflictBranch(
context.cliBinary,
session.cliEnv,
conflictPath,
(branch) => branch.content === right
);
assertEqual(storedRight.parentRev, baseOnB.rev, "Vault B's edit did not extend its displayed base.");
await pushLocalChanges(context.cliBinary, session.cliEnv);
const conflict = await waitForFileConflict(context.cliBinary, session.cliEnv, conflictPath);
const leftBranch = conflict.branches.find((branch) => branch.content === left);
@@ -1028,8 +1040,18 @@ async function runMarkdownAutoMerge(
);
const afterResolution = `${merged.trimEnd()}\n\nPost-resolution edit on B.\n`;
await storeFileRevision(context.cliBinary, session.cliEnv, conflictPath, afterResolution, mergedRev);
await writeVaultFile(vaultB.path, conflictPath, afterResolution);
await writeNoteViaObsidian(context.cliBinary, session.cliEnv, conflictPath, afterResolution);
const storedAfterResolution = await waitForConflictBranch(
context.cliBinary,
session.cliEnv,
conflictPath,
(branch) => branch.content === afterResolution
);
assertEqual(
storedAfterResolution.parentRev,
mergedRev,
"The post-resolution edit did not extend the merged revision."
);
await pushLocalChanges(context.cliBinary, session.cliEnv);
await stopTrackedSession(context, session);