@narumitw/pi-sync 0.52.0 → 0.53.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/README.md +3 -4
- package/dist/chunks/{chunk-7D6RDCVC.ts → chunk-BX3K7YW7.ts} +2 -2
- package/dist/chunks/{chunk-QHSQCK7L.ts → chunk-FHNISD7A.ts} +2 -2
- package/dist/chunks/{chunk-2CBF6SMT.ts → chunk-I5IG4WV4.ts} +2 -2
- package/dist/chunks/{chunk-WKPX2SIC.ts → chunk-NGIJQSRE.ts} +2 -2
- package/dist/chunks/{chunk-2GUXI2XT.ts → chunk-QTCGWQP3.ts} +74 -30
- package/dist/chunks/chunk-QTCGWQP3.ts.map +7 -0
- package/dist/chunks/{conflict-review-T3PB7ZSD.ts → conflict-review-NK5CM6UA.ts} +3 -3
- package/dist/chunks/{manager-result-dispatcher-VIDT3QBU.ts → manager-result-dispatcher-35TM3ZR3.ts} +4 -4
- package/dist/chunks/{manager-ui-HSMHS3OK.ts → manager-ui-6AYMNXUP.ts} +7 -7
- package/dist/chunks/{remote-selection-ui-SMF5CLFO.ts → remote-selection-ui-BB5SX6P5.ts} +3 -3
- package/dist/chunks/{s3-backend-DJ2NT3SZ.ts → s3-backend-O2AS3TH6.ts} +99 -9
- package/dist/chunks/s3-backend-O2AS3TH6.ts.map +7 -0
- package/dist/chunks/{sync-inspection-VBJF2FWC.ts → sync-inspection-RLIHUYDV.ts} +3 -3
- package/dist/chunks/{sync-operations-27VQUDH2.ts → sync-operations-RBUOUJWL.ts} +4 -4
- package/dist/index.ts +5 -5
- package/package.json +1 -1
- package/src/backends/s3/s3-backend.ts +23 -5
- package/src/backends/s3/s3-client.ts +33 -6
- package/src/backends/s3/s3-conditions.ts +67 -0
- package/src/sync/merge-apply.ts +76 -28
- package/dist/chunks/chunk-2GUXI2XT.ts.map +0 -7
- package/dist/chunks/s3-backend-DJ2NT3SZ.ts.map +0 -7
- /package/dist/chunks/{chunk-7D6RDCVC.ts.map → chunk-BX3K7YW7.ts.map} +0 -0
- /package/dist/chunks/{chunk-QHSQCK7L.ts.map → chunk-FHNISD7A.ts.map} +0 -0
- /package/dist/chunks/{chunk-2CBF6SMT.ts.map → chunk-I5IG4WV4.ts.map} +0 -0
- /package/dist/chunks/{chunk-WKPX2SIC.ts.map → chunk-NGIJQSRE.ts.map} +0 -0
- /package/dist/chunks/{conflict-review-T3PB7ZSD.ts.map → conflict-review-NK5CM6UA.ts.map} +0 -0
- /package/dist/chunks/{manager-result-dispatcher-VIDT3QBU.ts.map → manager-result-dispatcher-35TM3ZR3.ts.map} +0 -0
- /package/dist/chunks/{manager-ui-HSMHS3OK.ts.map → manager-ui-6AYMNXUP.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-SMF5CLFO.ts.map → remote-selection-ui-BB5SX6P5.ts.map} +0 -0
- /package/dist/chunks/{sync-inspection-VBJF2FWC.ts.map → sync-inspection-RLIHUYDV.ts.map} +0 -0
- /package/dist/chunks/{sync-operations-27VQUDH2.ts.map → sync-operations-RBUOUJWL.ts.map} +0 -0
package/README.md
CHANGED
|
@@ -166,7 +166,7 @@ Shutdown behavior is unchanged: when **Automatic sync** is On and sessions are i
|
|
|
166
166
|
|
|
167
167
|
**Settings → Automatic transfer at startup** controls the separate per-setup `sync.automaticTransfer` boolean, which defaults to `false`. It authorizes one conflict-free startup transfer at a validated idle boundary in TUI/RPC, including session replacement and `/reload`. Busy startup waits for `agent_settled`; foreground commands, a new agent run, replacement, and shutdown cancel and drain owned work. Changing the setting affects authorization immediately; enabling it schedules the next attempt on the next session start. There is no watcher or polling loop.
|
|
168
168
|
|
|
169
|
-
A baseline and matching authoritative content list are required. First-source choice, changed selection, missing established remote, secrets, and real conflicts remain review barriers. Automatic transfer requires conditional or lease-protected publication: Git
|
|
169
|
+
A baseline and matching authoritative content list are required. First-source choice, changed selection, missing established remote, secrets, and real conflicts remain review barriers. Automatic transfer requires conditional or lease-protected publication: Git, verified WebDAV, and R2/S3 with verified conditional writes are supported. The existing **Automatic sync** setting and shutdown policy are unchanged when this new opt-in is absent.
|
|
170
170
|
|
|
171
171
|
Successful transfers show one summary. They do not reload resources, activate extension code, or rewrite model context. After local resources change, reload or restart when ready; newly pulled conversations still require explicit resume. Headless print/JSON skip this new startup feature. Reviewed directional settings/session-root transitions record both roots and verified settings evidence so interrupted apply can recover before or after settings installation. Older pending journals without transition evidence retain their original root-ownership checks and may require reviewed recovery; preserve their backups rather than downgrading. See [merge safety and recovery](./docs/merge-implementation-audit.md) for journal boundaries, external-writer limits, and downgrade guidance.
|
|
172
172
|
|
|
@@ -264,7 +264,7 @@ Review [Settings](#-settings) for included-content privacy and [Manager, conflic
|
|
|
264
264
|
| --- | --- | --- | --- |
|
|
265
265
|
| Git | Exact expected-ref lease | Existing SSH/configured credential helper | `<branch>:<storage.path>` |
|
|
266
266
|
| WebDAV | Verified strong conditional requests | Private settings username/app password | `<url>/<storage.path>` |
|
|
267
|
-
| R2/S3 |
|
|
267
|
+
| R2/S3 | Verified strong conditional requests | Private settings credentials | `<bucket>/<storage.path>` |
|
|
268
268
|
|
|
269
269
|
Git requires Git 2.30 or newer and a SHA-1-format remote repository.
|
|
270
270
|
HTTPS userinfo, URL passwords, local paths, `file`, `git`, `ext`, and remote-helper transports are rejected.
|
|
@@ -275,8 +275,7 @@ WebDAV requires HTTPS except loopback tests.
|
|
|
275
275
|
URL credentials, query strings, fragments, unsafe redirects, weak/missing ETags, and ignored conditional headers fail closed.
|
|
276
276
|
`/sync doctor` verifies collection and conditional-write behavior with an isolated probe, then repairs a missing active-snapshot history entry.
|
|
277
277
|
|
|
278
|
-
S3/R2
|
|
279
|
-
Unlike Git/WebDAV, generic S3 does not provide an atomic compare-and-swap for `latest.json`; status review remains important for simultaneous writers.
|
|
278
|
+
S3/R2 publishes `latest.json` and history using ETag `If-Match`, or `If-None-Match: *` for first creation, then verifies the active pointer. Before each publication, an isolated `.pi-sync-probes/<random-id>` object verifies that the server rejects stale ETags and create-only writes to existing objects and rotates strong ETags. Credentials must allow read, write, and delete under the selected storage path; the probe is deleted even after cancellation. Missing/weak ETags, ignored conditions, and probe or cleanup failures stop publication. A failed cleanup reports the probe key for manual removal; bucket versioning may retain probe versions. `/sync doctor` remains read-only for S3/R2 and does not verify write support.
|
|
280
279
|
|
|
281
280
|
Snapshot recovery is guarded: new journals record before/after images, older journals are retired only when their unchanged preimages are provable, and unrecognized bytes remain untouched for manual review. Current-session targets are never restored during startup. Preserve a blocked transaction and its backup, close Pi, and review the private evidence before restoring selected paths; malformed/unsupported journals are not disposable. Pi may have loaded resources before lifecycle recovery, so reload or restart explicitly after recovery if loaded resources need to match the restored files.
|
|
282
281
|
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-BDB4IDM3.ts";
|
|
7
7
|
import {
|
|
8
8
|
createSyncBackend
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FHNISD7A.ts";
|
|
10
10
|
import {
|
|
11
11
|
throwIfAborted
|
|
12
12
|
} from "./chunk-PWMWOJP4.ts";
|
|
@@ -47,4 +47,4 @@ async function inspectSync(config, options, signal, factory = createSyncBackend)
|
|
|
47
47
|
export {
|
|
48
48
|
inspectSync
|
|
49
49
|
};
|
|
50
|
-
//# sourceMappingURL=chunk-
|
|
50
|
+
//# sourceMappingURL=chunk-BX3K7YW7.ts.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
var createSyncBackend = async (config) => {
|
|
6
6
|
switch (config.backend.type) {
|
|
7
7
|
case "s3": {
|
|
8
|
-
const { S3SyncBackend } = await import("./s3-backend-
|
|
8
|
+
const { S3SyncBackend } = await import("./s3-backend-O2AS3TH6.ts");
|
|
9
9
|
return new S3SyncBackend(config.backend);
|
|
10
10
|
}
|
|
11
11
|
case "webdav": {
|
|
@@ -22,4 +22,4 @@ var createSyncBackend = async (config) => {
|
|
|
22
22
|
export {
|
|
23
23
|
createSyncBackend
|
|
24
24
|
};
|
|
25
|
-
//# sourceMappingURL=chunk-
|
|
25
|
+
//# sourceMappingURL=chunk-FHNISD7A.ts.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-V6VZ5TLG.ts";
|
|
6
6
|
import {
|
|
7
7
|
createSyncBackend
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FHNISD7A.ts";
|
|
9
9
|
import {
|
|
10
10
|
setSyncStatus
|
|
11
11
|
} from "./chunk-K3RIEL6J.ts";
|
|
@@ -603,4 +603,4 @@ export {
|
|
|
603
603
|
runCancellableOperation,
|
|
604
604
|
showRemoteSelectionReview
|
|
605
605
|
};
|
|
606
|
-
//# sourceMappingURL=chunk-
|
|
606
|
+
//# sourceMappingURL=chunk-I5IG4WV4.ts.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
runCancellableOperation,
|
|
5
5
|
showRemoteSelectionReview
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-I5IG4WV4.ts";
|
|
7
7
|
import {
|
|
8
8
|
safeTerminalText
|
|
9
9
|
} from "./chunk-AMJRUXFT.ts";
|
|
@@ -206,4 +206,4 @@ async function dispatchManagerResult(ctx, initialResult, origin, runRoute, signa
|
|
|
206
206
|
export {
|
|
207
207
|
dispatchManagerResult
|
|
208
208
|
};
|
|
209
|
-
//# sourceMappingURL=chunk-
|
|
209
|
+
//# sourceMappingURL=chunk-NGIJQSRE.ts.map
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
} from "./chunk-V6VZ5TLG.ts";
|
|
26
26
|
import {
|
|
27
27
|
createSyncBackend
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-FHNISD7A.ts";
|
|
29
29
|
import {
|
|
30
30
|
applySnapshotTransaction,
|
|
31
31
|
recoverPendingSnapshotTransactions,
|
|
@@ -845,8 +845,29 @@ async function applyMergedSnapshot(before, after, protectedPaths, options, valid
|
|
|
845
845
|
protectedTarget,
|
|
846
846
|
new Set(Object.keys(afterHashes))
|
|
847
847
|
);
|
|
848
|
+
const targetsByQueue = /* @__PURE__ */ new Map();
|
|
849
|
+
const queueTargets = [];
|
|
850
|
+
const deferredTargets = [];
|
|
851
|
+
for (const target of targets) {
|
|
852
|
+
let key = path4.resolve(target);
|
|
853
|
+
try {
|
|
854
|
+
key = await fs4.realpath(target);
|
|
855
|
+
} catch (error) {
|
|
856
|
+
const code = error.code;
|
|
857
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") throw error;
|
|
858
|
+
}
|
|
859
|
+
options.signal?.throwIfAborted();
|
|
860
|
+
options.validateMutation?.();
|
|
861
|
+
const aliases = targetsByQueue.get(key) ?? [];
|
|
862
|
+
aliases.push(target);
|
|
863
|
+
targetsByQueue.set(key, aliases);
|
|
864
|
+
}
|
|
865
|
+
for (const [key, aliases] of targetsByQueue) {
|
|
866
|
+
queueTargets.push(key);
|
|
867
|
+
if (aliases.length > 1) deferredTargets.push(...aliases.filter((target) => path4.resolve(target) !== key));
|
|
868
|
+
}
|
|
848
869
|
async function acquire(index) {
|
|
849
|
-
const target =
|
|
870
|
+
const target = queueTargets[index];
|
|
850
871
|
if (target) return withFileMutationQueue(target, () => acquire(index + 1));
|
|
851
872
|
await validate();
|
|
852
873
|
await assertCanonicalMergedTargets(root, changed, options);
|
|
@@ -935,40 +956,63 @@ async function applyMergedSnapshot(before, after, protectedPaths, options, valid
|
|
|
935
956
|
}
|
|
936
957
|
await syncDirectory(path4.dirname(target2));
|
|
937
958
|
}
|
|
938
|
-
|
|
959
|
+
const requireAbsentDestinations = async () => {
|
|
939
960
|
await validate();
|
|
940
|
-
const
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
} catch (error) {
|
|
949
|
-
if (error.code !== "ENOENT") throw error;
|
|
961
|
+
for (const target2 of deferredTargets) {
|
|
962
|
+
try {
|
|
963
|
+
await fs4.lstat(target2);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
if (error.code !== "ENOENT") throw error;
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
throw new Error("Case replacement destination changed before queue reservation; journal retained for review.");
|
|
950
969
|
}
|
|
951
|
-
|
|
952
|
-
|
|
970
|
+
await validate();
|
|
971
|
+
};
|
|
972
|
+
async function acquireDestinations(index2) {
|
|
973
|
+
const target2 = deferredTargets[index2];
|
|
974
|
+
if (target2) return withFileMutationQueue(target2, () => acquireDestinations(index2 + 1));
|
|
975
|
+
await requireAbsentDestinations();
|
|
976
|
+
await writeTargets();
|
|
977
|
+
}
|
|
978
|
+
await requireAbsentDestinations();
|
|
979
|
+
await acquireDestinations(0);
|
|
980
|
+
async function writeTargets() {
|
|
981
|
+
for (const item of plan.writes) {
|
|
982
|
+
await validate();
|
|
983
|
+
const relative = relativeByTarget.get(item.target);
|
|
984
|
+
if (!relative) throw new Error("Unowned merge write target.");
|
|
985
|
+
await assertFilesystemTarget(root, relative, options, /* @__PURE__ */ new Set());
|
|
986
|
+
await fs4.mkdir(path4.dirname(item.target), { recursive: true });
|
|
987
|
+
const temporary = path4.join(path4.dirname(item.target), `.pi-sync.json.${randomUUID()}.apply`);
|
|
988
|
+
let mode = 384;
|
|
953
989
|
try {
|
|
954
|
-
await
|
|
955
|
-
|
|
990
|
+
mode = (await fs4.stat(item.target)).mode & 511;
|
|
991
|
+
} catch (error) {
|
|
992
|
+
if (error.code !== "ENOENT") throw error;
|
|
993
|
+
}
|
|
994
|
+
try {
|
|
995
|
+
const handle = await fs4.open(temporary, "wx", mode);
|
|
996
|
+
try {
|
|
997
|
+
await handle.writeFile(item.content);
|
|
998
|
+
await handle.sync();
|
|
999
|
+
} finally {
|
|
1000
|
+
await handle.close();
|
|
1001
|
+
}
|
|
1002
|
+
await revalidateTarget(item.target);
|
|
1003
|
+
await fs4.rename(temporary, item.target);
|
|
1004
|
+
await syncDirectory(path4.dirname(item.target));
|
|
956
1005
|
} finally {
|
|
957
|
-
await
|
|
1006
|
+
await fs4.rm(temporary, { force: true });
|
|
958
1007
|
}
|
|
959
|
-
await revalidateTarget(item.target);
|
|
960
|
-
await fs4.rename(temporary, item.target);
|
|
961
|
-
await syncDirectory(path4.dirname(item.target));
|
|
962
|
-
} finally {
|
|
963
|
-
await fs4.rm(temporary, { force: true });
|
|
964
1008
|
}
|
|
1009
|
+
await syncMutationParents(
|
|
1010
|
+
targets,
|
|
1011
|
+
[root, ...options.sessionDir ? [sessionStorageRoot(root, options.sessionDir)] : []],
|
|
1012
|
+
options
|
|
1013
|
+
);
|
|
1014
|
+
await validate();
|
|
965
1015
|
}
|
|
966
|
-
await syncMutationParents(
|
|
967
|
-
targets,
|
|
968
|
-
[root, ...options.sessionDir ? [sessionStorageRoot(root, options.sessionDir)] : []],
|
|
969
|
-
options
|
|
970
|
-
);
|
|
971
|
-
await validate();
|
|
972
1016
|
}
|
|
973
1017
|
await acquire(0);
|
|
974
1018
|
}
|
|
@@ -1699,4 +1743,4 @@ export {
|
|
|
1699
1743
|
createSyncDecision,
|
|
1700
1744
|
mergeSync
|
|
1701
1745
|
};
|
|
1702
|
-
//# sourceMappingURL=chunk-
|
|
1746
|
+
//# sourceMappingURL=chunk-QTCGWQP3.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/merge-review.ts", "../../src/ui/sync-format.ts", "../../src/sync/conflict-artifact-ownership.ts", "../../src/sync/conflict-resolution.ts", "../../src/sync/conflict-retention.ts", "../../src/sync/content-conflicts.ts", "../../src/sync/merge-apply.ts", "../../src/snapshot/snapshot-apply.ts", "../../src/sync/partial-progress.ts", "../../src/sync/settings-conflicts.ts", "../../src/sync/settings-merge.ts", "../../src/sync/sync-decision.ts", "../../src/sync/merged-sync.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionCommandContext, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { runDocumentReview } from \"@narumitw/pi-tui-kit\";\n\n/** Cell-exact scrolling in TUI and paginated observable confirmation in RPC. */\nexport async function confirmMergeReview(\n ctx: ExtensionCommandContext | ExtensionContext,\n title: string,\n content: string,\n signal: AbortSignal | undefined,\n isCurrent: () => boolean,\n confirmationLabel = \"Apply merged transfer\",\n) {\n const result = await runDocumentReview(ctx, {\n title,\n content,\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n confirmation: { label: confirmationLabel },\n hint: \"close\",\n signal,\n isCurrent,\n onError: () => {},\n });\n if (result.kind === \"error\") throw new Error(\"Merge review failed; no transfer was performed.\");\n if (result.kind === \"unsupported\")\n throw new Error(\"Merge review requires observable TUI or RPC; review the plan before using --yes.\");\n return result.kind === \"confirmed\";\n}\n", "import type { PublicationCapability, RemoteHead } from \"../backends/sync-backend.js\";\nimport type { CommonSyncConfig } from \"../settings/settings-types.js\";\nimport { agentDir } from \"../snapshot/session-paths.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { inspectRemoteSelection } from \"../sync/sync-policy.js\";\nimport { fileHashMap } from \"../sync/sync-state.js\";\nimport { safeTerminalText, snapshotPathLabel } from \"./terminal-text.js\";\n\nexport function formatDiff(local: Snapshot, remote: Snapshot) {\n const localMap = fileHashMap(local);\n const remoteMap = fileHashMap(remote);\n const allPaths = [...new Set([...Object.keys(localMap), ...Object.keys(remoteMap)])].sort();\n const lines = [`local: ${local.files.length} files`, `remote: ${remote.id} (${remote.files.length} files)`, \"\"];\n let changed = 0;\n for (const filePath of allPaths) {\n if (!Object.hasOwn(localMap, filePath)) {\n lines.push(`Remote only: ${snapshotPathLabel(filePath)}`);\n changed += 1;\n } else if (!Object.hasOwn(remoteMap, filePath)) {\n lines.push(`Local only: ${snapshotPathLabel(filePath)}`);\n changed += 1;\n } else if (localMap[filePath] !== remoteMap[filePath]) {\n lines.push(`Different: ${snapshotPathLabel(filePath)}`);\n changed += 1;\n }\n }\n if (changed === 0) lines.push(\"No file differences.\");\n return lines.join(\"\\n\");\n}\n\nexport function formatSnapshotOnlyDiff(title: string, snapshot: Snapshot) {\n return [`${title}: ${snapshot.id}`, ...snapshot.files.map((file) => `Add: ${snapshotPathLabel(file.path)}`)].join(\n \"\\n\",\n );\n}\n\nexport function formatPushSummary(\n config: CommonSyncConfig,\n destination: string,\n upload: Snapshot,\n head: RemoteHead | undefined,\n preservedRemoteFileCount = 0,\n remote?: Snapshot,\n) {\n return [\n `Sync setup: ${safeTerminalText(config.setupName)}`,\n `Storage location: ${safeTerminalText(destination)}`,\n `Upload ${upload.files.length} files from ${safeTerminalText(agentDir())}.`,\n `Sessions: ${upload.syncSessions ? \"included \u2014 may contain private conversations\" : \"not included\"}`,\n head ? `Remote latest: ${head.snapshotId}` : \"Remote latest: empty\",\n \"Publication effect: the backend's active head will reference the new immutable snapshot.\",\n ...(remote && inspectRemoteSelection(config.include, remote).kind === \"different\"\n ? [\"Included-content policy effect: replace the differing remote selection with this setup's local selection.\"]\n : []),\n formatPublicationPreview(remote, upload),\n preservedRemoteFileCount > 0\n ? `Possible secrets in locally managed files were scanned before this prompt; ${preservedRemoteFileCount} preserved remote file(s) were not rescanned.`\n : \"Possible secrets were scanned before this prompt.\",\n ].join(\"\\n\");\n}\n\nexport function formatApplyPreview(local: Snapshot, remote: Snapshot) {\n return formatDirectionalChanges(local, remote, {\n add: \"Add locally\",\n update: \"Update locally\",\n remove: \"Remove locally\",\n });\n}\n\nexport function formatPullSummary(\n config: CommonSyncConfig,\n destination: string,\n local: Snapshot,\n remote: Snapshot,\n protectedSessionCount: number,\n) {\n return [\n `Sync setup: ${safeTerminalText(config.setupName)}`,\n `Storage location: ${safeTerminalText(destination)}`,\n `Snapshot: ${safeTerminalText(remote.id)}`,\n `Sessions: ${remote.syncSessions ? \"included \u2014 may contain private conversations\" : \"not included\"}`,\n `Protected live sessions: ${protectedSessionCount || \"none\"}`,\n formatApplyPreview(local, remote),\n \"A local backup is created before these writes/deletes. The remote active snapshot is unchanged.\",\n ].join(\"\\n\");\n}\n\nexport function formatRollbackSummary(\n config: CommonSyncConfig,\n destination: string,\n local: Snapshot,\n remote: Snapshot,\n requestedSnapshot: string,\n protectedSessionCount: number,\n) {\n return [\n `Sync setup: ${safeTerminalText(config.setupName)}`,\n `Storage location: ${safeTerminalText(destination)}`,\n `Snapshot: ${safeTerminalText(requestedSnapshot)}`,\n `Sessions: ${remote.syncSessions ? \"included \u2014 may contain private conversations\" : \"not included\"}`,\n `Protected live sessions: ${protectedSessionCount || \"none\"}`,\n formatApplyPreview(local, remote),\n \"A local backup is created before applying; the backend's active head will change.\",\n ].join(\"\\n\");\n}\n\nexport function formatPublicationPreview(remote: Snapshot | undefined, upload: Snapshot) {\n if (!remote) {\n return [\"Remote is empty.\", ...upload.files.map((file) => `Add remotely: ${snapshotPathLabel(file.path)}`)].join(\n \"\\n\",\n );\n }\n return formatDirectionalChanges(remote, upload, {\n add: \"Add remotely\",\n update: \"Update remotely\",\n remove: \"Remove remotely\",\n });\n}\n\nfunction formatDirectionalChanges(\n before: Snapshot,\n after: Snapshot,\n labels: { add: string; update: string; remove: string },\n) {\n const beforeMap = fileHashMap(before);\n const afterMap = fileHashMap(after);\n const paths = [...new Set([...Object.keys(beforeMap), ...Object.keys(afterMap)])].sort();\n const lines: string[] = [];\n for (const filePath of paths) {\n if (!Object.hasOwn(beforeMap, filePath)) lines.push(`${labels.add}: ${snapshotPathLabel(filePath)}`);\n else if (!Object.hasOwn(afterMap, filePath)) lines.push(`${labels.remove}: ${snapshotPathLabel(filePath)}`);\n else if (beforeMap[filePath] !== afterMap[filePath]) lines.push(`${labels.update}: ${snapshotPathLabel(filePath)}`);\n }\n if (lines.length === 0) lines.push(\"No file changes.\");\n return lines.join(\"\\n\");\n}\n\nexport function countPreservedRemoteFiles(local: Snapshot, upload: Snapshot) {\n const localPaths = new Set(local.files.map((file) => file.path));\n return upload.files.filter((file) => !localPaths.has(file.path)).length;\n}\n\nexport function publicationCapabilityDescription(capability: PublicationCapability) {\n switch (capability) {\n case \"lease-protected\":\n return \"lease-protected (exact expected-ref update)\";\n case \"atomic-conditional\":\n return \"atomic-conditional (verified atomic precondition)\";\n case \"conditional-required\":\n return \"conditional-required (read-only until atomic preconditions are verified)\";\n case \"read-check-write-verify\":\n return \"read-check-write-verify (visible races rejected; simultaneous unseen races remain possible)\";\n }\n}\n\nexport function redact(value: string) {\n return value.length <= 8 ? \"configured\" : `${value.slice(0, 4)}\u2026${value.slice(-4)}`;\n}\n", "import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { syncDirectory } from \"../state/json-file.js\";\nimport { readStateForConfig, statePathForConfig } from \"../state/sync-state-store.js\";\nimport {\n type ConflictArtifact,\n type CreatedConflictArtifact,\n conflictArtifactFingerprint,\n conflictDirectory,\n} from \"./conflict-artifacts.js\";\nimport { readMergeJournal } from \"./merge-journal.js\";\n\n/** Attempt-owned cleanup only: unknown evidence remains the retention policy's responsibility. */\nexport async function releaseConflictArtifacts(\n config: AnySyncConfig,\n statePath: string,\n created: readonly CreatedConflictArtifact[],\n) {\n if (!created.length || statePathForConfig(config) !== statePath) return;\n try {\n const state = await readStateForConfig(config);\n if (statePathForConfig(config) !== statePath) return;\n const journal = await readMergeJournal(config);\n if (statePathForConfig(config) !== statePath) return;\n const referenced = new Set([\n ...(state.unresolved ?? []).map((group) => group.artifact),\n ...(journal?.progress?.groups ?? []).map((group) => group.artifact),\n ]);\n for (const lease of created) {\n if (referenced.has(lease.token) || lease.target !== path.join(conflictDirectory(config), `${lease.token}.json`))\n continue;\n try {\n const stat = await fs.lstat(lease.target);\n if (\n !stat.isFile() ||\n stat.nlink !== 1 ||\n stat.dev !== lease.dev ||\n stat.ino !== lease.ino ||\n stat.size !== lease.size\n )\n continue;\n const artifact = JSON.parse(await fs.readFile(lease.target, \"utf8\")) as ConflictArtifact;\n if (conflictArtifactFingerprint(artifact) !== lease.fingerprint || statePathForConfig(config) !== statePath)\n continue;\n const latest = await fs.lstat(lease.target);\n if (\n latest.dev !== lease.dev ||\n latest.ino !== lease.ino ||\n latest.nlink !== 1 ||\n statePathForConfig(config) !== statePath\n )\n continue;\n await fs.unlink(lease.target);\n await syncDirectory(path.dirname(lease.target));\n } catch {\n /* Missing, replaced or unreadable evidence is not ours to delete. */\n }\n }\n } catch {\n /* Invalid state/journal or unavailable storage cannot prove lack of references. */\n }\n}\n", "import type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { syncStateFingerprint } from \"../state/sync-state-store.js\";\nimport { conflictArtifactFingerprint, readConflictArtifact } from \"./conflict-artifacts.js\";\nimport { type FileMergePlan, mergePathIdentity, planFileMerge } from \"./file-merge-planner.js\";\nimport { fileHashMap } from \"./sync-state.js\";\nexport interface ConflictResolution {\n token: string;\n group: number;\n source: \"local\" | \"remote\";\n stateIdentity: string;\n artifactIdentity: string;\n}\nexport async function resolveReviewedGroup(\n config: AnySyncConfig,\n backend: SyncBackend,\n state: SyncState,\n local: Snapshot,\n remote: Snapshot,\n head: RemoteHead,\n plan: FileMergePlan,\n resolution: ConflictResolution,\n protectedPaths: ReadonlySet<string>,\n): Promise<FileMergePlan> {\n const artifact = await readConflictArtifact(config, backend.identity, resolution.token);\n const group = artifact.groups[resolution.group];\n if (\n conflictArtifactFingerprint(artifact) !== resolution.artifactIdentity ||\n !group ||\n plan.kind !== \"planned\" ||\n !state.unresolved?.some(\n (item) => item.artifact === resolution.token && JSON.stringify(item.paths) === JSON.stringify(group.paths),\n ) ||\n syncStateFingerprint(state) !== resolution.stateIdentity ||\n state.lastObservedSnapshot !== head.snapshotId ||\n !state.lastObservedRevision ||\n !backend.sameRevision(state.lastObservedRevision, head.revision)\n )\n throw new Error(\"Conflict review is stale; refresh sync and review again.\");\n const ours = fileHashMap(local);\n const theirs = fileHashMap(remote);\n const oldOurs = fileHashMap(artifact.local);\n const oldTheirs = fileHashMap(artifact.remote);\n if (\n group.paths.some(\n (filePath) =>\n ours[filePath] !== oldOurs[filePath] ||\n theirs[filePath] !== oldTheirs[filePath] ||\n state.lastFileHashes[filePath] !== artifact.state.lastFileHashes[filePath],\n )\n )\n throw new Error(\"Conflict versions changed; no resolution was applied.\");\n if (\n group.paths.some((filePath) =>\n [...protectedPaths].some((value) => mergePathIdentity(value) === mergePathIdentity(filePath)),\n )\n )\n throw new Error(\n \"Current session conflict cannot be resolved from the loaded session; preserve evidence and close Pi.\",\n );\n const selected = resolution.source === \"local\" ? local : remote;\n const paths = new Set(group.paths);\n for (const snapshot of [selected, local]) {\n const layout = planFileMerge({\n baseline: {},\n local: snapshot.files.filter((file) => paths.has(file.path)),\n remote: [],\n selectionCompatible: true,\n });\n if (layout.kind !== \"planned\" || layout.conflicts.length)\n throw new Error(\n \"Selected/current local group still has path collisions; preserve evidence, repair the layout manually and refresh sync.\",\n );\n }\n const selectedFiles = new Map(selected.files.map((file) => [file.path, file]));\n const decisions = plan.decisions.map((item) =>\n paths.has(item.path)\n ? {\n kind: \"accepted\" as const,\n path: item.path,\n source: resolution.source,\n file: selectedFiles.get(item.path),\n }\n : item,\n );\n return {\n kind: \"planned\",\n decisions,\n conflicts: decisions.filter((item): item is Extract<typeof item, { kind: \"conflict\" }> => item.kind === \"conflict\"),\n };\n}\n", "import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { syncDirectory } from \"../state/json-file.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { conflictDirectory, readConflictArtifact } from \"./conflict-artifacts.js\";\nimport { fileHashMap } from \"./sync-state.js\";\n/** Only after accepted state and journal retirement, under the operation lock. Unknown/unresolved evidence is never pruned. */\nexport async function pruneCompletedConflicts(\n config: AnySyncConfig,\n backend: string,\n state: SyncState,\n local: Snapshot,\n remote: Snapshot,\n validate: () => void,\n) {\n validate();\n const directory = conflictDirectory(config);\n let names: string[];\n try {\n const stat = await fs.lstat(directory);\n validate();\n if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error(\"Unsafe conflict retention directory.\");\n names = await fs.readdir(directory);\n validate();\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw error;\n }\n const pinned = new Set(state.unresolved?.map((group) => group.artifact) ?? []);\n const ours = fileHashMap(local);\n const theirs = fileHashMap(remote);\n const completed: { token: string; modified: number }[] = [];\n for (const name of names) {\n validate();\n const token = name.replace(/\\.json$/u, \"\");\n if (!/^[a-f0-9-]{36}\\.json$/u.test(name) || pinned.has(token)) continue;\n try {\n const artifact = await readConflictArtifact(config, backend, token);\n validate();\n const originalLocal = fileHashMap(artifact.local);\n const originalRemote = fileHashMap(artifact.remote);\n if (\n !artifact.groups.every((group) =>\n group.paths.every(\n (filePath) =>\n state.lastFileHashes[filePath] === ours[filePath] &&\n ours[filePath] === theirs[filePath] &&\n (ours[filePath] === originalLocal[filePath] || ours[filePath] === originalRemote[filePath]),\n ),\n )\n )\n continue;\n const stat = await fs.lstat(path.join(directory, name));\n validate();\n if (stat.isFile()) completed.push({ token, modified: stat.mtimeMs });\n } catch {\n validate(); /* Corrupt/unknown evidence remains. */\n }\n }\n completed.sort((left, right) => right.modified - left.modified || left.token.localeCompare(right.token));\n for (const entry of completed.slice(32)) {\n validate();\n await fs.rm(path.join(directory, `${entry.token}.json`));\n validate();\n }\n if (completed.length > 32) {\n await syncDirectory(directory);\n validate();\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot, SnapshotFile } from \"../snapshot/snapshot-types.js\";\nimport { readMergeAncestors } from \"../state/merge-baseline-store.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { type FileMergePlan, mergePathIdentity } from \"./file-merge-planner.js\";\nimport { mergeSession } from \"./session-merge.js\";\nimport { isMergeTextPath, mergeText, TEXT_MERGE_WORK_LIMIT, type TextMergeBudget } from \"./text-merge.js\";\nexport function snapshotFile(filePath: string, bytes: Buffer): SnapshotFile {\n return {\n path: filePath,\n contentBase64: bytes.toString(\"base64\"),\n sha256: createHash(\"sha256\").update(bytes).digest(\"hex\"),\n };\n}\nexport async function resolveContentConflicts(\n config: AnySyncConfig,\n state: SyncState,\n local: Snapshot,\n remote: Snapshot,\n plan: FileMergePlan,\n protectedPaths: ReadonlySet<string>,\n options: { textBudget?: TextMergeBudget; signal?: AbortSignal } = {},\n): Promise<FileMergePlan> {\n if (plan.kind !== \"planned\" || !config.mergeContent) return plan;\n options.signal?.throwIfAborted();\n const budget = options.textBudget ?? { remaining: TEXT_MERGE_WORK_LIMIT };\n const decisions = [...plan.decisions];\n let ancestors: SnapshotFile[] = [];\n try {\n ancestors = (await readMergeAncestors(config, state)) ?? [];\n } catch {\n options.signal?.throwIfAborted();\n return plan;\n }\n options.signal?.throwIfAborted();\n const oursByPath = new Map(local.files.map((file) => [file.path, file]));\n const theirsByPath = new Map(remote.files.map((file) => [file.path, file]));\n const ancestorsByPath = new Map(ancestors.map((file) => [file.path, file]));\n const decisionIndex = new Map(decisions.map((decision, index) => [decision.path, index]));\n const protectedKeys = new Set([...protectedPaths].map(mergePathIdentity));\n for (const conflict of plan.conflicts) {\n options.signal?.throwIfAborted();\n if (conflict.reason !== \"both-changed\" || protectedKeys.has(mergePathIdentity(conflict.path))) continue;\n const session = conflict.path.startsWith(\"sessions/\") && conflict.path.endsWith(\".jsonl\");\n if (!session && (!isMergeTextPath(conflict.path) || budget.remaining === 0)) continue;\n const ours = oursByPath.get(conflict.path);\n const theirs = theirsByPath.get(conflict.path);\n if (!ours || !theirs) continue;\n const ancestor = ancestorsByPath.get(conflict.path);\n const base = ancestor ? Buffer.from(ancestor.contentBase64, \"base64\") : undefined;\n if (!base) continue;\n const localBytes = Buffer.from(ours.contentBase64, \"base64\");\n const remoteBytes = Buffer.from(theirs.contentBase64, \"base64\");\n const bytes = session\n ? mergeSession(base, localBytes, remoteBytes)\n : mergeText(base, localBytes, remoteBytes, { budget, signal: options.signal });\n if (!bytes) continue;\n const index = decisionIndex.get(conflict.path);\n if (index === undefined) continue;\n decisions[index] = {\n kind: \"accepted\",\n path: conflict.path,\n source: \"merged\",\n file: snapshotFile(conflict.path, bytes),\n };\n }\n return {\n kind: \"planned\",\n decisions,\n conflicts: decisions.filter((item): item is Extract<typeof item, { kind: \"conflict\" }> => item.kind === \"conflict\"),\n };\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { withFileMutationQueue } from \"@earendil-works/pi-coding-agent\";\nimport { agentDir } from \"../snapshot/session-paths.js\";\nimport { createSnapshot, snapshotTarget } from \"../snapshot/snapshot.js\";\nimport { preflightSnapshotApply, preflightSnapshotMutations } from \"../snapshot/snapshot-apply.js\";\nimport { sessionStorageRoot } from \"../snapshot/snapshot-paths.js\";\nimport type { Snapshot, SnapshotOptions } from \"../snapshot/snapshot-types.js\";\nimport { syncDirectory } from \"../state/json-file.js\";\nimport { syncMutationParents } from \"../state/mutation-directory-sync.js\";\nimport { mergePathIdentity } from \"./file-merge-planner.js\";\nimport { fileHashMap } from \"./sync-state.js\";\n\n/** Read-only filesystem applicability check before publishing a combined result. */\nexport async function preflightMergedTargets(\n before: Snapshot,\n after: Snapshot,\n options: SnapshotOptions,\n protectedTarget?: string,\n) {\n const root = agentDir();\n const beforeHashes: Record<string, string> = Object.assign(Object.create(null), fileHashMap(before));\n const afterHashes: Record<string, string> = Object.assign(Object.create(null), fileHashMap(after));\n const paths = [...new Set([...Object.keys(beforeHashes), ...Object.keys(afterHashes)])].sort();\n const changed = new Set(paths.filter((item) => beforeHashes[item] !== afterHashes[item]));\n await assertCanonicalMergedTargets(root, changed, options);\n await assertDistinctMergedTargets(root, paths, changed, options, protectedTarget, new Set(Object.keys(afterHashes)));\n const removed = replacementPaths(\n new Set(paths.filter((item) => changed.has(item) && !afterHashes[item])),\n afterHashes,\n );\n const removedTargets = new Set([...removed].map((item) => snapshotTarget(root, item, options.sessionDir)));\n for (const relative of paths) {\n if (changed.has(relative)) await assertFilesystemTarget(root, relative, options, removedTargets, beforeHashes);\n }\n}\n\nfunction replacementPaths(removed: Set<string>, afterHashes: Readonly<Record<string, string>>) {\n for (const relative of [...removed]) {\n let parent = path.posix.dirname(relative);\n while (parent !== \".\") {\n if (afterHashes[parent]) {\n for (\n let directory = path.posix.dirname(relative);\n directory !== parent;\n directory = path.posix.dirname(directory)\n )\n removed.add(directory);\n removed.add(parent);\n break;\n }\n parent = path.posix.dirname(parent);\n }\n }\n return removed;\n}\n\n/** Snapshot collection canonicalizes top-level names, but merged journals own exact physical paths. */\nasync function assertCanonicalMergedTargets(root: string, changed: Iterable<string>, options: SnapshotOptions) {\n const topLevel = new Map(\n [...changed].filter((relative) => !relative.includes(\"/\")).map((relative) => [relative.toLowerCase(), relative]),\n );\n if (topLevel.size === 0) return;\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n let names: string[];\n try {\n names = await fs.readdir(root);\n } catch (error) {\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n return;\n }\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n for (const name of names) {\n const canonical = topLevel.get(name.toLowerCase());\n if (canonical !== undefined && name !== canonical)\n throw new Error(\n \"Merged target has a noncanonical case variant; normalize selected top-level file spelling before retrying. Journal retained if already committed.\",\n );\n }\n}\n\n/** Even an unchanged virtual alias must not describe different bytes for a changed physical file. */\nasync function assertDistinctMergedTargets(\n root: string,\n paths: string[],\n changed: ReadonlySet<string>,\n options: SnapshotOptions,\n protectedTarget?: string,\n finalPaths: ReadonlySet<string> = new Set(paths),\n) {\n const protectedKey = protectedTarget\n ? mergePathIdentity(await resolvedTargetIdentity(path.resolve(protectedTarget), options))\n : undefined;\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n const keys = new Map<string, string>();\n for (const relative of paths) {\n options.signal?.throwIfAborted();\n const target = snapshotTarget(root, relative, options.sessionDir);\n const key = mergePathIdentity(await resolvedTargetIdentity(target, options));\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n const existing = keys.get(key);\n if (\n existing &&\n (mergePathIdentity(existing) !== mergePathIdentity(relative) ||\n (finalPaths.has(existing) && finalPaths.has(relative)))\n )\n throw new Error(\"Merged paths resolve to the same file; reviewed directional recovery is required.\");\n if (key === protectedKey && changed.has(relative))\n throw new Error(\"A merged transfer targets the current session; review is required.\");\n keys.set(key, relative);\n }\n}\n\nasync function assertReviewedTree(directory: string, relative: string, beforeHashes: Readonly<Record<string, string>>) {\n for (const name of await fs.readdir(directory)) {\n const child = path.join(directory, name);\n const childRelative = `${relative}/${name}`;\n const stat = await fs.lstat(child);\n if (stat.isDirectory()) {\n await assertReviewedTree(child, childRelative, beforeHashes);\n } else if (\n stat.isFile() &&\n stat.nlink === 1 &&\n beforeHashes[childRelative] ===\n createHash(\"sha256\")\n .update(await fs.readFile(child))\n .digest(\"hex\")\n ) {\n continue;\n } else {\n throw new Error(\"Reviewed directory contains unknown or changed files; publication refused.\");\n }\n }\n}\n\nfunction hasBlockingFileAncestor(target: string, files: ReadonlySet<string>) {\n for (let parent = path.dirname(target); parent !== path.dirname(parent); parent = path.dirname(parent))\n if (files.has(parent)) return true;\n return false;\n}\n\nasync function resolvedTargetIdentity(target: string, options: SnapshotOptions) {\n // Resolve the nearest existing ancestor too: roots may alias even when a target is absent.\n let ancestor = target;\n while (true) {\n options.signal?.throwIfAborted();\n try {\n const resolved = await fs.realpath(ancestor);\n return path.resolve(resolved, path.relative(ancestor, target));\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") throw error;\n const parent = path.dirname(ancestor);\n if (parent === ancestor) return target;\n ancestor = parent;\n }\n }\n}\n\nasync function assertFilesystemTarget(\n root: string,\n relative: string,\n options: SnapshotOptions,\n removedTargets: ReadonlySet<string> = new Set(),\n beforeHashes?: Readonly<Record<string, string>>,\n) {\n const target = snapshotTarget(root, relative, options.sessionDir);\n const boundary =\n relative.startsWith(\"sessions/\") && options.sessionDir\n ? path.resolve(sessionStorageRoot(root, options.sessionDir))\n : path.resolve(root);\n for (\n let parent = path.dirname(target);\n mergePathIdentity(parent) !== mergePathIdentity(boundary);\n parent = path.dirname(parent)\n ) {\n options.signal?.throwIfAborted();\n if (path.dirname(parent) === parent) throw new Error(\"Unowned merged target.\");\n try {\n const stat = await fs.lstat(parent);\n if (\n (!stat.isDirectory() || stat.isSymbolicLink()) &&\n !(stat.isFile() && stat.nlink === 1 && removedTargets.has(parent))\n )\n throw new Error(\"Unsafe merge filesystem layout; review the selected paths before transfer.\");\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") throw error;\n }\n }\n options.signal?.throwIfAborted();\n try {\n const stat = await fs.lstat(target);\n if ((!stat.isFile() && !removedTargets.has(target)) || (stat.isFile() && stat.nlink > 1))\n throw new Error(\"Merge target is non-regular or hard-linked; review a directional operation before transfer.\");\n if (stat.isDirectory() && beforeHashes) await assertReviewedTree(target, relative, beforeHashes);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && !(code === \"ENOTDIR\" && removedTargets.size > 0)) throw error;\n }\n}\n\n/** Roll forward only while each target is still its reviewed preimage or committed postimage. */\nexport async function applyMergedSnapshot(\n before: Snapshot,\n after: Snapshot,\n protectedPaths: Set<string>,\n options: SnapshotOptions,\n validate: () => Promise<void>,\n protectedTarget?: string,\n) {\n const root = agentDir();\n const beforeHashes: Record<string, string> = Object.assign(Object.create(null), fileHashMap(before));\n const afterHashes: Record<string, string> = Object.assign(Object.create(null), fileHashMap(after));\n const paths = [...new Set([...Object.keys(beforeHashes), ...Object.keys(afterHashes)])].sort();\n const replacements = replacementPaths(\n new Set(paths.filter((item) => beforeHashes[item] && !afterHashes[item])),\n afterHashes,\n );\n const intermediateDirectories = [...replacements].filter((item) => !beforeHashes[item] && !afterHashes[item]);\n const changed = [\n ...new Set([...paths.filter((item) => beforeHashes[item] !== afterHashes[item]), ...intermediateDirectories]),\n ].sort();\n const protectedKeys = new Set([...protectedPaths].map(mergePathIdentity));\n if (changed.some((item) => protectedKeys.has(mergePathIdentity(item)))) {\n throw new Error(\"A merged transfer targets the current session; review is required.\");\n }\n // Exact file queues, not a directory pseudo-lock: Pi edit/write tools use these keys.\n const targets = changed.map((item) => snapshotTarget(root, item, options.sessionDir));\n const relativeByTarget = new Map(targets.map((target, index) => [target, changed[index]]));\n const targetSet = new Set(targets);\n await assertDistinctMergedTargets(\n root,\n paths,\n new Set(changed),\n options,\n protectedTarget,\n new Set(Object.keys(afterHashes)),\n );\n // Existing case aliases share Pi's non-reentrant realpath queue. Reserve the\n // missing destination separately only after deleting its reviewed preimage.\n const targetsByQueue = new Map<string, string[]>();\n const queueTargets: string[] = [];\n const deferredTargets: string[] = [];\n for (const target of targets) {\n let key = path.resolve(target);\n try {\n key = await fs.realpath(target);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") throw error;\n }\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n const aliases = targetsByQueue.get(key) ?? [];\n aliases.push(target);\n targetsByQueue.set(key, aliases);\n }\n for (const [key, aliases] of targetsByQueue) {\n queueTargets.push(key);\n if (aliases.length > 1) deferredTargets.push(...aliases.filter((target) => path.resolve(target) !== key));\n }\n async function acquire(index: number): Promise<void> {\n const target = queueTargets[index];\n if (target) return withFileMutationQueue(target, () => acquire(index + 1));\n await validate();\n await assertCanonicalMergedTargets(root, changed, options);\n await validate();\n const current = await createSnapshot(before.profile, options);\n const currentHashes: Record<string, string> = Object.assign(Object.create(null), fileHashMap(current));\n const blockingFiles = new Set(\n paths\n .filter(\n (relative) =>\n (beforeHashes[relative] && !afterHashes[relative]) ||\n (afterHashes[relative] && currentHashes[relative] === afterHashes[relative]),\n )\n .map((relative) => snapshotTarget(root, relative, options.sessionDir)),\n );\n for (const item of changed) {\n if (currentHashes[item] !== beforeHashes[item] && currentHashes[item] !== afterHashes[item]) {\n throw new Error(\n \"Local content changed during merged transfer; journal retained for review. No newer bytes were replaced.\",\n );\n }\n const target = snapshotTarget(root, item, options.sessionDir);\n try {\n const stat = await fs.lstat(target);\n if ((!stat.isFile() && !stat.isDirectory()) || (stat.isFile() && stat.nlink > 1))\n throw new Error(\"Merged transfer target is no longer an independent regular file.\");\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && !(code === \"ENOTDIR\" && hasBlockingFileAncestor(target, blockingFiles))) throw error;\n }\n }\n const plan = preflightSnapshotApply(root, after, current, options);\n plan.writes = plan.writes.filter((item) => targetSet.has(item.target));\n plan.deletes = plan.deletes.filter((target) => targetSet.has(target));\n await preflightSnapshotMutations(root, plan, options.sessionDir, options);\n const deletedTargets = new Set(plan.deletes);\n for (const relative of intermediateDirectories) {\n for (let parent = path.posix.dirname(relative); parent !== \".\"; parent = path.posix.dirname(parent)) {\n if (afterHashes[parent] && deletedTargets.has(snapshotTarget(root, parent, options.sessionDir))) {\n plan.deletes.push(snapshotTarget(root, relative, options.sessionDir));\n break;\n }\n }\n }\n // A parent must remain until every reviewed leaf and intermediate directory is gone.\n plan.deletes.sort(\n (left, right) => right.split(path.sep).length - left.split(path.sep).length || left.localeCompare(right),\n );\n const removed = replacementPaths(\n new Set(paths.filter((relative) => deletedTargets.has(snapshotTarget(root, relative, options.sessionDir)))),\n afterHashes,\n );\n const removedTargets = new Set([...removed].map((item) => snapshotTarget(root, item, options.sessionDir)));\n await assertCanonicalMergedTargets(root, changed, options);\n await validate();\n const revalidateTarget = async (target: string) => {\n await validate();\n const relative = relativeByTarget.get(target);\n if (!relative) throw new Error(\"Unowned merge target.\");\n await assertFilesystemTarget(root, relative, options, removedTargets, currentHashes);\n await validate();\n let hash: string | undefined;\n try {\n const stat = await fs.lstat(target);\n if (stat.isDirectory() && removed.has(relative)) {\n if ((await fs.readdir(target)).length)\n throw new Error(\"Reviewed directory has remaining contents; journal retained for review.\");\n } else {\n if (!stat.isFile() || stat.nlink > 1)\n throw new Error(\"Merged transfer target is no longer an independent regular file.\");\n hash = createHash(\"sha256\")\n .update(await fs.readFile(target))\n .digest(\"hex\");\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n if (hash !== beforeHashes[relative] && hash !== afterHashes[relative])\n throw new Error(\"Local content changed at the apply boundary; journal retained, newer bytes untouched.\");\n };\n for (const target of plan.deletes) {\n await revalidateTarget(target);\n try {\n const stat = await fs.lstat(target);\n await validate();\n if (stat.isDirectory())\n await fs.rmdir(target); // Only an empty, reviewed directory may be replaced.\n else await fs.rm(target, { force: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n await syncDirectory(path.dirname(target));\n }\n const requireAbsentDestinations = async () => {\n await validate();\n for (const target of deferredTargets) {\n try {\n await fs.lstat(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n continue;\n }\n throw new Error(\"Case replacement destination changed before queue reservation; journal retained for review.\");\n }\n await validate();\n };\n async function acquireDestinations(index: number): Promise<void> {\n const target = deferredTargets[index];\n if (target) return withFileMutationQueue(target, () => acquireDestinations(index + 1));\n // Writers registered after deletion must finish first; never accept their\n // bytes as our own, even if they match a recognizable pre/postimage.\n await requireAbsentDestinations();\n await writeTargets();\n }\n await requireAbsentDestinations();\n await acquireDestinations(0);\n async function writeTargets() {\n for (const item of plan.writes) {\n await validate();\n const relative = relativeByTarget.get(item.target);\n if (!relative) throw new Error(\"Unowned merge write target.\");\n await assertFilesystemTarget(root, relative, options, new Set());\n await fs.mkdir(path.dirname(item.target), { recursive: true });\n const temporary = path.join(path.dirname(item.target), `.pi-sync.json.${randomUUID()}.apply`);\n let mode = 0o600;\n try {\n mode = (await fs.stat(item.target)).mode & 0o777;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n try {\n const handle = await fs.open(temporary, \"wx\", mode);\n try {\n await handle.writeFile(item.content);\n await handle.sync();\n } finally {\n await handle.close();\n }\n await revalidateTarget(item.target);\n await fs.rename(temporary, item.target);\n await syncDirectory(path.dirname(item.target));\n } finally {\n await fs.rm(temporary, { force: true });\n }\n }\n await syncMutationParents(\n targets,\n [root, ...(options.sessionDir ? [sessionStorageRoot(root, options.sessionDir)] : [])],\n options,\n );\n await validate();\n }\n }\n await acquire(0);\n}\n", "import { createHash } from \"node:crypto\";\nimport type { Dirent, Stats } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { assertWithinRoot, isDeniedPath, isPathInside, parentPaths, safeJoin, toPosix } from \"../paths.js\";\nimport { syncDirectory } from \"../state/json-file.js\";\nimport { agentDir } from \"./session-paths.js\";\nimport {\n createSnapshot,\n isSessionFilePath,\n isSessionPath,\n sessionStorageRoot,\n snapshotIncludesSessions,\n snapshotTarget,\n} from \"./snapshot.js\";\nimport { applySnapshotTransaction, recoverPendingSnapshotTransactions } from \"./snapshot-transaction.js\";\nimport type { Snapshot, SnapshotApplyPlan, SnapshotOptions } from \"./snapshot-types.js\";\n\nfunction sha256(value: Buffer) {\n return createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction fileHashMap(snapshot: Snapshot) {\n return Object.fromEntries(snapshot.files.map((file) => [file.path, file.sha256]));\n}\n\nexport async function applySnapshot(\n snapshot: Snapshot,\n protectedRelativePaths = new Set<string>(),\n options: Pick<\n SnapshotOptions,\n | \"include\"\n | \"sessionDir\"\n | \"syncFiles\"\n | \"syncSessions\"\n | \"extraFiles\"\n | \"signal\"\n | \"validateMutation\"\n | \"expectedFileHashes\"\n > = {},\n) {\n const root = agentDir();\n const { sessionDir } = options;\n const transactionOptions = {\n sessionDir,\n signal: options.signal,\n validateMutation: options.validateMutation,\n protectedTargets: [...protectedRelativePaths].map((relative) => snapshotTarget(root, relative, sessionDir)),\n expectedPreimages: new Map(\n Object.entries(options.expectedFileHashes ?? {}).map(([relative, hash]) => [\n snapshotTarget(root, relative, sessionDir),\n hash === null ? \"missing\" : `file:${hash}`,\n ]),\n ),\n };\n options.validateMutation?.();\n await recoverPendingSnapshotTransactions(transactionOptions);\n const current = await createSnapshot(snapshot.profile, {\n ...options,\n ...(options.include === undefined ? { syncSessions: snapshotIncludesSessions(snapshot) } : {}),\n sessionDir,\n });\n const plan = await addTopLevelCaseVariantDeletes(\n root,\n protectSnapshotApplyPlan(\n root,\n preflightSnapshotApply(root, snapshot, current, { sessionDir }),\n protectedRelativePaths,\n sessionDir,\n ),\n snapshot,\n );\n await preflightSnapshotMutations(root, plan, sessionDir, options);\n await applySnapshotTransaction(plan, transactionOptions);\n return appliedFileHashMap(snapshot, current, protectedRelativePaths);\n}\n\nexport function preflightSnapshotApply(\n root: string,\n snapshot: Snapshot,\n current: Snapshot,\n options: { sessionDir?: string } = {},\n): SnapshotApplyPlan {\n const seenPaths = new Set<string>();\n const remotePaths = new Set<string>();\n const writes: Array<{ target: string; content: Buffer }> = [];\n const deletes: string[] = [];\n\n for (const file of snapshot.files) {\n const normalized = toPosix(file.path);\n if (!isSafeSnapshotPath(file.path)) {\n throw new Error(`Unsafe path in snapshot: ${file.path}`);\n }\n if (isSessionPath(normalized) && !isSessionFilePath(normalized)) {\n throw new Error(`Unsafe session path in snapshot: ${file.path}`);\n }\n if (seenPaths.has(normalized)) throw new Error(`Duplicate path in snapshot: ${normalized}`);\n seenPaths.add(normalized);\n remotePaths.add(normalized);\n\n const target = snapshotTarget(root, normalized, options.sessionDir);\n const content = decodeBase64Strict(file.contentBase64, normalized);\n if (sha256(content) !== file.sha256) throw new Error(`Checksum mismatch in snapshot file: ${normalized}`);\n writes.push({ target, content });\n }\n\n const deletePaths = new Set<string>();\n for (const file of current.files) {\n const normalized = toPosix(file.path);\n if (!remotePaths.has(normalized)) {\n deletePaths.add(snapshotTarget(root, normalized, options.sessionDir));\n }\n for (const remotePath of parentPaths(normalized)) {\n if (remotePaths.has(remotePath)) {\n deletePaths.add(snapshotTarget(root, remotePath, options.sessionDir));\n }\n }\n }\n deletes.push(...deletePaths);\n\n return { writes, deletes };\n}\n\nexport function protectSnapshotApplyPlan(\n root: string,\n plan: SnapshotApplyPlan,\n protectedRelativePaths: Set<string>,\n sessionDir?: string,\n): SnapshotApplyPlan {\n if (protectedRelativePaths.size === 0) return plan;\n const protectedTargets = new Set(\n [...protectedRelativePaths].map((relativePath) => snapshotTarget(root, relativePath, sessionDir)),\n );\n return {\n writes: plan.writes.filter((item) => !protectedTargets.has(item.target)),\n deletes: plan.deletes.filter((target) => !protectedTargets.has(target)),\n };\n}\n\nexport async function addTopLevelCaseVariantDeletes(\n root: string,\n plan: SnapshotApplyPlan,\n snapshot: Pick<Snapshot, \"files\">,\n): Promise<SnapshotApplyPlan> {\n const topLevelPaths = new Map<string, string>();\n for (const file of snapshot.files) {\n const normalized = toPosix(file.path);\n if (!normalized.includes(\"/\") && isSafeSnapshotPath(file.path)) {\n topLevelPaths.set(normalized.toLowerCase(), normalized);\n }\n }\n if (topLevelPaths.size === 0) return plan;\n\n let entries: Dirent[];\n try {\n entries = await fs.readdir(root, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return plan;\n throw error;\n }\n\n const deletes = new Set(plan.deletes);\n for (const entry of entries) {\n const canonicalPath = topLevelPaths.get(entry.name.toLowerCase());\n if (canonicalPath && entry.name !== canonicalPath && (entry.isFile() || entry.isSymbolicLink())) {\n deletes.add(safeJoin(root, entry.name));\n }\n }\n return { ...plan, deletes: [...deletes] };\n}\n\nexport function appliedFileHashMap(snapshot: Snapshot, current: Snapshot, protectedRelativePaths: Set<string>) {\n const hashes = fileHashMap(snapshot);\n if (protectedRelativePaths.size === 0) return hashes;\n const currentHashes = fileHashMap(current);\n for (const relativePath of protectedRelativePaths) {\n const normalized = toPosix(relativePath);\n if (currentHashes[normalized]) {\n hashes[normalized] = currentHashes[normalized];\n } else {\n delete hashes[normalized];\n }\n }\n return hashes;\n}\n\nfunction isSafeSnapshotPath(relativePath: string) {\n if (relativePath.includes(\"\\\\\")) return false;\n const normalized = toPosix(relativePath);\n return (\n Boolean(normalized) &&\n normalized !== \".\" &&\n normalized !== \"..\" &&\n !normalized.startsWith(\"../\") &&\n !path.posix.isAbsolute(normalized) &&\n path.posix.normalize(normalized) === normalized &&\n !isDeniedPath(normalized)\n );\n}\n\nfunction decodeBase64Strict(value: string, filePath: string) {\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value) || value.length % 4 !== 0) {\n throw new Error(`Invalid base64 content in snapshot file: ${filePath}`);\n }\n return Buffer.from(value, \"base64\");\n}\n\ntype MutationGuards = Pick<SnapshotOptions, \"signal\" | \"validateMutation\">;\n\nexport async function preflightSnapshotMutations(\n root: string,\n plan: { deletes: string[]; writes: Array<{ target: string; content: Buffer }> },\n sessionDir?: string,\n options: MutationGuards = {},\n) {\n assertMutationCurrent(options);\n const deletePaths = new Set(plan.deletes);\n for (const target of plan.deletes) {\n await assertNoSymlinkParents(rootForTarget(root, target, sessionDir), target, options);\n assertMutationCurrent(options);\n }\n for (const item of plan.writes) {\n await prepareSnapshotWrite(rootForTarget(root, item.target, sessionDir), item.target, deletePaths, options);\n assertMutationCurrent(options);\n }\n}\n\nfunction assertMutationCurrent(options: MutationGuards) {\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n}\n\nasync function guardedStat(target: string, options: MutationGuards) {\n assertMutationCurrent(options);\n let stat: Stats;\n try {\n stat = await fs.lstat(target);\n } catch (error) {\n assertMutationCurrent(options);\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n assertMutationCurrent(options);\n return stat;\n}\n\nfunction rootForTarget(root: string, target: string, sessionDir?: string) {\n const sessionRoot = sessionDir ? sessionStorageRoot(root, sessionDir) : undefined;\n if (sessionRoot && isPathInside(sessionRoot, target)) return sessionRoot;\n return root;\n}\n\nasync function prepareSnapshotWrite(root: string, target: string, deletePaths: Set<string>, options: MutationGuards) {\n const parentWillBeReplaced = await ensureSafeDirectory(root, path.dirname(target), deletePaths, options);\n assertMutationCurrent(options);\n if (parentWillBeReplaced) return;\n const stat = await guardedStat(target, options);\n assertMutationCurrent(options);\n if (stat?.isSymbolicLink()) throw new Error(`Refusing to overwrite symlink during snapshot apply: ${target}`);\n if (stat?.isDirectory() && !deletePaths.has(target)) {\n throw new Error(`Refusing to overwrite directory during snapshot apply: ${target}`);\n }\n}\n\nasync function ensureSafeDirectory(root: string, directory: string, deletePaths: Set<string>, options: MutationGuards) {\n assertMutationCurrent(options);\n assertWithinRoot(root, directory);\n const rootPath = path.resolve(root);\n const relative = path.relative(rootPath, path.resolve(directory));\n let current = rootPath;\n for (const part of relative.split(path.sep).filter(Boolean)) {\n current = path.join(current, part);\n const stat = await guardedStat(current, options);\n assertMutationCurrent(options);\n if (stat) {\n if (stat.isSymbolicLink()) throw new Error(`Refusing to follow symlink during snapshot apply: ${current}`);\n if (!stat.isDirectory()) {\n if (deletePaths.has(current)) return true;\n throw new Error(`Snapshot path parent is not a directory: ${current}`);\n }\n } else {\n await fs.mkdir(current);\n assertMutationCurrent(options);\n await syncDirectory(path.dirname(current));\n assertMutationCurrent(options);\n }\n }\n return false;\n}\n\nasync function assertNoSymlinkParents(root: string, target: string, options: MutationGuards) {\n assertMutationCurrent(options);\n assertWithinRoot(root, target);\n const rootPath = path.resolve(root);\n const relative = path.relative(rootPath, path.resolve(target));\n let current = rootPath;\n const parts = relative.split(path.sep).filter(Boolean);\n for (const part of parts.slice(0, -1)) {\n current = path.join(current, part);\n const stat = await guardedStat(current, options);\n assertMutationCurrent(options);\n if (!stat) return;\n if (stat.isSymbolicLink()) throw new Error(`Refusing to follow symlink during snapshot apply: ${current}`);\n if (!stat.isDirectory()) throw new Error(`Snapshot path parent is not a directory: ${current}`);\n }\n}\n", "import type { RemoteHead } from \"../backends/sync-backend.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot, SnapshotFile } from \"../snapshot/snapshot-types.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport type { FileMergeDecision } from \"./file-merge-planner.js\";\nimport { fileHashMap } from \"./sync-state.js\";\n/** Withholding preserves the complete local version, including explicit absence. */\nexport function acceptedMergeFiles(\n decisions: readonly FileMergeDecision[],\n localFiles: readonly SnapshotFile[],\n withheld: ReadonlySet<string>,\n) {\n const localByPath = new Map(localFiles.map((file) => [file.path, file]));\n return decisions.flatMap((decision) => {\n const file = withheld.has(decision.path)\n ? localByPath.get(decision.path)\n : decision.kind === \"accepted\"\n ? decision.file\n : undefined;\n return file ? [file] : [];\n });\n}\n\nexport interface PartialProgress {\n previous: SyncState;\n groups: { paths: string[]; artifact: string }[];\n}\nexport function progressState(\n config: AnySyncConfig,\n head: RemoteHead,\n snapshot: Snapshot,\n progress: PartialProgress,\n): SyncState {\n const withheld = new Set(progress.groups.flatMap((group) => group.paths));\n const current = fileHashMap(snapshot);\n const hashes = Object.assign(Object.create(null) as Record<string, string>, progress.previous.lastFileHashes);\n for (const key of new Set([...Object.keys(hashes), ...Object.keys(current)])) {\n if (withheld.has(key)) continue;\n const value = current[key];\n if (value === undefined) delete hashes[key];\n else hashes[key] = value;\n }\n return {\n ...progress.previous,\n version: 3,\n profile: config.snapshotIdentity,\n lastFileHashes: hashes,\n include: [...config.include],\n localFields: config.localFields,\n lastObservedSnapshot: head.snapshotId,\n lastObservedRevision: head.revision,\n unresolved: progress.groups,\n };\n}\n", "import { createHash } from \"node:crypto\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { readMergeAncestor } from \"../state/merge-baseline-store.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport type { FileMergePlan } from \"./file-merge-planner.js\";\nimport { mergeSettingsJson } from \"./settings-merge.js\";\n\nexport async function resolveSettingsConflicts(\n config: AnySyncConfig,\n state: SyncState,\n local: Snapshot,\n remote: Snapshot,\n plan: FileMergePlan,\n): Promise<{ plan: FileMergePlan; fields: string[] }> {\n if (plan.kind !== \"planned\") return { plan, fields: [] };\n const fields: string[] = [];\n const decisions = [...plan.decisions];\n for (let index = 0; index < decisions.length; index++) {\n const decision = decisions[index];\n if (decision?.kind !== \"conflict\" || decision.reason !== \"both-changed\" || decision.path !== \"settings.json\")\n continue;\n const left = local.files.find((file) => file.path === decision.path);\n const right = remote.files.find((file) => file.path === decision.path);\n if (!left || !right) continue; // File deletion/addition is not a JSON field merge.\n const ancestor = await readMergeAncestor(config, state, decision.path);\n if (!ancestor) continue;\n const merged = mergeSettingsJson(\n ancestor,\n Buffer.from(left.contentBase64, \"base64\"),\n Buffer.from(right.contentBase64, \"base64\"),\n );\n if (merged.kind === \"review\") {\n fields.push(...merged.fields);\n continue;\n }\n decisions[index] = {\n kind: \"accepted\",\n path: decision.path,\n source: \"merged\",\n file: {\n path: decision.path,\n contentBase64: merged.content.toString(\"base64\"),\n sha256: createHash(\"sha256\").update(merged.content).digest(\"hex\"),\n },\n };\n }\n return {\n plan: { kind: \"planned\", decisions, conflicts: decisions.filter((decision) => decision.kind === \"conflict\") },\n fields,\n };\n}\n", "import {\n type JsonDocument,\n type JsonNode,\n jsonEqual,\n parseSettingsDocument,\n renderSettingsMembers,\n} from \"./json-document.js\";\n\nexport type SettingsMergeResult =\n | { kind: \"merged\"; content: Buffer }\n | { kind: \"review\"; reason: \"unsupported-format\" | \"field-conflict\"; fields: string[] };\n\nconst COUPLED_FIELDS = [\n [\"defaultProvider\", \"defaultModel\"],\n [\"queueMode\", \"steeringMode\"],\n [\"websockets\", \"transport\"],\n [\"skills\", \"enableSkillCommands\"],\n [\"enableAnalytics\", \"trackingId\"],\n] as const;\n\n/** Only global settings.json; objects/arrays are atomic units until their invariants are proven. */\nexport function mergeSettingsJson(ancestor: Buffer, local: Buffer, remote: Buffer): SettingsMergeResult {\n let documents: JsonDocument[];\n try {\n documents = [ancestor, local, remote].map(parseSettingsDocument);\n } catch {\n return { kind: \"review\", reason: \"unsupported-format\", fields: [] };\n }\n const [base, left, right] = documents as [JsonDocument, JsonDocument, JsonDocument];\n const selected = new Map<string, { document: JsonDocument; node: JsonNode }>();\n const fields = new Set(documents.flatMap((document) => [...document.root.members.keys()]));\n const units: string[][] = COUPLED_FIELDS.map((group) => [...group]);\n const coupled = new Set(units.flat());\n units.push(...[...fields].filter((field) => !coupled.has(field)).map((field) => [field]));\n const conflicts: string[] = [];\n for (const unit of units) {\n const equal = (first: JsonDocument, second: JsonDocument) =>\n unit.every((field) =>\n jsonEqual(first.root.members.get(field)?.node.value, second.root.members.get(field)?.node.value),\n );\n const source = equal(left, right) ? left : equal(left, base) ? right : equal(right, base) ? left : undefined;\n if (!source) {\n conflicts.push(...unit.filter((field) => fields.has(field)));\n continue;\n }\n for (const field of unit) {\n const member = source.root.members.get(field);\n if (member) selected.set(field, { document: source, node: member.node });\n }\n }\n if (conflicts.length) return { kind: \"review\", reason: \"field-conflict\", fields: conflicts };\n try {\n return { kind: \"merged\", content: renderSettingsMembers(left, selected) };\n } catch {\n return { kind: \"review\", reason: \"unsupported-format\", fields: [] };\n }\n}\n", "import { syncConfigReviewIdentity } from \"../settings/config.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { formatDiff, formatSnapshotOnlyDiff } from \"../ui/sync-format.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { SyncDecisionRequiredError } from \"./sync-errors.js\";\nimport { includeFromSelectionConfig } from \"./sync-policy.js\";\nimport { syncPolicyChanged } from \"./sync-state.js\";\n\nexport type SyncDecisionKind =\n | \"remote-or-policy-changed\"\n | \"both-changed\"\n | \"first-sync-settings-diverged\"\n | \"first-sync-sessions-diverged\"\n | \"remote-empty\";\n\nexport type SyncResolutionDirection = \"push\" | \"pull\";\n\nexport interface SyncDecision {\n kind: SyncDecisionKind;\n setupName: string;\n configIdentity: string;\n causes: {\n localChanged: boolean;\n remoteChanged: boolean;\n policyChanged: boolean;\n };\n previousInclude?: readonly string[];\n currentInclude: readonly string[];\n review: string;\n directions: readonly SyncResolutionDirection[];\n directMessage: string;\n}\n\nexport {\n isSyncDecisionRequiredError,\n SyncDecisionRequiredError,\n} from \"./sync-errors.js\";\n\ninterface CreateSyncDecisionOptions {\n kind: SyncDecisionKind;\n config: AnySyncConfig;\n state: SyncState;\n local: Snapshot;\n remote?: Snapshot;\n localChanged: boolean;\n remoteChanged: boolean;\n directMessage: string;\n}\n\nexport function createSyncDecision(options: CreateSyncDecisionOptions) {\n const { config, state, local, remote, kind } = options;\n const policyChanged = Boolean(state.lastAppliedSnapshot) && syncPolicyChanged(state, config);\n const previousInclude = includeFromSelectionConfig(state);\n const currentInclude = [...config.include];\n const causes = {\n localChanged: options.localChanged,\n remoteChanged: options.remoteChanged,\n policyChanged,\n };\n const causeLines =\n kind === \"first-sync-settings-diverged\"\n ? [\"This machine and the remote have different Pi settings on first sync.\"]\n : kind === \"first-sync-sessions-diverged\"\n ? [\"Pi settings match, but local and remote sessions differ on first sync.\"]\n : kind === \"remote-empty\"\n ? [\"The remote storage location is empty.\"]\n : [\n ...(causes.localChanged ? [\"Local content changed since the last sync.\"] : []),\n ...(causes.remoteChanged ? [\"Remote content changed since the last sync.\"] : []),\n ...(causes.policyChanged ? [\"Included content changed since the last sync.\"] : []),\n ];\n const comparison = remote\n ? formatDiff(local, remote)\n : formatSnapshotOnlyDiff(\"Remote is empty. Local push would upload\", local);\n const review = [\n `Sync setup: ${safeTerminalText(config.setupName)}`,\n \"\",\n \"Why a decision is required:\",\n ...causeLines,\n ...(policyChanged\n ? [\"\", `Previously included: ${safeList(previousInclude)}`, `Currently included: ${safeList(currentInclude)}`]\n : []),\n \"\",\n \"Observed differences:\",\n ...comparison.split(\"\\n\").map(safeTerminalText),\n ].join(\"\\n\");\n return new SyncDecisionRequiredError({\n kind,\n setupName: config.setupName,\n configIdentity: syncConfigReviewIdentity(config),\n causes,\n ...(policyChanged ? { previousInclude: [...previousInclude] } : {}),\n currentInclude,\n review,\n directions: kind === \"remote-empty\" ? [\"push\"] : [\"push\", \"pull\"],\n directMessage: options.directMessage,\n });\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n", "import type { ExtensionCommandContext, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport {\n expectedRemoteHead,\n type RemoteHead,\n type SyncBackend,\n SyncBackendConflictError,\n} from \"../backends/sync-backend.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncCheckConfigFingerprint } from \"../settings/config.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport {\n effectiveSessionRoot,\n requireStableMergeSessionRoot,\n snapshotOptionsForContext,\n} from \"../snapshot/session-paths.js\";\nimport {\n createSnapshot,\n filterSnapshotForConfigPolicy,\n mergeRemotePreservedFiles,\n regenerateSnapshotIdentity,\n scanSnapshot,\n} from \"../snapshot/snapshot.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { pruneMergeBaselines, readMergeAncestors, stageMergeBaseline } from \"../state/merge-baseline-store.js\";\nimport {\n readStateForConfig,\n statePathForConfig,\n syncStateFingerprint,\n writeStateForConfig,\n} from \"../state/sync-state-store.js\";\nimport { confirmMergeReview } from \"../ui/merge-review.js\";\nimport { formatApplyPreview, formatPublicationPreview } from \"../ui/sync-format.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { releaseConflictArtifacts } from \"./conflict-artifact-ownership.js\";\nimport {\n type CreatedConflictArtifact,\n conflictGroups,\n readConflictArtifact,\n saveConflictArtifact,\n} from \"./conflict-artifacts.js\";\nimport { type ConflictResolution, resolveReviewedGroup } from \"./conflict-resolution.js\";\nimport { pruneCompletedConflicts } from \"./conflict-retention.js\";\nimport { resolveContentConflicts } from \"./content-conflicts.js\";\nimport { planFileMerge } from \"./file-merge-planner.js\";\nimport { overlayLocalFields, portableSnapshot, sameLocalFields } from \"./local-fields.js\";\nimport { applyMergedSnapshot, preflightMergedTargets } from \"./merge-apply.js\";\nimport {\n clearMergeJournal,\n type MergeJournal,\n mergeJournalIdentity,\n readMergeJournal,\n writeMergeJournal,\n} from \"./merge-journal.js\";\nimport { acceptedMergeFiles, type PartialProgress, progressState } from \"./partial-progress.js\";\nimport {\n formatRemoteSelectionStatus,\n readSnapshotForHead,\n requireCompatibleRemoteSelection,\n} from \"./remote-snapshot.js\";\nimport { resolveSettingsConflicts } from \"./settings-conflicts.js\";\nimport { createSyncDecision } from \"./sync-decision.js\";\nimport { backupLocal, captureMutationOwner, protectedSessionPaths } from \"./sync-local.js\";\nimport { inspectRemoteSelection } from \"./sync-policy.js\";\nimport { fileHashMap, hasLocalChanges, hasRemoteChanges, sameHashes, syncPolicyChanged } from \"./sync-state.js\";\nimport { TEXT_MERGE_WORK_LIMIT } from \"./text-merge.js\";\n\nconst MAX_ATTEMPTS = 3;\n\n/** Established-baseline sync only. First-source selection remains in the existing command flow. */\nexport async function mergeSync(\n ctx: ExtensionContext | ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n resolution?: ConflictResolution,\n) {\n const validateOwner = captureMutationOwner(ctx, options.signal);\n const isCurrent = () => {\n try {\n validateOwner();\n return true;\n } catch {\n return false;\n }\n };\n const config = await loadConfig(options.setup);\n const configToken = syncCheckConfigFingerprint(config);\n const sessionRoot = config.include.includes(\"sessions\") ? await effectiveSessionRoot(ctx) : undefined;\n validateOwner();\n const snapshotOptions = {\n ...snapshotOptionsForContext(ctx, config),\n sessionDir: sessionRoot,\n signal: options.signal,\n };\n const validate = async () => {\n validateOwner();\n const latest = await loadConfig(options.setup);\n validateOwner();\n if (configToken !== syncCheckConfigFingerprint(latest))\n throw new Error(\"Sync setup or settings changed during transfer; reopen sync.\");\n if (sessionRoot !== undefined) {\n const currentRoot = await effectiveSessionRoot(ctx);\n validateOwner();\n if (currentRoot !== sessionRoot)\n throw new Error(\"Session storage root changed during transfer; evidence retained for review.\");\n }\n if (options.auto && (!latest.automaticTransfer || !ctx.isIdle()))\n throw new Error(\"Automatic transfer is no longer authorized at this idle boundary.\");\n };\n await validate();\n const backend = await factory(config);\n await validate();\n if (options.auto && backend.capability === \"read-check-write-verify\") {\n throw new Error(\n \"Automatic transfer requires conditional publication or a lease; this backend supports only read/check/write/verify. Use manual sync.\",\n );\n }\n const pending = await readMergeJournal(config);\n await validate();\n if (pending) {\n const recovered = await completeJournal(ctx, config, backend, pending, validate, options.signal, options.auto);\n if (!recovered) {\n if ((options.auto || !options.silent) && !options.signal?.aborted)\n ctx.ui.notify(\n \"Interrupted candidate is not active; local content and baseline were unchanged. Evidence was reconciled without retrying publication. Run sync again for a fresh plan.\",\n \"warning\",\n );\n return \"cancelled\" as const;\n }\n if ((options.auto || !options.silent) && !options.signal?.aborted)\n ctx.ui.notify(\"Recovered the committed merged transfer. Run sync again to inspect newer changes.\", \"info\");\n return \"applied\" as const;\n }\n const textBudget = { remaining: TEXT_MERGE_WORK_LIMIT };\n const createdArtifacts: CreatedConflictArtifact[] = [];\n const ownedStatePath = statePathForConfig(config);\n try {\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n await validate();\n const state = await readStateForConfig(config);\n if (state.unresolved?.length && !config.partialSync)\n throw new Error(\n \"Partial progress remains unresolved; re-enable partial sync or review an explicit force direction.\",\n );\n const localRaw = await createSnapshot(config.snapshotIdentity, snapshotOptions);\n const local = portableSnapshot(localRaw, config.localFields);\n if (!sameLocalFields(state.localFields, config.localFields))\n throw new Error(\"Local-field rules changed; review and confirm a directional migration first.\");\n const head = await backend.readHead(options.signal);\n await validate();\n const rawRemote = head ? await readSnapshotForHead(backend, head, options.signal) : undefined;\n await validate();\n if (rawRemote) {\n const files = [...local.files, ...rawRemote.files];\n if (\n files.length > 16_384 ||\n files.reduce((bytes, file) => bytes + file.contentBase64.length * 0.75, 0) > 64 * 1024 * 1024\n ) {\n throw new Error(\n \"Merged transfer exceeds the 64 MiB / 16,384 input-file bound; review an explicit push or pull instead.\",\n );\n }\n }\n const remote = rawRemote\n ? portableSnapshot(filterSnapshotForConfigPolicy(rawRemote, config), rawRemote.localFields)\n : undefined;\n if (rawRemote) {\n requireCompatibleRemoteSelection(config, rawRemote);\n const validation = planFileMerge({\n baseline: state.lastFileHashes,\n local: local.files,\n remote: rawRemote.files,\n selectionCompatible: true,\n });\n const managedPaths = new Set([\n ...Object.keys(state.lastFileHashes),\n ...[...local.files, ...(remote?.files ?? [])].map((file) => file.path),\n ]);\n if (\n validation.kind === \"planned\" &&\n validation.conflicts.some(\n (item) => item.reason === \"path-collision\" && (!config.partialSync || !managedPaths.has(item.path)),\n )\n )\n throw new Error(\"Remote snapshot contains path collisions; review a directional recovery before merging.\");\n }\n const review = (\n message: string,\n kind: \"both-changed\" | \"remote-empty\" | \"remote-or-policy-changed\" = \"both-changed\",\n ) =>\n createSyncDecision({\n kind,\n config,\n state,\n local,\n remote,\n localChanged: hasLocalChanges(local, state, config),\n remoteChanged: remote ? hasRemoteChanges(remote, state, config) : Boolean(state.lastAppliedSnapshot),\n directMessage: message,\n });\n if (!state.lastAppliedSnapshot) throw review(\"Choose the initial source before enabling automatic transfer.\");\n if (syncPolicyChanged(state, config))\n throw review(\"Included content changed; review the selection before merging.\", \"remote-or-policy-changed\");\n if (!head || !remote || !rawRemote)\n throw review(\"The established remote is missing; choose an explicit recovery direction.\", \"remote-empty\");\n const selectionState = inspectRemoteSelection(config.include, rawRemote);\n const selectionCompatible = selectionState.kind === \"same\";\n let plan = planFileMerge({\n baseline: state.lastFileHashes,\n local: local.files,\n remote: remote.files,\n selectionCompatible,\n protectedPaths: protectedSessionPaths(ctx, sessionRoot),\n });\n let resolved = { plan, fields: [] as string[] };\n if (config.mergeSettings) {\n try {\n resolved = await resolveSettingsConflicts(config, state, local, remote, plan);\n } catch (error) {\n if (!config.partialSync) throw error;\n }\n }\n await validate();\n plan = await resolveContentConflicts(\n config,\n state,\n local,\n remote,\n resolved.plan,\n protectedSessionPaths(ctx, sessionRoot),\n { textBudget, signal: options.signal },\n );\n await validate();\n if (resolution) {\n plan = await resolveReviewedGroup(\n config,\n backend,\n state,\n local,\n remote,\n head,\n plan,\n resolution,\n protectedSessionPaths(ctx, sessionRoot),\n );\n await validate();\n }\n if (plan.kind !== \"planned\" || (plan.conflicts.length && (!config.partialSync || options.auto))) {\n const decision = review(\n selectionCompatible\n ? `Conflicting or protected paths require review; no merged transfer was performed. Use /sync diff and an explicit direction.${resolved.fields.length ? ` Settings fields: ${resolved.fields.map(safeTerminalText).join(\", \")}` : \"\"}`\n : \"Remote selection metadata is unavailable; review the included content and choose an explicit direction before merging.\",\n selectionCompatible ? \"both-changed\" : \"remote-or-policy-changed\",\n );\n if (!selectionCompatible)\n decision.decision.review += `\\n\\n${formatRemoteSelectionStatus(selectionState)}\\nAn explicit direction adopts this setup's included-content policy; no automatic merge was performed.`;\n throw decision;\n }\n if (plan.kind !== \"planned\") throw new Error(\"Cannot partition an unverified merge plan.\");\n const groups = conflictGroups(plan, config);\n const withheld = new Set(groups.flatMap((group) => group.paths));\n // Transfer plans defer artifact writes until approved review and freshness guards pass.\n // A no-transfer manual inspection can persist referenced conflict state directly.\n const persistProgress = async (): Promise<PartialProgress | undefined> => {\n if (!groups.length) return;\n let ancestors: import(\"../snapshot/snapshot-types.js\").SnapshotFile[] = [];\n try {\n ancestors = ((await readMergeAncestors(config, state)) ?? []).filter((file) => withheld.has(file.path));\n } catch {\n /* Retain unknown evidence; absence remains explicit. */\n }\n await validate();\n const previousArtifacts = new Map<\n string,\n {\n artifact: Awaited<ReturnType<typeof readConflictArtifact>>;\n local: ReturnType<typeof fileHashMap>;\n remote: ReturnType<typeof fileHashMap>;\n }\n >();\n for (const token of new Set(state.unresolved?.map((group) => group.artifact) ?? [])) {\n try {\n const artifact = await readConflictArtifact(config, backend.identity, token);\n previousArtifacts.set(token, {\n artifact,\n local: fileHashMap(artifact.local),\n remote: fileHashMap(artifact.remote),\n });\n } catch {\n /* Unknown evidence retained, never reused. */\n }\n await validate();\n }\n const localHashes = fileHashMap(local);\n const remoteHashes = fileHashMap(remote);\n const previousGroups = new Map(state.unresolved?.map((item) => [JSON.stringify(item.paths), item]));\n const pending = groups.map((group) => {\n const previous = previousGroups.get(JSON.stringify(group.paths));\n const original = previous ? previousArtifacts.get(previous.artifact) : undefined;\n if (!original || !previous) return { group };\n return group.paths.every(\n (filePath) =>\n localHashes[filePath] === original.local[filePath] &&\n remoteHashes[filePath] === original.remote[filePath] &&\n state.lastFileHashes[filePath] === original.artifact.state.lastFileHashes[filePath],\n )\n ? { group, artifact: previous.artifact }\n : { group };\n });\n let artifact: string | undefined;\n const newGroups = pending.filter((item) => !item.artifact).map((item) => item.group);\n const newPaths = new Set(newGroups.flatMap((group) => group.paths));\n if (newGroups.length)\n artifact = await saveConflictArtifact(\n config,\n backend.identity,\n {\n state,\n local: { ...local, files: local.files.filter((file) => newPaths.has(file.path)) },\n remote: { ...remote, files: remote.files.filter((file) => newPaths.has(file.path)) },\n ancestors: ancestors.filter((file) => newPaths.has(file.path)),\n groups: newGroups,\n observed: { snapshotId: head.snapshotId, revision: head.revision },\n },\n captureMutationOwner(ctx, options.signal),\n (created) => createdArtifacts.push(created),\n );\n await validate();\n return {\n previous: state,\n groups: pending.map((item) => ({ paths: item.group.paths, artifact: item.artifact ?? artifact ?? \"\" })),\n };\n };\n let progress: PartialProgress | undefined;\n const accepted = regenerateSnapshotIdentity({\n ...local,\n files: acceptedMergeFiles(plan.decisions, local.files, withheld),\n });\n const after = overlayLocalFields(accepted, localRaw, config.localFields);\n if (config.include.includes(\"sessions\")) requireStableMergeSessionRoot(localRaw, after);\n const publication = regenerateSnapshotIdentity({\n ...accepted,\n version: config.partialSync ? 3 : accepted.version,\n files: [\n ...accepted.files.filter((file) => !withheld.has(file.path)),\n ...remote.files.filter((file) => withheld.has(file.path)),\n ],\n });\n const upload = mergeRemotePreservedFiles(publication, rawRemote, config);\n const publish =\n !sameHashes(fileHashMap(publication), fileHashMap(remote)) ||\n Boolean(config.partialSync && rawRemote.version !== 3);\n const apply = !sameHashes(fileHashMap(localRaw), fileHashMap(after));\n if (!publish && !apply) {\n const beforeEvidence = await backend.readHead(options.signal);\n await validate();\n if (!beforeEvidence || !backend.sameRevision(beforeEvidence.revision, head.revision))\n throw new Error(\"Remote changed before baseline acceptance; retry from a fresh observation.\");\n progress = await persistProgress();\n await validate();\n const currentLocal = await createSnapshot(config.snapshotIdentity, snapshotOptions);\n await validate();\n if (\n !sameHashes(fileHashMap(currentLocal), fileHashMap(localRaw)) ||\n syncStateFingerprint(await readStateForConfig(config)) !== syncStateFingerprint(state)\n )\n throw new Error(\n \"Local content or baseline changed before baseline acceptance; retry from a fresh observation.\",\n );\n await validate();\n const currentHead = await backend.readHead(options.signal);\n await validate();\n if (!currentHead || !backend.sameRevision(currentHead.revision, head.revision))\n throw new Error(\"Remote changed before baseline acceptance; retry from a fresh observation.\");\n await writeAcceptedState(config, head, accepted, validate, progress);\n await pruneMergeBaselines(\n config,\n acceptedState(config, head, accepted, progress),\n captureMutationOwner(ctx, options.signal),\n );\n await validate();\n await pruneCompletedConflicts(\n config,\n backend.identity,\n acceptedState(config, head, accepted, progress),\n accepted,\n remote,\n captureMutationOwner(ctx, options.signal),\n );\n await validate();\n if (!options.silent)\n ctx.ui.notify(\n progress\n ? `No independent transfer required; ${groups.length} conflict groups remain withheld. Review /sync conflicts.`\n : \"Pi Sync is already up to date.\",\n progress ? \"warning\" : \"info\",\n );\n return \"applied\" as const;\n }\n await preflightMergedTargets(localRaw, after, snapshotOptions, ctx.sessionManager.getSessionFile?.());\n await validate();\n if (!config.skipSecretScan && scanSnapshot(upload).length)\n throw new Error(\"Refusing to merge possible secrets. Review managed content before syncing.\");\n if (\n !options.yes &&\n !(await confirmMergeReview(\n ctx,\n \"Merge independent Pi changes?\",\n [\n `Sync setup: ${safeTerminalText(config.setupName)}`,\n `Storage location: ${safeTerminalText(backend.destination)}`,\n `Sessions: ${config.include.includes(\"sessions\") ? \"included \u2014 may contain private conversations\" : \"not included\"}`,\n `Local writes/deletions: ${plan.decisions.filter((item) => item.kind === \"accepted\" && (item.source === \"remote\" || item.source === \"merged\")).length}`,\n formatApplyPreview(localRaw, after).split(\"\\n\").map(safeTerminalText).join(\"\\n\"),\n `Unresolved dependency groups: ${groups.length} (withheld versions stay on each side; baselines do not advance)`,\n ...groups.flatMap((group) => group.paths.map((filePath) => `Withheld: ${safeTerminalText(filePath)}`)),\n `Remote publication: ${publish ? \"yes\" : \"no\"}`,\n formatPublicationPreview(rawRemote, upload).split(\"\\n\").map(safeTerminalText).join(\"\\n\"),\n `Backend publication: ${backend.capability}`,\n \"The current session is protected. A backup and recovery journal are retained. Resources are not reloaded.\",\n ].join(\"\\n\"),\n options.signal,\n isCurrent,\n ))\n )\n return \"cancelled\" as const;\n await validate();\n const refreshed = await createSnapshot(config.snapshotIdentity, snapshotOptions);\n if (!sameHashes(fileHashMap(refreshed), fileHashMap(localRaw)))\n throw new Error(\"Local content changed during review; no merged transfer was performed.\");\n if (syncStateFingerprint(await readStateForConfig(config)) !== syncStateFingerprint(state))\n throw new Error(\"Sync baseline changed during review; retry from a fresh observation.\");\n await validate();\n const refreshedHead = await backend.readHead(options.signal);\n await validate();\n if (!refreshedHead || !backend.sameRevision(refreshedHead.revision, head.revision))\n throw new Error(\"Remote changed during review; no merged transfer was performed.\");\n progress = await persistProgress();\n await validate();\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptions, options.signal);\n await validate();\n const journal: MergeJournal = {\n version: 1,\n identity: mergeJournalIdentity(config, backend.identity),\n before: localRaw,\n after,\n accepted,\n ...(progress ? { progress } : {}),\n upload: publish ? upload : rawRemote,\n expectedHead: head,\n backup,\n stateIdentity: syncStateFingerprint(state),\n ...(sessionRoot !== undefined ? { sessionRoot } : {}),\n ...(!publish ? { committedHead: head, applyOnly: true } : {}),\n };\n await writeMergeJournal(config, journal);\n // No backend call has begun: a stale candidate can be retired without ambiguous publication.\n const atCommitState = syncStateFingerprint(await readStateForConfig(config));\n await validate();\n const atCommit = await createSnapshot(config.snapshotIdentity, snapshotOptions);\n await validate();\n if (!sameHashes(fileHashMap(atCommit), fileHashMap(localRaw)) || atCommitState !== journal.stateIdentity) {\n await validate();\n await clearMergeJournal(config);\n throw new Error(\n \"Local content or baseline changed before publication; candidate retired without transfer. Review a fresh sync.\",\n );\n }\n // Backup/journal awaits can also change physical identity without changing any bytes.\n try {\n await preflightMergedTargets(atCommit, after, snapshotOptions, ctx.sessionManager.getSessionFile?.());\n await validate();\n } catch (error) {\n await validate();\n await clearMergeJournal(config);\n throw error;\n }\n try {\n if (publish) {\n const result = await backend.publishSnapshot(upload, expectedRemoteHead(head), {\n signal: options.signal,\n onCommit: options.onCommit,\n });\n journal.committedHead = result.head;\n journal.warnings = result.warnings;\n await writeMergeJournal(config, journal);\n } else options.onCommit?.();\n } catch (error) {\n if (\n error instanceof SyncBackendConflictError &&\n error.phase === \"before-commit\" &&\n !error.candidateMayHaveBeenActive\n ) {\n await clearMergeJournal(config);\n if (attempt + 1 < MAX_ATTEMPTS) continue;\n throw new Error(\"Remote changed before commit in all three attempts; retry later.\", { cause: error });\n }\n // Cancellation before publication is safe only if no backend attempt began.\n // Every uncertain/after-commit outcome retains evidence and is never blindly retried.\n throw new Error(\n \"Merged transfer interrupted; journal and backup retained. Run /sync sync to reconcile before further mutations.\",\n { cause: error },\n );\n }\n const completed = await completeJournal(ctx, config, backend, journal, validate, options.signal, options.auto);\n if (!completed) {\n if (!options.signal?.aborted && (options.auto || !options.silent))\n ctx.ui.notify(\n \"Remote changed before local apply; candidate retired without transfer. Run sync again.\",\n \"warning\",\n );\n return \"cancelled\" as const;\n }\n if (!options.signal?.aborted && (options.auto || !options.silent))\n ctx.ui.notify(\n [\n `Synced independent changes for \u201C${safeTerminalText(config.setupName)}\u201D. ${apply ? \"Local files changed; reload or restart Pi when ready to use changed resources.\" : \"Remote updated.\"} No automatic reload.`,\n ...(progress\n ? [\n `Partial progress: ${groups.length} dependency groups remain unresolved; neither side's withheld versions or baseline hashes were replaced. Review /sync conflicts.`,\n ]\n : []),\n ...(journal.warnings ?? []).map(safeTerminalText),\n ].join(\"\\n\"),\n progress || journal.warnings?.length ? \"warning\" : \"info\",\n );\n return \"applied\" as const;\n }\n } finally {\n await releaseConflictArtifacts(config, ownedStatePath, createdArtifacts);\n }\n}\n\nasync function completeJournal(\n ctx: ExtensionContext | ExtensionCommandContext,\n config: AnySyncConfig,\n backend: SyncBackend,\n journal: MergeJournal,\n validate: () => Promise<void>,\n signal?: AbortSignal,\n auto = false,\n) {\n if (\n journal.identity !== mergeJournalIdentity(config, backend.identity) ||\n !sameLocalFields(journal.upload.localFields, config.localFields)\n )\n throw new Error(\n \"Merge journal belongs to a different setup, selection or local-field policy; preserve it for reviewed recovery.\",\n );\n await validate();\n const sessionRoot = config.include.includes(\"sessions\") ? await effectiveSessionRoot(ctx) : undefined;\n await validate();\n if (sessionRoot !== undefined && journal.sessionRoot !== sessionRoot) {\n throw new Error(\n \"Merge journal session root is missing or differs from this context; preserve evidence and use reviewed directional recovery.\",\n );\n }\n const snapshotOptions = { ...snapshotOptionsForContext(ctx, config), sessionDir: sessionRoot, signal };\n const head = await backend.readHead(signal);\n if (!journal.committedHead && head && backend.sameRevision(head.revision, journal.expectedHead.revision)) {\n await validate();\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptions);\n if (\n !sameHashes(fileHashMap(local), fileHashMap(journal.before)) ||\n syncStateFingerprint(await readStateForConfig(config)) !== journal.stateIdentity\n ) {\n throw new Error(\n \"Uncertain publication is not active, but local content or baseline changed; keep the journal for reviewed recovery.\",\n );\n }\n await clearMergeJournal(config);\n return false;\n }\n await validate();\n // Baseline publication is the durable completion boundary. A later remote revision\n // cannot undo that acceptance; retire only the journal for the recorded commit.\n if (journal.committedHead && (!head || !backend.sameRevision(head.revision, journal.committedHead.revision))) {\n const state = await readStateForConfig(config);\n await validate();\n if (\n matchesAcceptedState(state, config, journal.committedHead, journal.accepted ?? journal.after, journal.progress)\n ) {\n await clearMergeJournal(config);\n await validate();\n await pruneMergeBaselines(config, state, captureMutationOwner(ctx, signal));\n await validate();\n return true;\n }\n }\n if (journal.applyOnly && (!head || !backend.sameRevision(head.revision, journal.expectedHead.revision))) {\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptions);\n const state = await readStateForConfig(config);\n await validate();\n if (\n sameHashes(fileHashMap(local), fileHashMap(journal.before)) &&\n syncStateFingerprint(state) === journal.stateIdentity\n ) {\n await clearMergeJournal(config);\n return false;\n }\n throw new Error(\"Apply-only remote head advanced after local changes; preserve the journal for reviewed recovery.\");\n }\n if (\n !head ||\n head.snapshotId !== journal.upload.id ||\n (journal.committedHead && !backend.sameRevision(head.revision, journal.committedHead.revision))\n ) {\n throw new Error(\n \"Publication outcome cannot be reconciled with the current remote head. Journal and backup retained; do not retry publication or restore old bytes blindly.\",\n );\n }\n const observed = await readSnapshotForHead(backend, head, signal);\n requireCompatibleRemoteSelection(config, observed);\n if (\n !sameHashes(fileHashMap(observed), fileHashMap(journal.upload)) ||\n JSON.stringify(observed.selection) !== JSON.stringify(journal.upload.selection)\n )\n throw new Error(\"Remote snapshot does not match the recorded merge publication.\");\n const state = await readStateForConfig(config);\n if (matchesAcceptedState(state, config, head, journal.accepted ?? journal.after, journal.progress)) {\n await validate();\n await clearMergeJournal(config);\n await validate();\n await pruneMergeBaselines(config, state, captureMutationOwner(ctx, signal));\n await validate();\n return true;\n }\n if (syncStateFingerprint(state) !== journal.stateIdentity) {\n throw new Error(\"Sync baseline changed after the interrupted merge; preserve its journal and review recovery.\");\n }\n if (inspectRemoteSelection(config.include, observed).kind !== \"same\")\n throw new Error(\n \"Pending merge has unavailable remote selection metadata; preserve its journal and choose a reviewed explicit direction.\",\n );\n if (config.include.includes(\"sessions\")) requireStableMergeSessionRoot(journal.before, journal.after);\n await validate();\n const validateOwner = captureMutationOwner(ctx, signal);\n const validateMutation = () => {\n validateOwner();\n if (auto && !ctx.isIdle()) throw new Error(\"Automatic file apply is no longer idle; evidence retained.\");\n };\n await applyMergedSnapshot(\n journal.before,\n journal.after,\n protectedSessionPaths(ctx, sessionRoot),\n { ...snapshotOptions, validateMutation },\n validate,\n ctx.sessionManager.getSessionFile?.(),\n );\n await validate();\n const headAtAcceptance = await backend.readHead(signal);\n await validate();\n if (!headAtAcceptance || !backend.sameRevision(headAtAcceptance.revision, head.revision))\n throw new Error(\"Remote changed during merged apply; journal and backup retained for review.\");\n await writeAcceptedState(config, head, journal.accepted ?? journal.after, validate, journal.progress);\n await validate();\n await clearMergeJournal(config);\n await validate();\n await pruneMergeBaselines(\n config,\n acceptedState(config, head, journal.accepted ?? journal.after, journal.progress),\n captureMutationOwner(ctx, signal),\n );\n await validate();\n await pruneCompletedConflicts(\n config,\n backend.identity,\n acceptedState(config, head, journal.accepted ?? journal.after, journal.progress),\n journal.accepted ?? journal.after,\n journal.upload,\n captureMutationOwner(ctx, signal),\n );\n await validate();\n return true;\n}\n\n// Older valid journals may have accepted noncanonical JSON before projection normalization.\nfunction matchesAcceptedState(\n state: Awaited<ReturnType<typeof readStateForConfig>>,\n config: AnySyncConfig,\n head: RemoteHead,\n snapshot: Snapshot,\n progress?: PartialProgress,\n) {\n return [true, false].some(\n (canonical) =>\n syncStateFingerprint(state) === syncStateFingerprint(acceptedState(config, head, snapshot, progress, canonical)),\n );\n}\n\nfunction acceptedState(\n config: AnySyncConfig,\n head: RemoteHead,\n snapshot: Snapshot,\n progress?: PartialProgress,\n canonical = true,\n) {\n if (progress) return progressState(config, head, snapshot, progress);\n return {\n version: 1,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: head.snapshotId,\n lastRemoteRevision: head.revision,\n lastFileHashes: fileHashMap(canonical ? portableSnapshot(snapshot, config.localFields) : snapshot),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n };\n}\n\nasync function writeAcceptedState(\n config: AnySyncConfig,\n head: RemoteHead,\n snapshot: Snapshot,\n validate: () => Promise<void>,\n progress?: PartialProgress,\n) {\n const accepted = portableSnapshot(snapshot, config.localFields);\n const state = acceptedState(config, head, accepted, progress);\n await stageMergeBaseline(config, accepted, state, progress?.previous);\n await validate();\n await writeStateForConfig(config, state);\n await validate();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["fs", "path", "fs", "path", "createHash", "fs", "path", "createHash", "fs", "path", "createHash", "fileHashMap", "fs", "path", "path", "fs", "createHash", "target", "index", "createHash", "createHash", "artifact", "pending", "state"]
|
|
7
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
confirmMergeReview,
|
|
5
5
|
mergeSync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QTCGWQP3.ts";
|
|
7
7
|
import {
|
|
8
8
|
conflictArtifactFingerprint,
|
|
9
9
|
readConflictArtifact
|
|
@@ -12,7 +12,7 @@ import "./chunk-BDB4IDM3.ts";
|
|
|
12
12
|
import "./chunk-V6VZ5TLG.ts";
|
|
13
13
|
import {
|
|
14
14
|
createSyncBackend
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-FHNISD7A.ts";
|
|
16
16
|
import "./chunk-ANWNQIR7.ts";
|
|
17
17
|
import {
|
|
18
18
|
captureMutationOwner
|
|
@@ -172,4 +172,4 @@ async function showConflicts(ctx, options, factory = createSyncBackend) {
|
|
|
172
172
|
export {
|
|
173
173
|
showConflicts
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=conflict-review-
|
|
175
|
+
//# sourceMappingURL=conflict-review-NK5CM6UA.ts.map
|