@narumitw/pi-sync 0.57.1 → 0.57.4

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.
Files changed (89) hide show
  1. package/README.md +5 -1
  2. package/dist/chunks/{agent-plan-K3CRYVXV.ts → agent-plan-3L7CRFDM.ts} +28 -11
  3. package/dist/chunks/agent-plan-3L7CRFDM.ts.map +7 -0
  4. package/dist/chunks/agent-refusal-retry-AH7TXOQT.ts +69 -0
  5. package/dist/chunks/agent-refusal-retry-AH7TXOQT.ts.map +7 -0
  6. package/dist/chunks/{agent-runner-E2JU2VZ6.ts → agent-runner-WMSCKSCB.ts} +7 -5
  7. package/dist/chunks/agent-runner-WMSCKSCB.ts.map +7 -0
  8. package/dist/chunks/{agent-store-A3F6IYWZ.ts → agent-store-55CZOCPX.ts} +25 -3
  9. package/dist/chunks/agent-store-55CZOCPX.ts.map +7 -0
  10. package/dist/chunks/{chunk-QGK445K7.ts → chunk-3ST7RSYN.ts} +1 -1
  11. package/dist/chunks/chunk-3ST7RSYN.ts.map +7 -0
  12. package/dist/chunks/{chunk-OWBAZA6J.ts → chunk-DT6TOCIG.ts} +2 -2
  13. package/dist/chunks/{chunk-JJTARUSO.ts → chunk-JCH3VXIO.ts} +3 -2
  14. package/dist/chunks/{chunk-JJTARUSO.ts.map → chunk-JCH3VXIO.ts.map} +2 -2
  15. package/dist/chunks/{chunk-OEWQVWLC.ts → chunk-ORGBI36T.ts} +4 -4
  16. package/dist/chunks/{chunk-EUMINX7L.ts → chunk-P7DD5PWZ.ts} +2 -2
  17. package/dist/chunks/{chunk-VJN7KU4J.ts → chunk-PG7NMFP2.ts} +83 -18
  18. package/dist/chunks/chunk-PG7NMFP2.ts.map +7 -0
  19. package/dist/chunks/{chunk-T3NC77TU.ts → chunk-R75IHAOJ.ts} +45 -18
  20. package/dist/chunks/chunk-R75IHAOJ.ts.map +7 -0
  21. package/dist/chunks/{chunk-QSHMOL3I.ts → chunk-U3XRI2HF.ts} +28 -195
  22. package/dist/chunks/chunk-U3XRI2HF.ts.map +7 -0
  23. package/dist/chunks/chunk-WD6FJHCK.ts +140 -0
  24. package/dist/chunks/chunk-WD6FJHCK.ts.map +7 -0
  25. package/dist/chunks/{conflict-review-ZCGWFKEK.ts → conflict-review-T7GSOKNG.ts} +9 -8
  26. package/dist/chunks/{conflict-review-ZCGWFKEK.ts.map → conflict-review-T7GSOKNG.ts.map} +1 -1
  27. package/dist/chunks/{continuous-record-LFRVXQBD.ts → continuous-record-SQJ47CXN.ts} +3 -3
  28. package/dist/chunks/{continuous-sync-LAIMSW7D.ts → continuous-sync-U4HIKPQK.ts} +9 -9
  29. package/dist/chunks/{continuous-sync-LAIMSW7D.ts.map → continuous-sync-U4HIKPQK.ts.map} +2 -2
  30. package/dist/chunks/{git-backend-KYDZ673X.ts → git-backend-NYKSG5X6.ts} +4 -4
  31. package/dist/chunks/{manager-result-dispatcher-AGBBVDDS.ts → manager-result-dispatcher-HOCM2GDA.ts} +4 -4
  32. package/dist/chunks/{manager-ui-KRAW3NE2.ts → manager-ui-FXXO6TW4.ts} +54 -17
  33. package/dist/chunks/manager-ui-FXXO6TW4.ts.map +7 -0
  34. package/dist/chunks/{remote-selection-ui-5725JDNC.ts → remote-selection-ui-YFPGYGNE.ts} +3 -3
  35. package/dist/chunks/{s3-backend-Y7WSCLJI.ts → s3-backend-F7PR5FB3.ts} +4 -4
  36. package/dist/chunks/{setup-wizard-65DROCIJ.ts → setup-wizard-OVHZYXNW.ts} +2 -2
  37. package/dist/chunks/{sync-inspection-XFJOAMJD.ts → sync-inspection-5MY2HI4P.ts} +3 -3
  38. package/dist/chunks/{sync-operations-W5HFFMTP.ts → sync-operations-GNPS6BLY.ts} +29 -17
  39. package/dist/chunks/sync-operations-GNPS6BLY.ts.map +7 -0
  40. package/dist/chunks/{webdav-backend-6K26F6LT.ts → webdav-backend-TGFUH3SF.ts} +4 -4
  41. package/dist/index.ts +28 -23
  42. package/dist/index.ts.map +2 -2
  43. package/docs/agent-continuous-hardening.md +79 -0
  44. package/docs/agent-mode-verification.md +2 -0
  45. package/docs/agent-quality-verification.md +41 -0
  46. package/docs/continuous-sync-verification.md +2 -0
  47. package/package.json +4 -4
  48. package/skills/configure-pi-sync/references/configuration.md +21 -5
  49. package/src/commands/command-execution.ts +7 -2
  50. package/src/commands/command-handler.ts +3 -1
  51. package/src/commands/command-types.ts +3 -1
  52. package/src/sync/agent-plan.ts +26 -9
  53. package/src/sync/agent-refusal-retry.ts +54 -0
  54. package/src/sync/agent-request.ts +3 -1
  55. package/src/sync/agent-runner.ts +8 -6
  56. package/src/sync/agent-store.ts +32 -1
  57. package/src/sync/agent-sync.ts +63 -13
  58. package/src/sync/continuous-lease.ts +2 -7
  59. package/src/sync/continuous-record.ts +95 -13
  60. package/src/sync/continuous-storage.ts +12 -3
  61. package/src/sync/continuous-sync.ts +2 -1
  62. package/src/sync/merged-sync.ts +37 -9
  63. package/src/sync/sync-mutations.ts +11 -0
  64. package/src/ui/cancellable-operation.ts +2 -0
  65. package/src/ui/manager-state.ts +1 -0
  66. package/src/ui/manager-ui.ts +59 -14
  67. package/src/ui/secret-input.ts +29 -209
  68. package/dist/chunks/agent-plan-K3CRYVXV.ts.map +0 -7
  69. package/dist/chunks/agent-runner-E2JU2VZ6.ts.map +0 -7
  70. package/dist/chunks/agent-store-A3F6IYWZ.ts.map +0 -7
  71. package/dist/chunks/chunk-QGK445K7.ts.map +0 -7
  72. package/dist/chunks/chunk-QOC47PBC.ts +0 -97
  73. package/dist/chunks/chunk-QOC47PBC.ts.map +0 -7
  74. package/dist/chunks/chunk-QSHMOL3I.ts.map +0 -7
  75. package/dist/chunks/chunk-T3NC77TU.ts.map +0 -7
  76. package/dist/chunks/chunk-VJN7KU4J.ts.map +0 -7
  77. package/dist/chunks/manager-ui-KRAW3NE2.ts.map +0 -7
  78. package/dist/chunks/sync-operations-W5HFFMTP.ts.map +0 -7
  79. /package/dist/chunks/{chunk-OWBAZA6J.ts.map → chunk-DT6TOCIG.ts.map} +0 -0
  80. /package/dist/chunks/{chunk-OEWQVWLC.ts.map → chunk-ORGBI36T.ts.map} +0 -0
  81. /package/dist/chunks/{chunk-EUMINX7L.ts.map → chunk-P7DD5PWZ.ts.map} +0 -0
  82. /package/dist/chunks/{continuous-record-LFRVXQBD.ts.map → continuous-record-SQJ47CXN.ts.map} +0 -0
  83. /package/dist/chunks/{git-backend-KYDZ673X.ts.map → git-backend-NYKSG5X6.ts.map} +0 -0
  84. /package/dist/chunks/{manager-result-dispatcher-AGBBVDDS.ts.map → manager-result-dispatcher-HOCM2GDA.ts.map} +0 -0
  85. /package/dist/chunks/{remote-selection-ui-5725JDNC.ts.map → remote-selection-ui-YFPGYGNE.ts.map} +0 -0
  86. /package/dist/chunks/{s3-backend-Y7WSCLJI.ts.map → s3-backend-F7PR5FB3.ts.map} +0 -0
  87. /package/dist/chunks/{setup-wizard-65DROCIJ.ts.map → setup-wizard-OVHZYXNW.ts.map} +0 -0
  88. /package/dist/chunks/{sync-inspection-XFJOAMJD.ts.map → sync-inspection-5MY2HI4P.ts.map} +0 -0
  89. /package/dist/chunks/{webdav-backend-6K26F6LT.ts.map → webdav-backend-TGFUH3SF.ts.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/transfer-review.ts", "../../src/sync/apply-review.ts", "../../src/sync/field-migration.ts", "../../src/sync/sync-mutations.ts", "../../src/sync/sync-queries.ts"],
4
+ "sourcesContent": ["import type { ExtensionCommandContext, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { confirmMergeReview } from \"./merge-review.js\";\n\n/** Reuse the scrollable safe-default review in TUI; retain RPC's confirmation protocol. */\nexport async function confirmTransferReview(\n ctx: ExtensionCommandContext | ExtensionContext,\n title: string,\n content: string,\n signal: AbortSignal | undefined,\n validate: () => void,\n) {\n validate();\n const isCurrent = () => {\n try {\n validate();\n return true;\n } catch {\n return false;\n }\n };\n const confirmed =\n ctx.mode === \"tui\" && ctx.hasUI\n ? await confirmMergeReview(ctx, title, content, signal, isCurrent, \"apply reviewed transfer\", content.split(\"\\n\"))\n : await ctx.ui.confirm(title, content, { signal });\n validate();\n return confirmed;\n}\n", "import { createHash } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { agentDir } from \"../snapshot/session-paths.js\";\nimport { addTopLevelCaseVariantDeletes } from \"../snapshot/snapshot-apply.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { throwIfAborted } from \"./signals.js\";\n\nexport interface CaseCleanupReview {\n path: string;\n fingerprint: string;\n}\n\n/** Inspect the apply engine's additional alias removals, which logical snapshots omit. */\nexport async function inspectCaseCleanup(snapshot: Snapshot, signal?: AbortSignal): Promise<CaseCleanupReview[]> {\n throwIfAborted(signal);\n const root = agentDir();\n const plan = await addTopLevelCaseVariantDeletes(root, { writes: [], deletes: [] }, snapshot);\n throwIfAborted(signal);\n const review: CaseCleanupReview[] = [];\n for (const target of plan.deletes.sort()) {\n const stat = await fs.lstat(target);\n throwIfAborted(signal);\n const hash = createHash(\"sha256\");\n if (stat.isSymbolicLink()) hash.update(await fs.readlink(target));\n else {\n if (!stat.isFile()) throw new Error(\"Case-variant path is no longer a regular file or symlink.\");\n const handle = await fs.open(\n target,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0),\n );\n try {\n throwIfAborted(signal);\n const opened = await handle.stat();\n if (!opened.isFile() || opened.dev !== stat.dev || opened.ino !== stat.ino)\n throw new Error(\"Case-variant file changed while preparing review.\");\n for await (const bytes of handle.createReadStream({ autoClose: false, signal })) {\n throwIfAborted(signal);\n hash.update(bytes);\n }\n } finally {\n await handle.close();\n }\n }\n throwIfAborted(signal);\n review.push({\n path: path.basename(target),\n fingerprint: `${stat.dev}:${stat.ino}:${stat.mode}:${hash.digest(\"hex\")}`,\n });\n }\n return review;\n}\n\nexport async function revalidateCaseCleanup(\n expected: readonly CaseCleanupReview[],\n snapshot: Snapshot,\n signal?: AbortSignal,\n) {\n const current = await inspectCaseCleanup(snapshot, signal);\n if (JSON.stringify(current) !== JSON.stringify(expected))\n throw new Error(\"Case-variant paths changed during transfer review; reopen the preview.\");\n}\n", "import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\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 { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { sameLocalFields } from \"./local-fields.js\";\nimport { captureMutationOwner } from \"./sync-local.js\";\n\nexport async function confirmFieldMigration(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n state: SyncState,\n remote: Snapshot | undefined,\n force: boolean,\n signal?: AbortSignal,\n) {\n if (remote?.localFields !== undefined && config.localFields === undefined)\n throw new Error(\n \"Portable snapshots require settings version 4 and explicit localFields rules on this machine; older policy must not replace local-only values.\",\n );\n const changed =\n (Boolean(state.lastAppliedSnapshot) && !sameLocalFields(state.localFields, config.localFields)) ||\n (remote !== undefined && !sameLocalFields(remote.localFields, config.localFields));\n if (!changed) return true;\n if (!force)\n throw new Error(\n \"Local-field policy changed; review an explicit push --force or pull --force migration. Old remote history is not erased.\",\n );\n const validate = captureMutationOwner(ctx, signal);\n if (!ctx.hasUI) throw new Error(\"Local-field migration requires observable TUI/RPC confirmation.\");\n validate();\n const confirmed = await ctx.ui.confirm(\n \"Migrate portable settings policy?\",\n `New machine-local fields: ${(config.localFields ?? []).map(safeTerminalText).join(\", \") || \"none\"}. Additions remove fields from future snapshots, not old history. Removals make local-only values portable again and a pull may replace them. The selected direction is authoritative; inspect /sync diff first. This confirmation is required even with --yes.`,\n { signal },\n );\n validate();\n return confirmed;\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 PublishSnapshotResult,\n type RemoteHead,\n type SyncBackend,\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 { sessionDirForApply, snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport {\n createSnapshot,\n filterSnapshotForConfigPolicy,\n mergeRemotePreservedFiles,\n regenerateSnapshotIdentity,\n scanSnapshot,\n snapshotIncludesSessions,\n snapshotWithoutSessions,\n} from \"../snapshot/snapshot.js\";\nimport { applySnapshot } from \"../snapshot/snapshot-apply.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { pruneMergeBaselines } from \"../state/merge-baseline-store.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { readStateForConfig, syncStateFingerprint, writeStateForConfig } from \"../state/sync-state-store.js\";\nimport {\n countPreservedRemoteFiles,\n formatPullSummary,\n formatPushSummary,\n formatRollbackSummary,\n} from \"../ui/sync-format.js\";\nimport { setSyncStatus } from \"../ui/sync-status.js\";\nimport { confirmTransferReview } from \"../ui/transfer-review.js\";\nimport { startupTransferEnabled } from \"./agent-policy.js\";\nimport { inspectCaseCleanup, revalidateCaseCleanup } from \"./apply-review.js\";\nimport { confirmFieldMigration } from \"./field-migration.js\";\nimport { overlayLocalFields, portableSnapshot, sameLocalFields, validatePortableSnapshot } from \"./local-fields.js\";\nimport { readMergeJournal, requireNoMergeJournal, retireMergeJournal } from \"./merge-journal.js\";\nimport { mergeSync } from \"./merged-sync.js\";\nimport { readRemoteSnapshot, readSnapshotForHead, requireCompatibleRemoteSelection } from \"./remote-snapshot.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { createSyncDecision } from \"./sync-decision.js\";\nimport { errorMessage } from \"./sync-errors.js\";\n\nimport { backupLocal, captureMutationOwner, protectedSessionPaths } from \"./sync-local.js\";\nimport { inspectRemoteSelection } from \"./sync-policy.js\";\nimport {\n canPullRemoteSessionsOnFirstSync,\n canPullRemoteSettingsOnFirstSync,\n fileHashMap,\n hasLocalChanges,\n hasRemoteChanges,\n remoteChangedSinceState,\n sameHashes,\n shouldRefreshSyncedState,\n snapshotHashesMatchState,\n snapshotsMatch,\n syncPolicyChanged,\n} from \"./sync-state.js\";\n\nconst VERSION = 1;\nconst POST_LOCAL_COMMIT_TIMEOUT_MS = 30_000;\n\n/** Whole-direction acceptance must never forget withheld state without an explicit recovery choice. */\nfunction requireResolvedDirectionalProgress(state: SyncState, options: CommandOptions, allowForce = true) {\n if (state.unresolved?.length && (options.auto || !options.force || !allowForce))\n throw new Error(\n \"Unresolved partial conflicts remain. Review /sync conflicts or explicitly choose push --force or pull --force; automatic transfer and rollback cannot accept unresolved groups.\",\n );\n}\n\nexport class PublicationStatePersistenceError extends Error {\n readonly head: RemoteHead;\n readonly backupPath?: string;\n\n constructor(head: RemoteHead, cause: unknown, backupPath?: string) {\n super(\n `Remote publication ${head.snapshotId} is active, but local sync state could not be saved${backupPath ? `; local backup: ${backupPath}` : \"\"}: ${errorMessage(cause)}`,\n { cause },\n );\n this.name = \"PublicationStatePersistenceError\";\n this.head = head;\n this.backupPath = backupPath;\n }\n}\n\nexport class RollbackPublicationError extends Error {\n readonly backupPath: string;\n\n constructor(backupPath: string, cause: unknown) {\n super(`Rollback applied locally with backup ${backupPath}, but remote publication failed: ${errorMessage(cause)}`, {\n cause,\n });\n this.name = \"RollbackPublicationError\";\n this.backupPath = backupPath;\n }\n}\n\ninterface PushInput {\n config: AnySyncConfig;\n state: SyncState;\n local: Snapshot;\n backend?: SyncBackend;\n}\n\nexport async function push(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n input?: PushInput,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const config = input?.config ?? (await loadConfig(options.setup));\n throwIfAborted(options.signal);\n await requireNoMergeJournal(config, options);\n const state = input?.state ?? (await readStateForConfig(config));\n validateMutation();\n requireResolvedDirectionalProgress(state, options);\n setSyncStatus(ctx, `pushing ${config.setupName}`);\n const backend = input?.backend ?? (await factory(config));\n throwIfAborted(options.signal);\n const localRaw =\n input?.local ?? (await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)));\n const local = portableSnapshot(localRaw, config.localFields);\n throwIfAborted(options.signal);\n\n let head = await backend.readHead(options.signal);\n let remoteForUpload = await readRemoteSnapshotForUpload(backend, config, head, state, options.signal);\n if (\n !options.force &&\n !remoteForUpload &&\n head?.selection &&\n inspectRemoteSelection(config.include, { selection: head.selection, files: [] }).kind === \"different\"\n ) {\n remoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n }\n if (remoteForUpload && !options.force) {\n requireCompatibleRemoteSelection(config, remoteForUpload);\n }\n if (\n remoteChangedSinceState(head, state, config, (left, right) => backend.sameRevision(left, right)) &&\n !options.force\n ) {\n const remoteForConflict = remoteForUpload ? filterSnapshotForConfigPolicy(remoteForUpload, config) : undefined;\n if (!remoteForConflict || !snapshotHashesMatchState(remoteForConflict, state, config)) {\n throw createSyncDecision({\n kind: head ? \"remote-or-policy-changed\" : \"remote-empty\",\n config,\n state,\n local,\n remote: remoteForConflict,\n localChanged: hasLocalChanges(local, state, config),\n remoteChanged: true,\n directMessage: \"Remote or sync policy changed since last sync. Run /sync pull first or /sync push --force.\",\n });\n }\n }\n\n if (!remoteForUpload && head && (config.localFields !== undefined || !options.yes))\n remoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n if (!(await confirmFieldMigration(ctx, config, state, remoteForUpload, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n const configIdentity = syncCheckConfigFingerprint(config);\n let upload = await snapshotForUpload(backend, config, local, head, remoteForUpload, options.signal);\n if (!config.skipSecretScan) {\n const secrets = scanSnapshot(local);\n if (secrets.length > 0) {\n throw new Error(`Refusing to push possible secrets:\\n${secrets.map((s) => `- ${s}`).join(\"\\n\")}`);\n }\n }\n\n if (!(await confirmPush(ctx, options, config, backend, local, upload, head, remoteForUpload))) {\n return \"cancelled\" as const;\n }\n\n if (options.force) {\n const refreshedHead = await backend.readHead(options.signal);\n if (!sameRemoteHead(backend, head, refreshedHead)) {\n head = refreshedHead;\n remoteForUpload = head ? await readSnapshotForHead(backend, head, options.signal) : undefined;\n validateMutation();\n if (!(await confirmFieldMigration(ctx, config, state, remoteForUpload, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n validateMutation();\n upload = await snapshotForUpload(backend, config, local, head, remoteForUpload, options.signal);\n if (\n !(await confirmPush(\n ctx,\n options,\n config,\n backend,\n local,\n upload,\n head,\n remoteForUpload,\n \"Remote changed during review. Push the refreshed plan?\",\n ))\n ) {\n return \"cancelled\" as const;\n }\n }\n }\n\n validateMutation();\n if (configIdentity !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during push review.\");\n validateMutation();\n if (!options.yes || config.localFields !== undefined || (await readMergeJournal(config))) {\n const current = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(current), fileHashMap(localRaw)))\n throw new Error(\"Local content changed during push review; retry from current bytes.\");\n }\n const currentState = await readStateForConfig(config);\n if (!options.yes && syncStateFingerprint(currentState) !== syncStateFingerprint(state))\n throw new Error(\"Baseline changed during push review.\");\n requireResolvedDirectionalProgress(currentState, options);\n validateMutation();\n const result = await backend.publishSnapshot(upload, expectedRemoteHead(head), {\n signal: options.signal,\n onCommit: options.onCommit,\n });\n try {\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: result.head.snapshotId,\n lastRemoteRevision: result.head.revision,\n lastFileHashes: fileHashMap(local),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n local,\n validateCommittedOwner,\n );\n } catch (error) {\n throw new PublicationStatePersistenceError(result.head, error);\n }\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return;\n setSyncStatus(ctx, undefined);\n if (!options.silent) {\n ctx.ui.notify(\n [\n `Pushed ${upload.files.length} files from sync setup \u201C${config.setupName}\u201D as ${result.head.snapshotId}.`,\n ...result.warnings,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n result.warnings.length > 0 ? \"warning\" : \"info\",\n );\n }\n return \"applied\" as const;\n}\n\nexport async function pull(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n await requireNoMergeJournal(config, options);\n setSyncStatus(ctx, `pulling ${config.setupName}`);\n const backend = await factory(config);\n const state = await readStateForConfig(config);\n validateMutation();\n requireResolvedDirectionalProgress(state, options);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n throwIfAborted(options.signal);\n const { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n throwIfAborted(options.signal);\n const localChanged = hasLocalChanges(local, state, config);\n if (!remote) {\n throw createSyncDecision({\n kind: \"remote-empty\",\n config,\n state,\n local,\n localChanged,\n remoteChanged: false,\n directMessage: \"Remote is empty. Run /sync push from a configured machine first.\",\n });\n }\n\n if (!sameLocalFields(config.localFields, remote.localFields)) {\n setSyncStatus(ctx, undefined);\n throw new Error(\n \"Pull requires the configured local-field policy to match the remote. To change the remote policy, review push --force from the authoritative machine first, then pull using matching rules; old history is not erased.\",\n );\n }\n if (!(await confirmFieldMigration(ctx, config, state, remote, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n const configIdentity = syncCheckConfigFingerprint(config);\n const logical = portableSnapshot(remote, config.localFields);\n const physical = overlayLocalFields(logical, local, config.localFields);\n const remoteChanged = hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx));\n if (localChanged && remoteChanged && state.lastAppliedSnapshot && !options.force) {\n throw createSyncDecision({\n kind: \"both-changed\",\n config,\n state,\n local,\n remote,\n localChanged,\n remoteChanged,\n directMessage:\n \"Both local and remote changed since last sync. Run /sync diff, then choose /sync pull --force or /sync push --force.\",\n });\n }\n\n const caseCleanup = options.yes ? [] : await inspectCaseCleanup(physical, options.signal);\n validateMutation();\n if (\n !options.yes &&\n !(await confirmTransferReview(\n ctx,\n snapshotIncludesSessions(remote) ? \"Pull pi settings and sessions?\" : \"Pull pi settings?\",\n formatPullSummary(\n config,\n backend.destination,\n local,\n physical,\n protectedSessionPaths(ctx),\n caseCleanup.map((item) => item.path),\n ),\n options.signal,\n validateMutation,\n ))\n ) {\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\"Pull cancelled.\", \"info\");\n return \"cancelled\" as const;\n }\n\n throwIfAborted(options.signal);\n const recoveringMerge = Boolean(await readMergeJournal(config));\n const requireFreshRecovery = async () => {\n validateMutation();\n const currentHead = await backend.readHead(options.signal);\n validateMutation();\n const current = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n validateMutation();\n if (!sameHashes(fileHashMap(current), fileHashMap(local)) || !sameRemoteHead(backend, head, currentHead)) {\n throw new Error(\"Local or remote content changed during recovery review; retry from a fresh diff.\");\n }\n };\n if (recoveringMerge) await requireFreshRecovery();\n if (configIdentity !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during pull review.\");\n validateMutation();\n const refreshed = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(local), fileHashMap(refreshed)))\n throw new Error(\"Local bytes changed during pull review.\");\n if (!sameRemoteHead(backend, head, await backend.readHead(options.signal)))\n throw new Error(\"Remote changed during pull review.\");\n validateMutation();\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptionsForContext(ctx, config), options.signal);\n const applySessionDir = await sessionDirForApply(ctx, physical);\n if (recoveringMerge) await requireFreshRecovery();\n const currentState = await readStateForConfig(config);\n if (!options.yes && syncStateFingerprint(currentState) !== syncStateFingerprint(state))\n throw new Error(\"Baseline changed during pull review.\");\n requireResolvedDirectionalProgress(currentState, options);\n if (!options.yes) await revalidateCaseCleanup(caseCleanup, physical, options.signal);\n validateMutation();\n options.onCommit?.();\n const lastFileHashes = await applySnapshot(physical, protectedSessionPaths(ctx), {\n include: config.include,\n sessionDir: applySessionDir,\n signal: options.signal,\n validateMutation,\n expectedFileHashes: config.localFields?.length\n ? { \"settings.json\": fileHashMap(local)[\"settings.json\"] ?? null }\n : undefined,\n });\n // Local installation is complete; user cancellation must not leave the baseline stale.\n validateCommittedOwner();\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: remote.id,\n lastRemoteRevision: head?.revision,\n lastFileHashes: config.localFields?.length\n ? { ...lastFileHashes, \"settings.json\": fileHashMap(logical)[\"settings.json\"] }\n : lastFileHashes,\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n logical,\n validateCommittedOwner,\n );\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return \"applied\" as const;\n setSyncStatus(ctx, undefined);\n if (!options.silent) {\n ctx.ui.notify(`Pulled ${remote.files.length} files from ${remote.id}. Backup: ${backup}`, \"info\");\n } else if (options.auto && config.include.includes(\"sessions\") && snapshotIncludesSessions(remote)) {\n ctx.ui.notify(\n \"Pulled Pi sessions after startup selected the current session. Restart Pi or resume a pulled session to use newly synced conversations.\",\n \"warning\",\n );\n }\n if (options.reload) await maybeReload(ctx, options.signal, validateMutation);\n return \"applied\" as const;\n}\n\nexport async function syncBoth(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n options.background?.validate(config);\n if (options.agentRetryRefusal) {\n if (!config.agentMode || options.auto || options.background || !ctx.hasUI)\n throw new Error(\"Enable Agent mode and use the foreground manager to retry a cached refusal.\");\n const state = await readStateForConfig(config);\n validateMutation();\n const pending = await readMergeJournal(config);\n validateMutation();\n if (!config.include.length || !state.lastAppliedSnapshot || pending)\n throw new Error(\"Retry requires an accepted baseline and no pending journal. Use Sync now or reviewed recovery.\");\n return mergeSync(ctx, options, factory);\n }\n if (config.include.length > 0 && options.auto && startupTransferEnabled(config))\n return mergeSync(ctx, options, factory);\n if (!options.auto && config.include.length > 0 && (await readMergeJournal(config)))\n return mergeSync(ctx, options, factory);\n const state = await readStateForConfig(config);\n throwIfAborted(options.signal);\n if (!options.auto && config.include.length > 0 && state.lastAppliedSnapshot) return mergeSync(ctx, options, factory);\n const backend = await factory(config);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n throwIfAborted(options.signal);\n if (config.include.length === 0) {\n if (!options.silent) {\n ctx.ui.notify(\n `Sync setup \u201C${config.setupName}\u201D includes no files. Choose included content in /sync Settings before syncing.`,\n \"warning\",\n );\n }\n return;\n }\n const { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n throwIfAborted(options.signal);\n const localChanged = hasLocalChanges(local, state, config);\n const remoteChanged = remote ? hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx)) : false;\n if (options.auto) throw new Error(\"Automatic transfer is not authorized by the current settings.\");\n\n // Established baselines return through mergeSync above; only initial-source selection remains.\n const portableLocal = portableSnapshot(local, config.localFields);\n const acceptMatchingState = async (snapshot: Snapshot) => {\n requireCompatibleRemoteSelection(config, snapshot);\n const accepted = portableSnapshot(snapshot, config.localFields);\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: snapshot.id,\n lastRemoteRevision: head?.revision,\n lastFileHashes: fileHashMap(accepted),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n accepted,\n validateMutation,\n );\n await pruneMergeBaselines(config, await readStateForConfig(config), validateMutation);\n validateMutation();\n };\n if (remote && remote.files.length > 0 && local.files.length > 0) {\n requireCompatibleRemoteSelection(config, remote);\n const portableRemote = portableSnapshot(remote, config.localFields);\n if (!canPullRemoteSettingsOnFirstSync(portableLocal, portableRemote)) {\n throw createSyncDecision({\n kind: \"first-sync-settings-diverged\",\n config,\n state,\n local,\n remote,\n localChanged: true,\n remoteChanged: true,\n directMessage:\n \"Remote settings exist and this machine has different local Pi settings. Run /sync diff, then manually choose /sync pull or /sync push.\",\n });\n }\n if (!sameHashes(fileHashMap(portableLocal), fileHashMap(portableRemote))) {\n if (!canPullRemoteSessionsOnFirstSync(portableLocal, portableRemote)) {\n throw createSyncDecision({\n kind: \"first-sync-sessions-diverged\",\n config,\n state,\n local,\n remote,\n localChanged: true,\n remoteChanged: true,\n directMessage:\n \"Remote settings match, but local and remote Pi sessions differ. Run /sync diff, then manually choose /sync pull or /sync push.\",\n });\n }\n await pull(ctx, options, factory);\n return;\n }\n await acceptMatchingState(remote);\n if (!options.silent) ctx.ui.notify(\"pi-sync state initialized; local settings already match remote.\", \"info\");\n return;\n }\n if (\n localChanged &&\n remoteChanged &&\n remote &&\n snapshotsMatch(portableLocal, portableSnapshot(remote, remote.localFields))\n ) {\n requireCompatibleRemoteSelection(config, remote);\n await acceptMatchingState(remote);\n if (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n return;\n }\n if (remoteChanged) {\n await pull(ctx, options, factory);\n return;\n }\n if (localChanged || !remote) {\n await push(ctx, options, undefined, factory);\n return;\n }\n if (shouldRefreshSyncedState(remote, head, state, config, (left, right) => backend.sameRevision(left, right))) {\n await acceptMatchingState(remote);\n }\n if (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n}\n\nexport async function rollback(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n expectedSelection?: { backendIdentity: string; setup?: string },\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const target = options.args[0];\n if (!target) throw new Error(\"Usage: /sync rollback <snapshot-id> [--yes]\");\n\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n const backend = await factory(config);\n if (\n expectedSelection &&\n (backend.identity !== expectedSelection.backendIdentity || config.setupName !== expectedSelection.setup)\n ) {\n throw new Error(\"Sync setup or storage location changed while history was open; reopen history and retry.\");\n }\n // --force is only a rollback compatibility flag, not a reviewed merge-recovery direction.\n await requireNoMergeJournal(config);\n const state = await readStateForConfig(config);\n validateMutation();\n requireResolvedDirectionalProgress(state, options, false);\n const decoded = await backend.readSnapshot(target, options.signal);\n validatePortableSnapshot(decoded);\n if (!sameLocalFields(decoded.localFields, config.localFields))\n throw new Error(\n \"Rollback requires the historical snapshot local-field policy to match the configured rules. Review push --force from current local bytes to migrate policy first; choose matching history afterward.\",\n );\n const selected = filterSnapshotForConfigPolicy(\n config.include.includes(\"sessions\") ? decoded : snapshotWithoutSessions(decoded),\n config,\n );\n const remote = portableSnapshot(regenerateSnapshotIdentity(selected), config.localFields);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n const expectedHead = await backend.readHead(options.signal);\n const currentRemote = expectedHead ? await readSnapshotForHead(backend, expectedHead, options.signal) : undefined;\n validateMutation();\n if (!(await confirmFieldMigration(ctx, config, state, currentRemote, true, options.signal))) return;\n validateMutation();\n const physical = overlayLocalFields(remote, local, config.localFields);\n const caseCleanup = options.yes ? [] : await inspectCaseCleanup(physical, options.signal);\n validateMutation();\n\n if (!options.yes) {\n const confirmed = await ctx.ui.confirm(\n snapshotIncludesSessions(remote) ? \"Rollback pi settings and sessions?\" : \"Rollback pi settings?\",\n formatRollbackSummary(\n config,\n backend.destination,\n local,\n physical,\n target,\n protectedSessionPaths(ctx),\n caseCleanup.map((item) => item.path),\n ),\n { signal: options.signal },\n );\n validateMutation();\n if (!confirmed) {\n ctx.ui.notify(\"Rollback cancelled.\", \"info\");\n return;\n }\n }\n\n validateMutation();\n const currentLocal = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(currentLocal), fileHashMap(local)))\n throw new Error(\"Local bytes changed during rollback review.\");\n if (syncCheckConfigFingerprint(config) !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during rollback review.\");\n if (!sameRemoteHead(backend, expectedHead, await backend.readHead(options.signal)))\n throw new Error(\"Remote changed during rollback review.\");\n validateMutation();\n throwIfAborted(options.signal);\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptionsForContext(ctx, config), options.signal);\n const applySessionDir = await sessionDirForApply(ctx, remote);\n const currentState = await readStateForConfig(config);\n if (!options.yes && syncStateFingerprint(currentState) !== syncStateFingerprint(state))\n throw new Error(\"Baseline changed during rollback review.\");\n requireResolvedDirectionalProgress(currentState, options, false);\n if (!options.yes) await revalidateCaseCleanup(caseCleanup, physical, options.signal);\n validateMutation();\n options.onCommit?.();\n const lastFileHashes = await applySnapshot(physical, protectedSessionPaths(ctx), {\n include: config.include,\n sessionDir: applySessionDir,\n signal: options.signal,\n validateMutation,\n expectedFileHashes: config.localFields?.length\n ? { \"settings.json\": fileHashMap(local)[\"settings.json\"] ?? null }\n : undefined,\n });\n // The local transaction is retired; finish publication despite caller cancellation.\n validateCommittedOwner();\n let result: PublishSnapshotResult;\n try {\n const completionSignal = AbortSignal.timeout(POST_LOCAL_COMMIT_TIMEOUT_MS);\n const upload = await snapshotForUpload(backend, config, remote, expectedHead, currentRemote, completionSignal);\n validateCommittedOwner();\n result = await backend.publishSnapshot(upload, expectedRemoteHead(expectedHead), {\n signal: completionSignal,\n });\n } catch (error) {\n throw new RollbackPublicationError(backup, error);\n }\n try {\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: result.head.snapshotId,\n lastRemoteRevision: result.head.revision,\n lastFileHashes: config.localFields?.length\n ? { ...lastFileHashes, \"settings.json\": fileHashMap(remote)[\"settings.json\"] }\n : lastFileHashes,\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n remote,\n validateCommittedOwner,\n );\n } catch (error) {\n throw new PublicationStatePersistenceError(result.head, error, backup);\n }\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return;\n ctx.ui.notify(\n [\n `Rolled back sync setup \u201C${config.setupName}\u201D to ${target}; latest: ${result.head.snapshotId}. Backup: ${backup}`,\n ...result.warnings,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n result.warnings.length > 0 ? \"warning\" : \"info\",\n );\n await maybeReload(ctx, options.signal, validateMutation);\n}\n\nasync function maybeReload(\n ctx: ExtensionCommandContext | ExtensionContext,\n signal?: AbortSignal,\n validateMutation = captureMutationOwner(ctx, signal),\n) {\n if (signal?.aborted || !(\"reload\" in ctx)) return;\n validateMutation();\n if (\n ctx.hasUI &&\n (await ctx.ui.confirm(\n \"Reload Pi resources now?\",\n \"This reloads extensions, skills, prompts, themes, and context files.\",\n ))\n ) {\n if (signal?.aborted) return;\n validateMutation();\n await ctx.reload();\n }\n}\n\nasync function readRemoteSnapshotForUpload(\n backend: SyncBackend,\n config: AnySyncConfig,\n head: RemoteHead | undefined,\n state: SyncState,\n signal?: AbortSignal,\n) {\n if (\n !head ||\n (head.snapshotId === state.lastAppliedSnapshot &&\n !syncPolicyChanged(state, config) &&\n (!state.lastRemoteRevision || backend.sameRevision(head.revision, state.lastRemoteRevision)))\n ) {\n return undefined;\n }\n return readSnapshotForHead(backend, head, signal);\n}\n\nasync function snapshotForUpload(\n backend: SyncBackend,\n config: AnySyncConfig,\n local: Snapshot,\n head: RemoteHead | undefined,\n remote?: Snapshot,\n signal?: AbortSignal,\n) {\n if (!head) return local;\n const snapshot = remote ?? (await readSnapshotForHead(backend, head, signal));\n return mergeRemotePreservedFiles(local, snapshot, config);\n}\n\nasync function confirmPush(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n config: AnySyncConfig,\n backend: SyncBackend,\n local: Snapshot,\n upload: Snapshot,\n head: RemoteHead | undefined,\n remote: Snapshot | undefined,\n title = snapshotIncludesSessions(upload) ? \"Push pi settings and sessions?\" : \"Push pi settings?\",\n) {\n throwIfAborted(options.signal);\n if (options.yes) return true;\n const confirmed = await confirmTransferReview(\n ctx,\n title,\n formatPushSummary(config, backend.destination, upload, head, countPreservedRemoteFiles(local, upload), remote),\n options.signal,\n captureMutationOwner(ctx, options.signal),\n );\n throwIfAborted(options.signal);\n if (confirmed) return true;\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\"Push cancelled.\", \"info\");\n return false;\n}\n\nfunction sameRemoteHead(backend: SyncBackend, left: RemoteHead | undefined, right: RemoteHead | undefined) {\n if (!left || !right) return left === right;\n return backend.sameRevision(left.revision, right.revision);\n}\n\nexport { backupLocal } from \"./sync-local.js\";\n", "import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { SyncBackend } from \"../backends/sync-backend.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncSessionsWarnings } from \"../settings/config.js\";\nimport { snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport { createSnapshot, scanSnapshot } from \"../snapshot/snapshot.js\";\nimport type { SnapshotOptions } from \"../snapshot/snapshot-types.js\";\nimport { inspectLock, isLockGuardHeld, isStaleLock, withLock } from \"../state/lock.js\";\nimport { readStateForConfig } from \"../state/sync-state-store.js\";\nimport { formatDiff, formatSnapshotOnlyDiff, publicationCapabilityDescription } from \"../ui/sync-format.js\";\nimport { setSyncStatus } from \"../ui/sync-status.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { portableSnapshot } from \"./local-fields.js\";\nimport { formatRemoteSelectionStatus, readRemoteSnapshot } from \"./remote-snapshot.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { errorMessage } from \"./sync-errors.js\";\nimport { inspectSync } from \"./sync-inspection.js\";\nimport { rollback } from \"./sync-mutations.js\";\n\nconst DEFAULT_PROFILE = \"default\";\n\nexport async function status(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n setSyncStatus(ctx, `checking ${config.setupName}`);\n const { head, selectionState, localChanged, remoteChanged, localFiles, destination, capability } = await inspectSync(\n config,\n snapshotOptionsForContext(ctx, config),\n options.signal,\n factory,\n );\n throwIfAborted(options.signal);\n\n const continuous = config.continuous\n ? await (await import(\"./continuous-record.js\")).continuousStatusLines(config)\n : [];\n throwIfAborted(options.signal);\n const remoteText = head ? `remote: ${head.snapshotId} from ${head.machine} at ${head.createdAt}` : \"remote: empty\";\n const warnings = syncSessionsWarnings(config);\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\n [\n `sync setup: ${config.setupName}`,\n `storage connection: ${config.connectionName}`,\n `storage location: ${safeTerminalText(destination)}`,\n `publication safety: ${publicationCapabilityDescription(capability)}`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n ...continuous,\n remoteText,\n formatRemoteSelectionStatus(selectionState),\n `local files: ${localFiles}`,\n `local changed since last sync: ${localChanged ? \"yes\" : \"no\"}`,\n `remote changed since last sync: ${remoteChanged ? \"yes\" : \"no\"}`,\n ...warnings,\n ].join(\"\\n\"),\n localChanged || remoteChanged || selectionState?.kind === \"different\" || warnings.length > 0 ? \"warning\" : \"info\",\n );\n}\n\nexport async function diff(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n setSyncStatus(ctx, `checking ${config.setupName}`);\n const backend = await factory(config);\n const local = portableSnapshot(\n await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)),\n config.localFields,\n );\n throwIfAborted(options.signal);\n const { snapshot: remote, selectionState } = await readRemoteSnapshot(backend, config, options.signal, {\n allowSelectionDifference: true,\n });\n throwIfAborted(options.signal);\n setSyncStatus(ctx, undefined);\n\n const warnings = syncSessionsWarnings(config);\n const header = [\n `sync setup: ${config.setupName}`,\n `storage connection: ${config.connectionName}`,\n `storage location: ${safeTerminalText(backend.destination)}`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n formatRemoteSelectionStatus(selectionState),\n ...warnings,\n ].join(\"\\n\");\n const level = warnings.length > 0 || selectionState?.kind === \"different\" ? \"warning\" : \"info\";\n if (!remote) {\n ctx.ui.notify(`${header}\\n\\n${formatSnapshotOnlyDiff(\"Remote is empty. Local push would upload\", local)}`, level);\n return;\n }\n\n ctx.ui.notify(`${header}\\n\\n${formatDiff(local, portableSnapshot(remote, remote.localFields))}`, level);\n}\n\nexport async function doctor(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const messages: string[] = [];\n let level: \"info\" | \"warning\" = \"info\";\n let snapshotOptions: SnapshotOptions = {};\n let profile = DEFAULT_PROFILE;\n let backend: SyncBackend | undefined;\n let backendSummary: string[] = [];\n\n try {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n backend = await factory(config);\n profile = config.snapshotIdentity;\n snapshotOptions = snapshotOptionsForContext(ctx, config);\n messages.push(\n `config: ok (sync setup ${config.setupName})`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n );\n backendSummary = [\n `storage location: ${safeTerminalText(backend.destination)}`,\n `publication safety: ${publicationCapabilityDescription(backend.capability)}`,\n ];\n const warnings = syncSessionsWarnings(config);\n if (warnings.length > 0) {\n level = \"warning\";\n messages.push(...warnings);\n }\n } catch (error) {\n throwIfAborted(options.signal);\n level = \"warning\";\n messages.push(`config: ${errorMessage(error)}`);\n }\n\n const local = await createSnapshot(profile, snapshotOptions);\n throwIfAborted(options.signal);\n const secrets = scanSnapshot(local);\n if (secrets.length > 0) {\n level = \"warning\";\n messages.push(\"secret scan: possible secrets found:\");\n messages.push(...secrets.map((secret) => `- ${secret}`));\n } else {\n messages.push(`secret scan: ok (${local.files.length} files checked)`);\n }\n\n const lock = await inspectLock();\n throwIfAborted(options.signal);\n if (lock.status === \"valid\" && isStaleLock(lock.lock)) {\n level = \"warning\";\n messages.push(`lock: stale (pid ${lock.lock.pid}); run /sync unlock --stale after verifying no sync is running`);\n } else if (lock.status === \"valid\") {\n messages.push(`lock: held by pid ${lock.lock.pid} since ${lock.lock.startedAt}`);\n } else if (lock.status === \"unreadable\") {\n level = \"warning\";\n messages.push(\"lock: unreadable; use /sync unlock --stale only after verifying no sync is running\");\n } else if (await isLockGuardHeld()) {\n throwIfAborted(options.signal);\n level = \"warning\";\n messages.push(\"lock: guard active while metadata is missing or still being initialized\");\n } else {\n messages.push(\"lock: free\");\n }\n\n if (backend) {\n messages.push(...backendSummary);\n const diagnostics = await backend.diagnose(options.signal);\n throwIfAborted(options.signal);\n for (const diagnostic of diagnostics) {\n messages.push(diagnostic.message);\n if (diagnostic.level !== \"info\") level = \"warning\";\n }\n }\n ctx.ui.notify(messages.join(\"\\n\"), level);\n}\n\nexport async function history(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n const backend = await factory(config);\n const snapshots = (await backend.listHistory(options.signal)).slice(-20).reverse();\n throwIfAborted(options.signal);\n const lastApplied = await readStateForConfig(config)\n .then((state) => state.lastAppliedSnapshot)\n .catch(() => undefined);\n throwIfAborted(options.signal);\n const appliedDetails = lastApplied\n ? `Last applied snapshot ID: ${safeTerminalText(lastApplied)}\\nApplication time: unavailable. Snapshot dates are creation times.`\n : \"Last applied snapshot ID: unavailable.\";\n if (snapshots.length === 0) {\n ctx.ui.notify(`No remote pi-sync history found.\\n${appliedDetails}`, \"info\");\n return;\n }\n\n const currentSnapshot = snapshots[0]?.snapshotId;\n if (ctx.mode === \"tui\") {\n const labels = snapshots.map(\n (item, index) =>\n `${index + 1}. ${item.createdAt} \u00B7 ${safeTerminalText(item.machine)} \u00B7 ${item.snapshotId}${item.snapshotId === currentSnapshot ? \" (current)\" : \"\"}${item.syncSessions ? \" \u00B7 sessions\" : \"\"}`,\n );\n const selected = await ctx.ui.select(\n `History for sync setup \u201C${safeTerminalText(config.setupName)}\u201D\\n\\n${appliedDetails}\\n\\nChoose a snapshot to preview rollback.`,\n [...labels, \"Back\"],\n { signal: options.signal },\n );\n if (!selected || selected === \"Back\") return;\n throwIfAborted(options.signal);\n const index = labels.indexOf(selected);\n const snapshot = snapshots[index];\n if (!snapshot) return;\n await withLock(\"rollback\", () =>\n rollback(ctx, { ...options, args: [snapshot.snapshotRef], yes: false }, factory, {\n backendIdentity: backend.identity,\n setup: config.setupName,\n }),\n );\n return;\n }\n ctx.ui.notify(\n [\n appliedDetails,\n ...snapshots.map((item) => `${item.snapshotRef} ${item.createdAt} ${safeTerminalText(item.machine)}`),\n ].join(\"\\n\"),\n \"info\",\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["state", "index"]
7
+ }
@@ -15,9 +15,6 @@ import "./chunk-7D5SF7P3.ts";
15
15
  import {
16
16
  validatePortableSnapshot
17
17
  } from "./chunk-A6HU4ERM.ts";
18
- import {
19
- throwIfAborted
20
- } from "./chunk-PWMWOJP4.ts";
21
18
  import {
22
19
  ContinuousError,
23
20
  continuousFailure,
@@ -27,6 +24,9 @@ import {
27
24
  SyncBackendConflictError,
28
25
  SyncBackendPublicationOutcomeUnknownError
29
26
  } from "./chunk-YDVQYUHE.ts";
27
+ import {
28
+ throwIfAborted
29
+ } from "./chunk-PWMWOJP4.ts";
30
30
  import {
31
31
  portableSnapshotSelection
32
32
  } from "./chunk-QOFMXPM5.ts";
@@ -845,4 +845,4 @@ export {
845
845
  snapshotsPath,
846
846
  webDavBackendIdentity
847
847
  };
848
- //# sourceMappingURL=webdav-backend-6K26F6LT.ts.map
848
+ //# sourceMappingURL=webdav-backend-TGFUH3SF.ts.map
package/dist/index.ts CHANGED
@@ -2,18 +2,19 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  withAgentSyncLock
5
- } from "./chunks/chunk-QOC47PBC.ts";
5
+ } from "./chunks/chunk-WD6FJHCK.ts";
6
+ import "./chunks/chunk-3ST7RSYN.ts";
6
7
  import {
7
8
  recoverSnapshotTransactionsOnStartup
8
9
  } from "./chunks/chunk-CRKTAPSL.ts";
