{
  "version": 3,
  "sources": ["../../src/sync-operations.ts", "../../src/snapshot-apply.ts", "../../src/sync-decision.ts"],
  "sourcesContent": ["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ExtensionCommandContext, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"./backend-factory.js\";\nimport {\n\tloadConfig,\n\treadStateForConfig,\n\tsessionDirForApply,\n\tstateDir,\n\tsyncConfigReviewFingerprint,\n\tsyncSessionsWarnings,\n\twriteStateForConfig,\n} from \"./config.js\";\nimport { inspectLock, isLockGuardHeld, isStaleLock, withLock } from \"./lock.js\";\nimport {\n\tformatRemoteSelectionStatus,\n\treadSnapshotForHead,\n\trequireCompatibleRemoteSelection,\n} from \"./remote-snapshot.js\";\nimport {\n\tcreateSnapshot,\n\tfilterSnapshotForConfigPolicy,\n\tmergeRemotePreservedFiles,\n\tregenerateSnapshotIdentity,\n\tscanSnapshot,\n\tsessionSnapshotPathFromAbsolute,\n\tsnapshotIncludesSessions,\n\tsnapshotWithoutSessions,\n} from \"./snapshot.js\";\nimport { applySnapshot } from \"./snapshot-apply.js\";\nimport { encodeSnapshot } from \"./snapshot-codec.js\";\nimport {\n\texpectedRemoteHead,\n\ttype PublishSnapshotResult,\n\ttype RemoteHead,\n\ttype SyncBackend,\n} from \"./sync-backend.js\";\nimport { createSyncDecision } from \"./sync-decision.js\";\nimport {\n\tcountPreservedRemoteFiles,\n\terrorMessage,\n\tformatDiff,\n\tformatPullSummary,\n\tformatPushSummary,\n\tformatRollbackSummary,\n\tformatSnapshotOnlyDiff,\n\tpublicationCapabilityDescription,\n\tsafeTerminalText,\n} from \"./sync-format.js\";\nimport { inspectRemoteSelection, remoteSelectionMismatch } from \"./sync-policy.js\";\nimport {\n\tcanPullRemoteSessionsOnFirstSync,\n\tcanPullRemoteSettingsOnFirstSync,\n\tfileHashMap,\n\thasLocalChanges,\n\thasRemoteChanges,\n\tremoteChangedSinceState,\n\tsameHashes,\n\tshouldRefreshSyncedState,\n\tsnapshotHashesMatchState,\n\tsnapshotsMatch,\n\tsyncPolicyChanged,\n} from \"./sync-state.js\";\nimport type {\n\tAnySyncConfig,\n\tCommandOptions,\n\tSnapshot,\n\tSnapshotOptions,\n\tSyncState,\n} from \"./types.js\";\n\nconst STATUS_KEY = \"sync\";\nconst VERSION = 1;\nconst DEFAULT_PROFILE = \"default\";\nconst POST_LOCAL_COMMIT_TIMEOUT_MS = 30_000;\n\nexport class PublicationStatePersistenceError extends Error {\n\treadonly head: RemoteHead;\n\treadonly backupPath?: string;\n\n\tconstructor(head: RemoteHead, cause: unknown, backupPath?: string) {\n\t\tsuper(\n\t\t\t`Remote publication ${head.snapshotId} is active, but local sync state could not be saved${backupPath ? `; local backup: ${backupPath}` : \"\"}: ${errorMessage(cause)}`,\n\t\t\t{ cause },\n\t\t);\n\t\tthis.name = \"PublicationStatePersistenceError\";\n\t\tthis.head = head;\n\t\tthis.backupPath = backupPath;\n\t}\n}\n\nexport class RollbackPublicationError extends Error {\n\treadonly backupPath: string;\n\n\tconstructor(backupPath: string, cause: unknown) {\n\t\tsuper(\n\t\t\t`Rollback applied locally with backup ${backupPath}, but remote publication failed: ${errorMessage(cause)}`,\n\t\t\t{ cause },\n\t\t);\n\t\tthis.name = \"RollbackPublicationError\";\n\t\tthis.backupPath = backupPath;\n\t}\n}\n\ninterface PushInput {\n\tconfig: AnySyncConfig;\n\tstate: SyncState;\n\tlocal: Snapshot;\n\tbackend?: SyncBackend;\n}\n\nfunction backendFor(config: AnySyncConfig, factory: SyncBackendFactory) {\n\treturn factory(config);\n}\n\nexport async function status(\n\tctx: ExtensionCommandContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst config = await loadConfig(options.setup);\n\tthrowIfAborted(options.signal);\n\tctx.ui.setStatus(STATUS_KEY, `checking ${config.setupName}`);\n\tconst backend = await backendFor(config, factory);\n\tconst local = await createSnapshot(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t);\n\tthrowIfAborted(options.signal);\n\tconst state = await readStateForConfig(config);\n\tthrowIfAborted(options.signal);\n\tconst head = await backend.readHead(options.signal);\n\tthrowIfAborted(options.signal);\n\tconst selectionState = head\n\t\t? inspectRemoteSelection(config.include, { selection: head.selection, files: [] })\n\t\t: undefined;\n\tconst localChanged = hasLocalChanges(local, state, config);\n\n\tconst remoteText = head\n\t\t? `remote: ${head.snapshotId} from ${head.machine} at ${head.createdAt}`\n\t\t: \"remote: empty\";\n\tconst remoteChanged = remoteChangedSinceState(head, state, config, (left, right) =>\n\t\tbackend.sameRevision(left, right),\n\t);\n\tconst warnings = syncSessionsWarnings(config);\n\tctx.ui.setStatus(STATUS_KEY, undefined);\n\tctx.ui.notify(\n\t\t[\n\t\t\t`sync setup: ${config.setupName}`,\n\t\t\t`storage connection: ${config.connectionName}`,\n\t\t\t`storage location: ${safeTerminalText(backend.destination)}`,\n\t\t\t`publication safety: ${publicationCapabilityDescription(backend.capability)}`,\n\t\t\t`included content: ${config.include.join(\", \") || \"none\"}`,\n\t\t\t`sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n\t\t\tremoteText,\n\t\t\tformatRemoteSelectionStatus(selectionState),\n\t\t\t`local files: ${local.files.length}`,\n\t\t\t`local changed since last sync: ${localChanged ? \"yes\" : \"no\"}`,\n\t\t\t`remote changed since last sync: ${remoteChanged ? \"yes\" : \"no\"}`,\n\t\t\t...warnings,\n\t\t].join(\"\\n\"),\n\t\tlocalChanged || remoteChanged || selectionState?.kind === \"different\" || warnings.length > 0\n\t\t\t? \"warning\"\n\t\t\t: \"info\",\n\t);\n}\n\nexport async function diff(\n\tctx: ExtensionCommandContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst config = await loadConfig(options.setup);\n\tthrowIfAborted(options.signal);\n\tctx.ui.setStatus(STATUS_KEY, `checking ${config.setupName}`);\n\tconst backend = await backendFor(config, factory);\n\tconst local = await createSnapshot(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t);\n\tthrowIfAborted(options.signal);\n\tconst { snapshot: remote, selectionState } = await readRemoteSnapshot(\n\t\tbackend,\n\t\tconfig,\n\t\toptions.signal,\n\t\t{ allowSelectionDifference: true },\n\t);\n\tthrowIfAborted(options.signal);\n\tctx.ui.setStatus(STATUS_KEY, undefined);\n\n\tconst warnings = syncSessionsWarnings(config);\n\tconst header = [\n\t\t`sync setup: ${config.setupName}`,\n\t\t`storage connection: ${config.connectionName}`,\n\t\t`storage location: ${safeTerminalText(backend.destination)}`,\n\t\t`included content: ${config.include.join(\", \") || \"none\"}`,\n\t\t`sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n\t\tformatRemoteSelectionStatus(selectionState),\n\t\t...warnings,\n\t].join(\"\\n\");\n\tconst level = warnings.length > 0 || selectionState?.kind === \"different\" ? \"warning\" : \"info\";\n\tif (!remote) {\n\t\tctx.ui.notify(\n\t\t\t`${header}\\n\\n${formatSnapshotOnlyDiff(\"Remote is empty. Local push would upload\", local)}`,\n\t\t\tlevel,\n\t\t);\n\t\treturn;\n\t}\n\n\tctx.ui.notify(`${header}\\n\\n${formatDiff(local, remote)}`, level);\n}\n\nexport async function doctor(\n\tctx: ExtensionCommandContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst messages: string[] = [];\n\tlet level: \"info\" | \"warning\" = \"info\";\n\tlet snapshotOptions: SnapshotOptions = {};\n\tlet profile = DEFAULT_PROFILE;\n\tlet backend: SyncBackend | undefined;\n\tlet backendSummary: string[] = [];\n\n\ttry {\n\t\tconst config = await loadConfig(options.setup);\n\t\tthrowIfAborted(options.signal);\n\t\tbackend = await backendFor(config, factory);\n\t\tprofile = config.snapshotIdentity;\n\t\tsnapshotOptions = snapshotOptionsForContext(ctx, config);\n\t\tmessages.push(\n\t\t\t`config: ok (sync setup ${config.setupName})`,\n\t\t\t`included content: ${config.include.join(\", \") || \"none\"}`,\n\t\t\t`sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n\t\t);\n\t\tbackendSummary = [\n\t\t\t`storage location: ${safeTerminalText(backend.destination)}`,\n\t\t\t`publication safety: ${publicationCapabilityDescription(backend.capability)}`,\n\t\t];\n\t\tconst warnings = syncSessionsWarnings(config);\n\t\tif (warnings.length > 0) {\n\t\t\tlevel = \"warning\";\n\t\t\tmessages.push(...warnings);\n\t\t}\n\t} catch (error) {\n\t\tthrowIfAborted(options.signal);\n\t\tlevel = \"warning\";\n\t\tmessages.push(`config: ${errorMessage(error)}`);\n\t}\n\n\tconst local = await createSnapshot(profile, snapshotOptions);\n\tthrowIfAborted(options.signal);\n\tconst secrets = scanSnapshot(local);\n\tif (secrets.length > 0) {\n\t\tlevel = \"warning\";\n\t\tmessages.push(\"secret scan: possible secrets found:\");\n\t\tmessages.push(...secrets.map((secret) => `- ${secret}`));\n\t} else {\n\t\tmessages.push(`secret scan: ok (${local.files.length} files checked)`);\n\t}\n\n\tconst lock = await inspectLock();\n\tthrowIfAborted(options.signal);\n\tif (lock.status === \"valid\" && isStaleLock(lock.lock)) {\n\t\tlevel = \"warning\";\n\t\tmessages.push(\n\t\t\t`lock: stale (pid ${lock.lock.pid}); run /sync unlock after verifying no sync is running`,\n\t\t);\n\t} else if (lock.status === \"valid\") {\n\t\tmessages.push(`lock: held by pid ${lock.lock.pid} since ${lock.lock.startedAt}`);\n\t} else if (lock.status === \"unreadable\") {\n\t\tlevel = \"warning\";\n\t\tmessages.push(\n\t\t\t\"lock: unreadable; use /sync unlock --stale only after verifying no sync is running\",\n\t\t);\n\t} else if (await isLockGuardHeld()) {\n\t\tthrowIfAborted(options.signal);\n\t\tlevel = \"warning\";\n\t\tmessages.push(\"lock: guard active while metadata is missing or still being initialized\");\n\t} else {\n\t\tmessages.push(\"lock: free\");\n\t}\n\n\tif (backend) {\n\t\tmessages.push(...backendSummary);\n\t\tconst diagnostics = await backend.diagnose(options.signal);\n\t\tthrowIfAborted(options.signal);\n\t\tfor (const diagnostic of diagnostics) {\n\t\t\tmessages.push(diagnostic.message);\n\t\t\tif (diagnostic.level !== \"info\") level = \"warning\";\n\t\t}\n\t}\n\tctx.ui.notify(messages.join(\"\\n\"), level);\n}\n\nexport async function push(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\toptions: CommandOptions,\n\tinput?: PushInput,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst config = input?.config ?? (await loadConfig(options.setup));\n\tthrowIfAborted(options.signal);\n\tctx.ui.setStatus(STATUS_KEY, `pushing ${config.setupName}`);\n\tconst backend = input?.backend ?? (await backendFor(config, factory));\n\tconst state = input?.state ?? (await readStateForConfig(config));\n\tthrowIfAborted(options.signal);\n\tconst local =\n\t\tinput?.local ??\n\t\t(await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)));\n\tthrowIfAborted(options.signal);\n\n\tlet head = await backend.readHead(options.signal);\n\tlet remoteForUpload = await readRemoteSnapshotForUpload(\n\t\tbackend,\n\t\tconfig,\n\t\thead,\n\t\tstate,\n\t\toptions.signal,\n\t);\n\tif (\n\t\t!options.force &&\n\t\t!remoteForUpload &&\n\t\thead?.selection &&\n\t\tinspectRemoteSelection(config.include, { selection: head.selection, files: [] }).kind ===\n\t\t\t\"different\"\n\t) {\n\t\tremoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n\t}\n\tif (remoteForUpload && !options.force) {\n\t\trequireCompatibleRemoteSelection(config, remoteForUpload);\n\t}\n\tif (\n\t\tremoteChangedSinceState(head, state, config, (left, right) =>\n\t\t\tbackend.sameRevision(left, right),\n\t\t) &&\n\t\t!options.force\n\t) {\n\t\tconst remoteForConflict = remoteForUpload\n\t\t\t? filterSnapshotForConfigPolicy(remoteForUpload, config)\n\t\t\t: undefined;\n\t\tif (!remoteForConflict || !snapshotHashesMatchState(remoteForConflict, state, config)) {\n\t\t\tthrow createSyncDecision({\n\t\t\t\tkind: head ? \"remote-or-policy-changed\" : \"remote-empty\",\n\t\t\t\tconfig,\n\t\t\t\tstate,\n\t\t\t\tlocal,\n\t\t\t\tremote: remoteForConflict,\n\t\t\t\tlocalChanged: hasLocalChanges(local, state, config),\n\t\t\t\tremoteChanged: true,\n\t\t\t\tdirectMessage:\n\t\t\t\t\t\"Remote or sync policy changed since last sync. Run /sync pull first or /sync push --force.\",\n\t\t\t});\n\t\t}\n\t}\n\n\tlet upload = await snapshotForUpload(\n\t\tbackend,\n\t\tconfig,\n\t\tlocal,\n\t\thead,\n\t\tremoteForUpload,\n\t\toptions.signal,\n\t);\n\tconst secrets = scanSnapshot(local);\n\tif (secrets.length > 0) {\n\t\tthrow new Error(\n\t\t\t`Refusing to push possible secrets:\\n${secrets.map((s) => `- ${s}`).join(\"\\n\")}`,\n\t\t);\n\t}\n\n\tif (!(await confirmPush(ctx, options, config, backend, local, upload, head, remoteForUpload))) {\n\t\treturn \"cancelled\" as const;\n\t}\n\n\tif (options.force) {\n\t\tconst refreshedHead = await backend.readHead(options.signal);\n\t\tif (!sameRemoteHead(backend, head, refreshedHead)) {\n\t\t\thead = refreshedHead;\n\t\t\tremoteForUpload = head\n\t\t\t\t? await backend.readSnapshot(head.snapshotRef, options.signal)\n\t\t\t\t: undefined;\n\t\t\tupload = await snapshotForUpload(\n\t\t\t\tbackend,\n\t\t\t\tconfig,\n\t\t\t\tlocal,\n\t\t\t\thead,\n\t\t\t\tremoteForUpload,\n\t\t\t\toptions.signal,\n\t\t\t);\n\t\t\tif (\n\t\t\t\t!(await confirmPush(\n\t\t\t\t\tctx,\n\t\t\t\t\toptions,\n\t\t\t\t\tconfig,\n\t\t\t\t\tbackend,\n\t\t\t\t\tlocal,\n\t\t\t\t\tupload,\n\t\t\t\t\thead,\n\t\t\t\t\tremoteForUpload,\n\t\t\t\t\t\"Remote changed during review. Push the refreshed plan?\",\n\t\t\t\t))\n\t\t\t) {\n\t\t\t\treturn \"cancelled\" as const;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result = await backend.publishSnapshot(upload, expectedRemoteHead(head), {\n\t\tsignal: options.signal,\n\t\tonCommit: options.onCommit,\n\t});\n\ttry {\n\t\tawait writeStateForConfig(config, {\n\t\t\tversion: VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastAppliedSnapshot: result.head.snapshotId,\n\t\t\tlastRemoteRevision: result.head.revision,\n\t\t\tlastFileHashes: fileHashMap(local),\n\t\t\tinclude: [...config.include],\n\t\t});\n\t} catch (error) {\n\t\tthrow new PublicationStatePersistenceError(result.head, error);\n\t}\n\tif (options.signal?.aborted) return;\n\tctx.ui.setStatus(STATUS_KEY, undefined);\n\tif (!options.silent) {\n\t\tctx.ui.notify(\n\t\t\t[\n\t\t\t\t`Pushed ${upload.files.length} files from sync setup \u201C${config.setupName}\u201D as ${result.head.snapshotId}.`,\n\t\t\t\t...result.warnings,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\"\\n\"),\n\t\t\tresult.warnings.length > 0 ? \"warning\" : \"info\",\n\t\t);\n\t}\n\treturn \"applied\" as const;\n}\n\nexport async function pull(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst config = await loadConfig(options.setup);\n\tthrowIfAborted(options.signal);\n\tctx.ui.setStatus(STATUS_KEY, `pulling ${config.setupName}`);\n\tconst backend = await backendFor(config, factory);\n\tconst state = await readStateForConfig(config);\n\tthrowIfAborted(options.signal);\n\tconst local = await createSnapshot(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t);\n\tthrowIfAborted(options.signal);\n\tconst { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n\tthrowIfAborted(options.signal);\n\tconst localChanged = hasLocalChanges(local, state, config);\n\tif (!remote) {\n\t\tthrow createSyncDecision({\n\t\t\tkind: \"remote-empty\",\n\t\t\tconfig,\n\t\t\tstate,\n\t\t\tlocal,\n\t\t\tlocalChanged,\n\t\t\tremoteChanged: false,\n\t\t\tdirectMessage: \"Remote is empty. Run /sync push from a configured machine first.\",\n\t\t});\n\t}\n\n\tconst remoteChanged = hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx));\n\tif (localChanged && remoteChanged && state.lastAppliedSnapshot && !options.force) {\n\t\tthrow createSyncDecision({\n\t\t\tkind: \"both-changed\",\n\t\t\tconfig,\n\t\t\tstate,\n\t\t\tlocal,\n\t\t\tremote,\n\t\t\tlocalChanged,\n\t\t\tremoteChanged,\n\t\t\tdirectMessage:\n\t\t\t\t\"Both local and remote changed since last sync. Run /sync diff, then choose /sync pull --force or /sync push --force.\",\n\t\t});\n\t}\n\n\tif (\n\t\t!options.yes &&\n\t\t!(await ctx.ui.confirm(\n\t\t\tsnapshotIncludesSessions(remote) ? \"Pull pi settings and sessions?\" : \"Pull pi settings?\",\n\t\t\tformatPullSummary(\n\t\t\t\tconfig,\n\t\t\t\tbackend.destination,\n\t\t\t\tlocal,\n\t\t\t\tremote,\n\t\t\t\tprotectedSessionPaths(ctx).size,\n\t\t\t),\n\t\t))\n\t) {\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\tctx.ui.notify(\"Pull cancelled.\", \"info\");\n\t\treturn \"cancelled\" as const;\n\t}\n\n\tthrowIfAborted(options.signal);\n\tconst backup = await backupLocal(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t\toptions.signal,\n\t);\n\tconst applySessionDir = await sessionDirForApply(ctx, remote);\n\tthrowIfAborted(options.signal);\n\toptions.onCommit?.();\n\tconst lastFileHashes = await applySnapshot(remote, protectedSessionPaths(ctx), {\n\t\tinclude: config.include,\n\t\tsessionDir: applySessionDir,\n\t});\n\tawait writeStateForConfig(config, {\n\t\tversion: VERSION,\n\t\tprofile: config.snapshotIdentity,\n\t\tlastAppliedSnapshot: remote.id,\n\t\tlastRemoteRevision: head?.revision,\n\t\tlastFileHashes,\n\t\tinclude: [...config.include],\n\t});\n\tif (options.signal?.aborted) return \"applied\" as const;\n\tctx.ui.setStatus(STATUS_KEY, undefined);\n\tif (!options.silent) {\n\t\tctx.ui.notify(\n\t\t\t`Pulled ${remote.files.length} files from ${remote.id}. Backup: ${backup}`,\n\t\t\t\"info\",\n\t\t);\n\t} else if (\n\t\toptions.auto &&\n\t\tconfig.include.includes(\"sessions\") &&\n\t\tsnapshotIncludesSessions(remote)\n\t) {\n\t\tctx.ui.notify(\n\t\t\t\"Pulled Pi sessions after startup selected the current session. Restart Pi or resume a pulled session to use newly synced conversations.\",\n\t\t\t\"warning\",\n\t\t);\n\t}\n\tif (options.reload) await maybeReload(ctx, options.signal);\n\treturn \"applied\" as const;\n}\n\nexport async function syncBoth(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst config = await loadConfig(options.setup);\n\tthrowIfAborted(options.signal);\n\tconst backend = await backendFor(config, factory);\n\tconst state = await readStateForConfig(config);\n\tthrowIfAborted(options.signal);\n\tconst local = await createSnapshot(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t);\n\tthrowIfAborted(options.signal);\n\tif (config.include.length === 0) {\n\t\tif (!options.silent) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Sync setup \u201C${config.setupName}\u201D includes no files. Choose included content in /sync Settings before syncing.`,\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\tconst { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n\tthrowIfAborted(options.signal);\n\tconst localChanged = hasLocalChanges(local, state, config);\n\tconst remoteChanged = remote\n\t\t? hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx))\n\t\t: false;\n\tconst firstSync = !state.lastAppliedSnapshot;\n\n\tif (firstSync && remote && remote.files.length > 0 && local.files.length > 0) {\n\t\tif (!canPullRemoteSettingsOnFirstSync(local, remote)) {\n\t\t\tthrow createSyncDecision({\n\t\t\t\tkind: \"first-sync-settings-diverged\",\n\t\t\t\tconfig,\n\t\t\t\tstate,\n\t\t\t\tlocal,\n\t\t\t\tremote,\n\t\t\t\tlocalChanged: true,\n\t\t\t\tremoteChanged: true,\n\t\t\t\tdirectMessage:\n\t\t\t\t\t\"Remote settings exist and this machine has different local Pi settings. Run /sync diff, then manually choose /sync pull or /sync push.\",\n\t\t\t});\n\t\t}\n\t\tif (!sameHashes(fileHashMap(local), fileHashMap(remote))) {\n\t\t\tif (!canPullRemoteSessionsOnFirstSync(local, remote)) {\n\t\t\t\tthrow createSyncDecision({\n\t\t\t\t\tkind: \"first-sync-sessions-diverged\",\n\t\t\t\t\tconfig,\n\t\t\t\t\tstate,\n\t\t\t\t\tlocal,\n\t\t\t\t\tremote,\n\t\t\t\t\tlocalChanged: true,\n\t\t\t\t\tremoteChanged: true,\n\t\t\t\t\tdirectMessage:\n\t\t\t\t\t\t\"Remote settings match, but local and remote Pi sessions differ. Run /sync diff, then manually choose /sync pull or /sync push.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait pull(ctx, options, factory);\n\t\t\treturn;\n\t\t}\n\t\tawait writeStateForConfig(config, {\n\t\t\tversion: VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastAppliedSnapshot: remote.id,\n\t\t\tlastRemoteRevision: head?.revision,\n\t\t\tlastFileHashes: fileHashMap(remote),\n\t\t\tinclude: [...config.include],\n\t\t});\n\t\tif (!options.silent)\n\t\t\tctx.ui.notify(\"pi-sync state initialized; local settings already match remote.\", \"info\");\n\t\treturn;\n\t}\n\tif (localChanged && remoteChanged && remote && snapshotsMatch(local, remote)) {\n\t\tawait writeStateForConfig(config, {\n\t\t\tversion: VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastAppliedSnapshot: remote.id,\n\t\t\tlastRemoteRevision: head?.revision,\n\t\t\tlastFileHashes: fileHashMap(remote),\n\t\t\tinclude: [...config.include],\n\t\t});\n\t\tif (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n\t\treturn;\n\t}\n\tif (localChanged && remoteChanged && state.lastAppliedSnapshot) {\n\t\tthrow createSyncDecision({\n\t\t\tkind: \"both-changed\",\n\t\t\tconfig,\n\t\t\tstate,\n\t\t\tlocal,\n\t\t\tremote,\n\t\t\tlocalChanged,\n\t\t\tremoteChanged,\n\t\t\tdirectMessage:\n\t\t\t\t\"Both local and remote changed. Run /sync diff and resolve with push --force or pull --force.\",\n\t\t});\n\t}\n\tif (remoteChanged) {\n\t\tawait pull(ctx, options, factory);\n\t\treturn;\n\t}\n\tif (localChanged || !remote) {\n\t\tawait push(ctx, options, undefined, factory);\n\t\treturn;\n\t}\n\tif (\n\t\tshouldRefreshSyncedState(remote, head, state, config, (left, right) =>\n\t\t\tbackend.sameRevision(left, right),\n\t\t)\n\t) {\n\t\tawait writeStateForConfig(config, {\n\t\t\tversion: VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastAppliedSnapshot: remote.id,\n\t\t\tlastRemoteRevision: head?.revision,\n\t\t\tlastFileHashes: fileHashMap(remote),\n\t\t\tinclude: [...config.include],\n\t\t});\n\t}\n\tif (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n}\n\nexport async function history(\n\tctx: ExtensionCommandContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tconst config = await loadConfig(options.setup);\n\tthrowIfAborted(options.signal);\n\tconst backend = await backendFor(config, factory);\n\tconst snapshots = (await backend.listHistory(options.signal)).slice(-20).reverse();\n\tthrowIfAborted(options.signal);\n\tif (snapshots.length === 0) {\n\t\tctx.ui.notify(\"No remote pi-sync history found.\", \"info\");\n\t\treturn;\n\t}\n\n\tconst currentSnapshot = snapshots[0]?.snapshotId;\n\tif (ctx.mode === \"tui\") {\n\t\tconst labels = snapshots.map(\n\t\t\t(item, index) =>\n\t\t\t\t`${index + 1}. ${item.createdAt} \u00B7 ${safeTerminalText(item.machine)} \u00B7 ${item.snapshotId}${item.snapshotId === currentSnapshot ? \" (current)\" : \"\"}${item.syncSessions ? \" \u00B7 sessions\" : \"\"}`,\n\t\t);\n\t\tconst selected = await ctx.ui.select(\n\t\t\t`History for sync setup \u201C${safeTerminalText(config.setupName)}\u201D\\n\\nChoose a snapshot to preview rollback.`,\n\t\t\t[...labels, \"Back\"],\n\t\t);\n\t\tif (!selected || selected === \"Back\") return;\n\t\tthrowIfAborted(options.signal);\n\t\tconst index = labels.indexOf(selected);\n\t\tconst snapshot = snapshots[index];\n\t\tif (!snapshot) return;\n\t\tawait withLock(\"rollback\", () =>\n\t\t\trollback(ctx, { ...options, args: [snapshot.snapshotRef], yes: false }, factory, {\n\t\t\t\tbackendIdentity: backend.identity,\n\t\t\t\tsetup: config.setupName,\n\t\t\t}),\n\t\t);\n\t\treturn;\n\t}\n\tctx.ui.notify(\n\t\tsnapshots\n\t\t\t.map((item) => `${item.snapshotRef} ${item.createdAt} ${safeTerminalText(item.machine)}`)\n\t\t\t.join(\"\\n\"),\n\t\t\"info\",\n\t);\n}\n\nexport async function rollback(\n\tctx: ExtensionCommandContext,\n\toptions: CommandOptions,\n\tfactory: SyncBackendFactory = createSyncBackend,\n\texpectedSelection?: { backendIdentity: string; setup?: string },\n) {\n\tconst target = options.args[0];\n\tif (!target) throw new Error(\"Usage: /sync rollback <snapshot-id> [--yes]\");\n\n\tconst config = await loadConfig(options.setup);\n\tthrowIfAborted(options.signal);\n\tconst backend = await backendFor(config, factory);\n\tif (\n\t\texpectedSelection &&\n\t\t(backend.identity !== expectedSelection.backendIdentity ||\n\t\t\tconfig.setupName !== expectedSelection.setup)\n\t) {\n\t\tthrow new Error(\n\t\t\t\"Sync setup or storage location changed while history was open; reopen history and retry.\",\n\t\t);\n\t}\n\tconst decoded = await backend.readSnapshot(target, options.signal);\n\tconst selected = filterSnapshotForConfigPolicy(\n\t\tconfig.include.includes(\"sessions\") ? decoded : snapshotWithoutSessions(decoded),\n\t\tconfig,\n\t);\n\tconst remote = regenerateSnapshotIdentity(selected);\n\tconst local = await createSnapshot(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t);\n\tconst expectedHead = await backend.readHead(options.signal);\n\tthrowIfAborted(options.signal);\n\n\tif (\n\t\t!options.yes &&\n\t\t!(await ctx.ui.confirm(\n\t\t\tsnapshotIncludesSessions(remote)\n\t\t\t\t? \"Rollback pi settings and sessions?\"\n\t\t\t\t: \"Rollback pi settings?\",\n\t\t\tformatRollbackSummary(\n\t\t\t\tconfig,\n\t\t\t\tbackend.destination,\n\t\t\t\tlocal,\n\t\t\t\tremote,\n\t\t\t\ttarget,\n\t\t\t\tprotectedSessionPaths(ctx).size,\n\t\t\t),\n\t\t))\n\t) {\n\t\tctx.ui.notify(\"Rollback cancelled.\", \"info\");\n\t\treturn;\n\t}\n\n\tthrowIfAborted(options.signal);\n\tconst backup = await backupLocal(\n\t\tconfig.snapshotIdentity,\n\t\tsnapshotOptionsForContext(ctx, config),\n\t\toptions.signal,\n\t);\n\tconst applySessionDir = await sessionDirForApply(ctx, remote);\n\tthrowIfAborted(options.signal);\n\toptions.onCommit?.();\n\tconst lastFileHashes = await applySnapshot(remote, protectedSessionPaths(ctx), {\n\t\tinclude: config.include,\n\t\tsessionDir: applySessionDir,\n\t});\n\tlet result: PublishSnapshotResult;\n\ttry {\n\t\tconst completionSignal = AbortSignal.timeout(POST_LOCAL_COMMIT_TIMEOUT_MS);\n\t\tconst upload = await snapshotForUpload(\n\t\t\tbackend,\n\t\t\tconfig,\n\t\t\tremote,\n\t\t\texpectedHead,\n\t\t\tundefined,\n\t\t\tcompletionSignal,\n\t\t\t{ ignoreUnreadableRemote: true },\n\t\t);\n\t\tresult = await backend.publishSnapshot(upload, expectedRemoteHead(expectedHead), {\n\t\t\tsignal: completionSignal,\n\t\t});\n\t} catch (error) {\n\t\tthrow new RollbackPublicationError(backup, error);\n\t}\n\ttry {\n\t\tawait writeStateForConfig(config, {\n\t\t\tversion: VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastAppliedSnapshot: result.head.snapshotId,\n\t\t\tlastRemoteRevision: result.head.revision,\n\t\t\tlastFileHashes,\n\t\t\tinclude: [...config.include],\n\t\t});\n\t} catch (error) {\n\t\tthrow new PublicationStatePersistenceError(result.head, error, backup);\n\t}\n\tif (options.signal?.aborted) return;\n\tctx.ui.notify(\n\t\t[\n\t\t\t`Rolled back sync setup \u201C${config.setupName}\u201D to ${target}; latest: ${result.head.snapshotId}. Backup: ${backup}`,\n\t\t\t...result.warnings,\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\"\\n\"),\n\t\tresult.warnings.length > 0 ? \"warning\" : \"info\",\n\t);\n\tawait maybeReload(ctx, options.signal);\n}\n\nfunction protectedSessionPaths(ctx: ExtensionCommandContext | ExtensionContext) {\n\tconst getSessionFile = ctx.sessionManager.getSessionFile;\n\tif (typeof getSessionFile !== \"function\") return new Set<string>();\n\tconst sessionFile = getSessionFile.call(ctx.sessionManager) as string | undefined;\n\tconst snapshotPath = sessionFile\n\t\t? sessionSnapshotPathFromAbsolute(sessionFile, sessionDirFromContext(ctx))\n\t\t: undefined;\n\treturn snapshotPath ? new Set([snapshotPath]) : new Set<string>();\n}\n\nfunction snapshotOptionsForContext(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\tconfig: AnySyncConfig,\n): SnapshotOptions {\n\treturn {\n\t\tinclude: config.include,\n\t\tsessionDir: sessionDirFromContext(ctx),\n\t};\n}\n\nfunction sessionDirFromContext(ctx: ExtensionCommandContext | ExtensionContext) {\n\tconst manager = ctx.sessionManager as typeof ctx.sessionManager & {\n\t\tusesDefaultSessionDir?: () => boolean;\n\t};\n\tconst usesDefaultSessionDir = manager.usesDefaultSessionDir;\n\tif (typeof usesDefaultSessionDir === \"function\" && usesDefaultSessionDir.call(manager)) {\n\t\treturn undefined;\n\t}\n\tconst getSessionDir = manager.getSessionDir;\n\treturn typeof getSessionDir === \"function\"\n\t\t? (getSessionDir.call(manager) as string | undefined)\n\t\t: undefined;\n}\n\nasync function maybeReload(ctx: ExtensionCommandContext | ExtensionContext, signal?: AbortSignal) {\n\tif (signal?.aborted || !(\"reload\" in ctx)) return;\n\tif (\n\t\tctx.hasUI &&\n\t\t(await ctx.ui.confirm(\n\t\t\t\"Reload Pi resources now?\",\n\t\t\t\"This reloads extensions, skills, prompts, themes, and context files.\",\n\t\t))\n\t) {\n\t\tif (signal?.aborted) return;\n\t\tawait ctx.reload();\n\t}\n}\n\nasync function readRemoteSnapshotForUpload(\n\tbackend: SyncBackend,\n\tconfig: AnySyncConfig,\n\thead: RemoteHead | undefined,\n\tstate: SyncState,\n\tsignal?: AbortSignal,\n) {\n\tif (\n\t\t!head ||\n\t\t(head.snapshotId === state.lastAppliedSnapshot &&\n\t\t\t!syncPolicyChanged(state, config) &&\n\t\t\t(!state.lastRemoteRevision || backend.sameRevision(head.revision, state.lastRemoteRevision)))\n\t) {\n\t\treturn undefined;\n\t}\n\treturn backend.readSnapshot(head.snapshotRef, signal);\n}\n\nasync function snapshotForUpload(\n\tbackend: SyncBackend,\n\tconfig: AnySyncConfig,\n\tlocal: Snapshot,\n\thead: RemoteHead | undefined,\n\tremote?: Snapshot,\n\tsignal?: AbortSignal,\n\toptions: { ignoreUnreadableRemote?: boolean } = {},\n) {\n\tif (!head) return local;\n\tlet snapshot = remote;\n\tif (!snapshot) {\n\t\ttry {\n\t\t\tsnapshot = await backend.readSnapshot(head.snapshotRef, signal);\n\t\t} catch (error) {\n\t\t\tif (options.ignoreUnreadableRemote) return local;\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn mergeRemotePreservedFiles(local, snapshot, config);\n}\n\nasync function readRemoteSnapshot(\n\tbackend: SyncBackend,\n\tconfig: AnySyncConfig,\n\tsignal?: AbortSignal,\n\toptions: { allowSelectionDifference?: boolean } = {},\n) {\n\tconst head = await backend.readHead(signal);\n\tif (!head) return { head: undefined, snapshot: undefined, selectionState: undefined };\n\tconst snapshot = await readSnapshotForHead(backend, head, signal);\n\tconst selectionState = inspectRemoteSelection(config.include, snapshot);\n\tif (!options.allowSelectionDifference && selectionState.kind === \"different\") {\n\t\tconst configIdentity = syncConfigReviewFingerprint(config);\n\t\tthrow remoteSelectionMismatch(config, selectionState.include, configIdentity);\n\t}\n\treturn {\n\t\thead,\n\t\tsnapshot: filterSnapshotForConfigPolicy(snapshot, config),\n\t\tselectionState,\n\t};\n}\n\nasync function confirmPush(\n\tctx: ExtensionCommandContext | ExtensionContext,\n\toptions: CommandOptions,\n\tconfig: AnySyncConfig,\n\tbackend: SyncBackend,\n\tlocal: Snapshot,\n\tupload: Snapshot,\n\thead: RemoteHead | undefined,\n\tremote: Snapshot | undefined,\n\ttitle = snapshotIncludesSessions(upload) ? \"Push pi settings and sessions?\" : \"Push pi settings?\",\n) {\n\tthrowIfAborted(options.signal);\n\tif (options.yes) return true;\n\tconst confirmed = await ctx.ui.confirm(\n\t\ttitle,\n\t\tformatPushSummary(\n\t\t\tconfig,\n\t\t\tbackend.destination,\n\t\t\tupload,\n\t\t\thead,\n\t\t\tcountPreservedRemoteFiles(local, upload),\n\t\t\tremote,\n\t\t),\n\t);\n\tthrowIfAborted(options.signal);\n\tif (confirmed) return true;\n\tctx.ui.setStatus(STATUS_KEY, undefined);\n\tctx.ui.notify(\"Push cancelled.\", \"info\");\n\treturn false;\n}\n\nfunction throwIfAborted(signal?: AbortSignal) {\n\tif (!signal?.aborted) return;\n\tthrow signal.reason instanceof Error\n\t\t? signal.reason\n\t\t: new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n\nfunction sameRemoteHead(\n\tbackend: SyncBackend,\n\tleft: RemoteHead | undefined,\n\tright: RemoteHead | undefined,\n) {\n\tif (!left || !right) return left === right;\n\treturn backend.sameRevision(left.revision, right.revision);\n}\n\nexport async function backupLocal(\n\tprofile: string,\n\toptions: SnapshotOptions = {},\n\tsignal?: AbortSignal,\n) {\n\tthrowIfAborted(signal);\n\tconst snapshot = await createSnapshot(profile, options);\n\tthrowIfAborted(signal);\n\tconst backupDirectory = path.join(stateDir(), \"backups\");\n\tawait fs.mkdir(backupDirectory, { recursive: true });\n\tthrowIfAborted(signal);\n\tconst backupPath = path.join(backupDirectory, `${snapshot.id}.json.gz`);\n\tconst encoded = await encodeSnapshot(snapshot);\n\tthrowIfAborted(signal);\n\tawait fs.writeFile(backupPath, encoded, { signal });\n\treturn backupPath;\n}\n", "import { createHash } from \"node:crypto\";\nimport type { Dirent } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { agentDir } from \"./config.js\";\nimport {\n\tassertWithinRoot,\n\tisDeniedPath,\n\tisPathInside,\n\tparentPaths,\n\tsafeJoin,\n\ttoPosix,\n} from \"./paths.js\";\nimport {\n\tcreateSnapshot,\n\tisSessionFilePath,\n\tisSessionPath,\n\tsessionStorageRoot,\n\tsnapshotIncludesSessions,\n\tsnapshotTarget,\n} from \"./snapshot.js\";\nimport {\n\tapplySnapshotTransaction,\n\trecoverPendingSnapshotTransactions,\n} from \"./snapshot-transaction.js\";\nimport type { Snapshot, SnapshotApplyPlan, SnapshotOptions } from \"./types.js\";\n\nfunction sha256(value: Buffer) {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction fileHashMap(snapshot: Snapshot) {\n\treturn Object.fromEntries(snapshot.files.map((file) => [file.path, file.sha256]));\n}\n\nexport async function applySnapshot(\n\tsnapshot: Snapshot,\n\tprotectedRelativePaths = new Set<string>(),\n\toptions: Pick<\n\t\tSnapshotOptions,\n\t\t\"include\" | \"sessionDir\" | \"syncFiles\" | \"syncSessions\" | \"extraFiles\"\n\t> = {},\n) {\n\tconst root = agentDir();\n\tconst { sessionDir } = options;\n\tawait recoverPendingSnapshotTransactions();\n\tconst current = await createSnapshot(snapshot.profile, {\n\t\t...options,\n\t\t...(options.include === undefined ? { syncSessions: snapshotIncludesSessions(snapshot) } : {}),\n\t\tsessionDir,\n\t});\n\tconst plan = await addTopLevelCaseVariantDeletes(\n\t\troot,\n\t\tprotectSnapshotApplyPlan(\n\t\t\troot,\n\t\t\tpreflightSnapshotApply(root, snapshot, current, { sessionDir }),\n\t\t\tprotectedRelativePaths,\n\t\t\tsessionDir,\n\t\t),\n\t\tsnapshot,\n\t);\n\tawait preflightSnapshotMutations(root, plan, sessionDir);\n\tawait applySnapshotTransaction(plan, { sessionDir });\n\treturn appliedFileHashMap(snapshot, current, protectedRelativePaths);\n}\n\nexport function preflightSnapshotApply(\n\troot: string,\n\tsnapshot: Snapshot,\n\tcurrent: Snapshot,\n\toptions: { sessionDir?: string } = {},\n): SnapshotApplyPlan {\n\tconst seenPaths = new Set<string>();\n\tconst remotePaths = new Set<string>();\n\tconst writes: Array<{ target: string; content: Buffer }> = [];\n\tconst deletes: string[] = [];\n\n\tfor (const file of snapshot.files) {\n\t\tconst normalized = toPosix(file.path);\n\t\tif (!isSafeSnapshotPath(file.path)) {\n\t\t\tthrow new Error(`Unsafe path in snapshot: ${file.path}`);\n\t\t}\n\t\tif (isSessionPath(normalized) && !isSessionFilePath(normalized)) {\n\t\t\tthrow new Error(`Unsafe session path in snapshot: ${file.path}`);\n\t\t}\n\t\tif (seenPaths.has(normalized)) throw new Error(`Duplicate path in snapshot: ${normalized}`);\n\t\tseenPaths.add(normalized);\n\t\tremotePaths.add(normalized);\n\n\t\tconst target = snapshotTarget(root, normalized, options.sessionDir);\n\t\tconst content = decodeBase64Strict(file.contentBase64, normalized);\n\t\tif (sha256(content) !== file.sha256)\n\t\t\tthrow new Error(`Checksum mismatch in snapshot file: ${normalized}`);\n\t\twrites.push({ target, content });\n\t}\n\n\tconst deletePaths = new Set<string>();\n\tfor (const file of current.files) {\n\t\tconst normalized = toPosix(file.path);\n\t\tif (!remotePaths.has(normalized)) {\n\t\t\tdeletePaths.add(snapshotTarget(root, normalized, options.sessionDir));\n\t\t}\n\t\tfor (const remotePath of parentPaths(normalized)) {\n\t\t\tif (remotePaths.has(remotePath)) {\n\t\t\t\tdeletePaths.add(snapshotTarget(root, remotePath, options.sessionDir));\n\t\t\t}\n\t\t}\n\t}\n\tdeletes.push(...deletePaths);\n\n\treturn { writes, deletes };\n}\n\nexport function protectSnapshotApplyPlan(\n\troot: string,\n\tplan: SnapshotApplyPlan,\n\tprotectedRelativePaths: Set<string>,\n\tsessionDir?: string,\n): SnapshotApplyPlan {\n\tif (protectedRelativePaths.size === 0) return plan;\n\tconst protectedTargets = new Set(\n\t\t[...protectedRelativePaths].map((relativePath) =>\n\t\t\tsnapshotTarget(root, relativePath, sessionDir),\n\t\t),\n\t);\n\treturn {\n\t\twrites: plan.writes.filter((item) => !protectedTargets.has(item.target)),\n\t\tdeletes: plan.deletes.filter((target) => !protectedTargets.has(target)),\n\t};\n}\n\nexport async function addTopLevelCaseVariantDeletes(\n\troot: string,\n\tplan: SnapshotApplyPlan,\n\tsnapshot: Pick<Snapshot, \"files\">,\n): Promise<SnapshotApplyPlan> {\n\tconst topLevelPaths = new Map<string, string>();\n\tfor (const file of snapshot.files) {\n\t\tconst normalized = toPosix(file.path);\n\t\tif (!normalized.includes(\"/\") && isSafeSnapshotPath(file.path)) {\n\t\t\ttopLevelPaths.set(normalized.toLowerCase(), normalized);\n\t\t}\n\t}\n\tif (topLevelPaths.size === 0) return plan;\n\n\tlet entries: Dirent[];\n\ttry {\n\t\tentries = await fs.readdir(root, { withFileTypes: true });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return plan;\n\t\tthrow error;\n\t}\n\n\tconst deletes = new Set(plan.deletes);\n\tfor (const entry of entries) {\n\t\tconst canonicalPath = topLevelPaths.get(entry.name.toLowerCase());\n\t\tif (\n\t\t\tcanonicalPath &&\n\t\t\tentry.name !== canonicalPath &&\n\t\t\t(entry.isFile() || entry.isSymbolicLink())\n\t\t) {\n\t\t\tdeletes.add(safeJoin(root, entry.name));\n\t\t}\n\t}\n\treturn { ...plan, deletes: [...deletes] };\n}\n\nexport function appliedFileHashMap(\n\tsnapshot: Snapshot,\n\tcurrent: Snapshot,\n\tprotectedRelativePaths: Set<string>,\n) {\n\tconst hashes = fileHashMap(snapshot);\n\tif (protectedRelativePaths.size === 0) return hashes;\n\tconst currentHashes = fileHashMap(current);\n\tfor (const relativePath of protectedRelativePaths) {\n\t\tconst normalized = toPosix(relativePath);\n\t\tif (currentHashes[normalized]) {\n\t\t\thashes[normalized] = currentHashes[normalized];\n\t\t} else {\n\t\t\tdelete hashes[normalized];\n\t\t}\n\t}\n\treturn hashes;\n}\n\nfunction isSafeSnapshotPath(relativePath: string) {\n\tif (relativePath.includes(\"\\\\\")) return false;\n\tconst normalized = toPosix(relativePath);\n\treturn (\n\t\tBoolean(normalized) &&\n\t\tnormalized !== \".\" &&\n\t\tnormalized !== \"..\" &&\n\t\t!normalized.startsWith(\"../\") &&\n\t\t!path.posix.isAbsolute(normalized) &&\n\t\tpath.posix.normalize(normalized) === normalized &&\n\t\t!isDeniedPath(normalized)\n\t);\n}\n\nfunction decodeBase64Strict(value: string, filePath: string) {\n\tif (!/^[A-Za-z0-9+/]*={0,2}$/.test(value) || value.length % 4 !== 0) {\n\t\tthrow new Error(`Invalid base64 content in snapshot file: ${filePath}`);\n\t}\n\treturn Buffer.from(value, \"base64\");\n}\n\nasync function preflightSnapshotMutations(\n\troot: string,\n\tplan: { deletes: string[]; writes: Array<{ target: string; content: Buffer }> },\n\tsessionDir?: string,\n) {\n\tconst deletePaths = new Set(plan.deletes);\n\tfor (const target of plan.deletes) {\n\t\tawait assertNoSymlinkParents(rootForTarget(root, target, sessionDir), target);\n\t}\n\tfor (const item of plan.writes) {\n\t\tawait prepareSnapshotWrite(\n\t\t\trootForTarget(root, item.target, sessionDir),\n\t\t\titem.target,\n\t\t\tdeletePaths,\n\t\t);\n\t}\n}\n\nfunction rootForTarget(root: string, target: string, sessionDir?: string) {\n\tconst sessionRoot = sessionDir ? sessionStorageRoot(root, sessionDir) : undefined;\n\tif (sessionRoot && isPathInside(sessionRoot, target)) return sessionRoot;\n\treturn root;\n}\n\nasync function prepareSnapshotWrite(root: string, target: string, deletePaths: Set<string>) {\n\tconst parentWillBeReplaced = await ensureSafeDirectory(root, path.dirname(target), deletePaths);\n\tif (parentWillBeReplaced) return;\n\ttry {\n\t\tconst stat = await fs.lstat(target);\n\t\tif (stat.isSymbolicLink())\n\t\t\tthrow new Error(`Refusing to overwrite symlink during snapshot apply: ${target}`);\n\t\tif (stat.isDirectory() && !deletePaths.has(target)) {\n\t\t\tthrow new Error(`Refusing to overwrite directory during snapshot apply: ${target}`);\n\t\t}\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t}\n}\n\nasync function ensureSafeDirectory(root: string, directory: string, deletePaths: Set<string>) {\n\tassertWithinRoot(root, directory);\n\tconst rootPath = path.resolve(root);\n\tconst relative = path.relative(rootPath, path.resolve(directory));\n\tlet current = rootPath;\n\tfor (const part of relative.split(path.sep).filter(Boolean)) {\n\t\tcurrent = path.join(current, part);\n\t\ttry {\n\t\t\tconst stat = await fs.lstat(current);\n\t\t\tif (stat.isSymbolicLink())\n\t\t\t\tthrow new Error(`Refusing to follow symlink during snapshot apply: ${current}`);\n\t\t\tif (!stat.isDirectory()) {\n\t\t\t\tif (deletePaths.has(current)) return true;\n\t\t\t\tthrow new Error(`Snapshot path parent is not a directory: ${current}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\t\tawait fs.mkdir(current);\n\t\t}\n\t}\n\treturn false;\n}\n\nasync function assertNoSymlinkParents(root: string, target: string) {\n\tassertWithinRoot(root, target);\n\tconst rootPath = path.resolve(root);\n\tconst relative = path.relative(rootPath, path.resolve(target));\n\tlet current = rootPath;\n\tconst parts = relative.split(path.sep).filter(Boolean);\n\tfor (const part of parts.slice(0, -1)) {\n\t\tcurrent = path.join(current, part);\n\t\ttry {\n\t\t\tconst stat = await fs.lstat(current);\n\t\t\tif (stat.isSymbolicLink())\n\t\t\t\tthrow new Error(`Refusing to follow symlink during snapshot apply: ${current}`);\n\t\t\tif (!stat.isDirectory())\n\t\t\t\tthrow new Error(`Snapshot path parent is not a directory: ${current}`);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n", "import { syncConfigReviewIdentity } from \"./config.js\";\nimport { SyncDecisionRequiredError } from \"./sync-errors.js\";\nimport { formatDiff, formatSnapshotOnlyDiff, safeTerminalText } from \"./sync-format.js\";\nimport { includeFromSelectionConfig } from \"./sync-policy.js\";\nimport { syncPolicyChanged } from \"./sync-state.js\";\nimport type { AnySyncConfig, Snapshot, SyncState } from \"./types.js\";\n\nexport type SyncDecisionKind =\n\t| \"remote-or-policy-changed\"\n\t| \"both-changed\"\n\t| \"first-sync-settings-diverged\"\n\t| \"first-sync-sessions-diverged\"\n\t| \"remote-empty\";\n\nexport type SyncResolutionDirection = \"push\" | \"pull\";\n\nexport interface SyncDecision {\n\tkind: SyncDecisionKind;\n\tsetupName: string;\n\tconfigIdentity: string;\n\tcauses: {\n\t\tlocalChanged: boolean;\n\t\tremoteChanged: boolean;\n\t\tpolicyChanged: boolean;\n\t};\n\tpreviousInclude?: readonly string[];\n\tcurrentInclude: readonly string[];\n\treview: string;\n\tdirections: readonly SyncResolutionDirection[];\n\tdirectMessage: string;\n}\n\nexport {\n\tisSyncDecisionRequiredError,\n\tSyncDecisionRequiredError,\n} from \"./sync-errors.js\";\n\ninterface CreateSyncDecisionOptions {\n\tkind: SyncDecisionKind;\n\tconfig: AnySyncConfig;\n\tstate: SyncState;\n\tlocal: Snapshot;\n\tremote?: Snapshot;\n\tlocalChanged: boolean;\n\tremoteChanged: boolean;\n\tdirectMessage: string;\n}\n\nexport function createSyncDecision(options: CreateSyncDecisionOptions) {\n\tconst { config, state, local, remote, kind } = options;\n\tconst policyChanged = Boolean(state.lastAppliedSnapshot) && syncPolicyChanged(state, config);\n\tconst previousInclude = includeFromSelectionConfig(state);\n\tconst currentInclude = [...config.include];\n\tconst causes = {\n\t\tlocalChanged: options.localChanged,\n\t\tremoteChanged: options.remoteChanged,\n\t\tpolicyChanged,\n\t};\n\tconst causeLines =\n\t\tkind === \"first-sync-settings-diverged\"\n\t\t\t? [\"This machine and the remote have different Pi settings on first sync.\"]\n\t\t\t: kind === \"first-sync-sessions-diverged\"\n\t\t\t\t? [\"Pi settings match, but local and remote sessions differ on first sync.\"]\n\t\t\t\t: kind === \"remote-empty\"\n\t\t\t\t\t? [\"The remote storage location is empty.\"]\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t...(causes.localChanged ? [\"Local content changed since the last sync.\"] : []),\n\t\t\t\t\t\t\t...(causes.remoteChanged ? [\"Remote content changed since the last sync.\"] : []),\n\t\t\t\t\t\t\t...(causes.policyChanged ? [\"Included content changed since the last sync.\"] : []),\n\t\t\t\t\t\t];\n\tconst comparison = remote\n\t\t? formatDiff(local, remote)\n\t\t: formatSnapshotOnlyDiff(\"Remote is empty. Local push would upload\", local);\n\tconst review = [\n\t\t`Sync setup: ${safeTerminalText(config.setupName)}`,\n\t\t\"\",\n\t\t\"Why a decision is required:\",\n\t\t...causeLines,\n\t\t...(policyChanged\n\t\t\t? [\n\t\t\t\t\t\"\",\n\t\t\t\t\t`Previously included: ${safeList(previousInclude)}`,\n\t\t\t\t\t`Currently included: ${safeList(currentInclude)}`,\n\t\t\t\t]\n\t\t\t: []),\n\t\t\"\",\n\t\t\"Observed differences:\",\n\t\t...comparison.split(\"\\n\").map(safeTerminalText),\n\t].join(\"\\n\");\n\treturn new SyncDecisionRequiredError({\n\t\tkind,\n\t\tsetupName: config.setupName,\n\t\tconfigIdentity: syncConfigReviewIdentity(config),\n\t\tcauses,\n\t\t...(policyChanged ? { previousInclude: [...previousInclude] } : {}),\n\t\tcurrentInclude,\n\t\treview,\n\t\tdirections: kind === \"remote-empty\" ? [\"push\"] : [\"push\", \"pull\"],\n\t\tdirectMessage: options.directMessage,\n\t});\n}\n\nfunction safeList(values: readonly string[]) {\n\treturn values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n"],
  "mappings": "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",
  "names": ["fs", "path", "fileHashMap", "index", "path", "fs"]
}