10
+ import {
11
+ createStartupTimings
12
+ } from "./chunks/chunk-UZPMDLTL.ts";
9
13
  import {
10
14
  createSyncAttentionController,
11
15
  observationMatchesConfig,
12
16
  syncAttentionMatchesConfig
13
17
  } from "./chunks/chunk-GSNPASKB.ts";
14
- import {
15
- captureMutationOwner
16
- } from "./chunks/chunk-UOHR7LRO.ts";
17
18
  import {
18
19
  automaticSyncSummary
19
20
  } from "./chunks/chunk-ECYCNZOE.ts";
@@ -31,12 +32,12 @@ import {
31
32
  usage,
32
33
  validateCommandOptions
33
34
  } from "./chunks/chunk-NLWS55B6.ts";
35
+ import {
36
+ captureMutationOwner
37
+ } from "./chunks/chunk-UOHR7LRO.ts";
34
38
  import {
35
39
  safeTerminalText
36
40
  } from "./chunks/chunk-AMJRUXFT.ts";
37
- import {
38
- createStartupTimings
39
- } from "./chunks/chunk-UZPMDLTL.ts";
40
41
  import "./chunks/chunk-UBV24CG4.ts";
41
42
  import {
42
43
  syncErrorGuidance
@@ -46,7 +47,6 @@ import {
46
47
  errorMessage,
47
48
  isSyncDecisionRequiredError
48
49
  } from "./chunks/chunk-7D5SF7P3.ts";
49
- import "./chunks/chunk-QGK445K7.ts";
50
50
  import {
51
51
  activeLocalConfigPath,
52
52
  consumeLocalConfigMigrationNotice,
@@ -66,12 +66,12 @@ import {
66
66
  unlock,
67
67
  withLock
68
68
  } from "./chunks/chunk-AAEEHR7H.ts";
69
+ import "./chunks/chunk-DT7M4VQS.ts";
70
+ import "./chunks/chunk-YDVQYUHE.ts";
69
71
  import {
70
72
  combineSignals,
71
73
  throwIfAborted
72
74
  } from "./chunks/chunk-PWMWOJP4.ts";
73
- import "./chunks/chunk-DT7M4VQS.ts";
74
- import "./chunks/chunk-YDVQYUHE.ts";
75
75
  import {
76
76
  RemoteSelectionMismatchError,
77
77
  formatRemoteSelectionMismatch,
@@ -159,7 +159,7 @@ async function executeRecoveryCommand(rawArgs, ctx, signal, loaders, onCommit, s
159
159
  return { kind: "failed" };
160
160
  }
161
161
  }
162
- async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup, onDialog) {
162
+ async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup, onDialog, retryRefusal = false) {
163
163
  ctx = trackOperationDialogs(ctx, onDialog);
164
164
  try {
165
165
  const command = await resolveSyncCommand(rawArgs, ctx);
@@ -170,6 +170,10 @@ async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup, on
170
170
  if (signal) options.signal = signal;
171
171
  if (onCommit) options.onCommit = onCommit;
172
172
  validateCommandOptions(subcommand, options);
173
+ if (retryRefusal) {
174
+ if (subcommand !== "sync") throw new Error("A refused-model retry is available only for merged sync.");
175
+ options.agentRetryRefusal = true;
176
+ }
173
177
  switch (subcommand) {
174
178
  case "help":
175
179
  ctx.ui.notify(usage(), "info");
@@ -215,7 +219,7 @@ async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup, on
215
219
  return { kind: "completed" };
216
220
  }
217
221
  case "conflicts": {
218
- const { showConflicts } = await import("./chunks/conflict-review-ZCGWFKEK.ts");
222
+ const { showConflicts } = await import("./chunks/conflict-review-T7GSOKNG.ts");
219
223
  throwIfAborted(options.signal);
220
224
  await withLock("sync", () => showConflicts(ctx, options));
221
225
  return { kind: "completed" };
@@ -241,8 +245,8 @@ async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup, on
241
245
  case "sync": {
242
246
  const operations = await loaders.operations();
243
247
  throwIfAborted(options.signal);
244
- await withAgentSyncLock(ctx, options, (current) => operations.syncBoth(ctx, current));
245
- return { kind: "completed" };
248
+ const outcome = await withAgentSyncLock(ctx, options, (current) => operations.syncBoth(ctx, current));
249
+ return { kind: "completed", ...retryRefusal && outcome ? { outcome } : {} };
246
250
  }
247
251
  case "history": {
248
252
  const operations = await loaders.operations();
@@ -312,7 +316,7 @@ async function initConfig(ctx, signal) {
312
316
  return;
313
317
  }
314
318
  if (ctx.mode === "tui") {
315
- const { showSetupWizard } = await import("./chunks/setup-wizard-65DROCIJ.ts");
319
+ const { showSetupWizard } = await import("./chunks/setup-wizard-OVHZYXNW.ts");
316
320
  throwIfAborted(signal);
317
321
  await showSetupWizard(ctx, signal);
318
322
  return;
@@ -407,9 +411,9 @@ function displayWebDavUrl(value, username) {
407
411
  async function handleCommand(rawArgs, ctx, sessionSignal, loaders, attention, onExplicitSync) {
408
412
  await reconcileObservation(attention, sessionSignal);
409
413
  if (sessionSignal.aborted) return;
410
- const run = (route, signal, onCommit, target, onDialog) => {
414
+ const run = (route, signal, onCommit, target, onDialog, retryRefusal = false) => {
411
415
  const [command, ...args] = splitArgs(route);
412
- if (command === "sync") {
416
+ if (command === "sync" && !retryRefusal) {
413
417
  try {
414
418
  const options = parseOptions(args);
415
419
  validateCommandOptions("sync", options);
@@ -424,12 +428,13 @@ async function handleCommand(rawArgs, ctx, sessionSignal, loaders, attention, on
424
428
  loaders,
425
429
  observationCommitCallback(attention, sessionSignal, onCommit),
426
430
  target,
427
- onDialog
431
+ onDialog,
432
+ retryRefusal
428
433
  );
429
434
  };
430
435
  if (!rawArgs.trim()) {
431
436
  try {
432
- const { showSyncManager } = await import("./chunks/manager-ui-KRAW3NE2.ts");
437
+ const { showSyncManager } = await import("./chunks/manager-ui-FXXO6TW4.ts");
433
438
  if (sessionSignal.aborted) return;
434
439
  await showSyncManager(ctx, run, sessionSignal, {
435
440
  getAttention: () => attention.current(),
@@ -529,7 +534,7 @@ function directSelectionOrigin(rawArgs) {
529
534
  async function resolveSelectionAttention(ctx, attention, signal, loaders, options = {}) {
530
535
  const current = attention.current();
531
536
  if (!current || signal.aborted) return;
532
- const { dispatchManagerResult } = await import("./chunks/manager-result-dispatcher-AGBBVDDS.ts");
537
+ const { dispatchManagerResult } = await import("./chunks/manager-result-dispatcher-HOCM2GDA.ts");
533
538
  if (signal.aborted || attention.current() !== current) return;
534
539
  await dispatchManagerResult(
535
540
  ctx,
@@ -840,11 +845,11 @@ function createStartupCheck(loaders, attention, timeoutMs = 3e4) {
840
845
  // src/sync/sync-loaders.ts
841
846
  function createSyncLoaders(dependencies) {
842
847
  const loaders = {
843
- inspection: cachedModuleLoader(dependencies.loadSyncInspection ?? (() => import("./chunks/sync-inspection-XFJOAMJD.ts"))),
848
+ inspection: cachedModuleLoader(dependencies.loadSyncInspection ?? (() => import("./chunks/sync-inspection-5MY2HI4P.ts"))),
844
849
  setupSwitch: cachedModuleLoader(dependencies.loadSetupSwitch ?? (() => import("./chunks/setup-switch-E7PHKI6J.ts"))),
845
850
  snapshot: cachedModuleLoader(dependencies.loadSnapshot ?? (() => import("./chunks/snapshot-THS5EY2L.ts"))),
846
851
  syncState: cachedModuleLoader(dependencies.loadSyncState ?? (() => import("./chunks/sync-state-CFL4RRRB.ts"))),
847
- operations: cachedModuleLoader(dependencies.loadSyncOperations ?? (() => import("./chunks/sync-operations-W5HFFMTP.ts")))
852
+ operations: cachedModuleLoader(dependencies.loadSyncOperations ?? (() => import("./chunks/sync-operations-GNPS6BLY.ts")))
848
853
  };
849
854
  return loaders;
850
855
  }
@@ -886,7 +891,7 @@ function sync(pi, dependencies = {}) {
886
891
  await continuous?.stop(ctx.sessionManager);
887
892
  return;
888
893
  }
889
- const { createContinuousSync } = await import("./chunks/continuous-sync-LAIMSW7D.ts");
894
+ const { createContinuousSync } = await import("./chunks/continuous-sync-U4HIKPQK.ts");
890
895
  if (!isCurrent()) return;
891
896
  continuous ??= createContinuousSync(loaders);
892
897
  continuous.start(ctx, signal, Boolean(retry && (retry.setup === void 0 || retry.setup === config.setupName)));