@narumitw/pi-sync 0.57.2 → 0.57.5

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-4TQWFLOQ.ts → chunk-U3XRI2HF.ts} +28 -197
  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-PSA2L6CE.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-SOYOJQKP.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 -211
  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-4TQWFLOQ.ts.map +0 -7
  72. package/dist/chunks/chunk-QGK445K7.ts.map +0 -7
  73. package/dist/chunks/chunk-QOC47PBC.ts +0 -97
  74. package/dist/chunks/chunk-QOC47PBC.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-PSA2L6CE.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-SOYOJQKP.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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ui/remote-selection-ui.ts", "../../src/ui/cancellable-operation.ts"],
4
- "sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport {\n loadConfig,\n loadPartialConfig,\n type SyncSetupStorageReview,\n syncConfigReviewFingerprint,\n} from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig, PartialConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { throwIfAborted } from \"../sync/signals.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n compareSyncInclude,\n inspectRemoteSelection,\n type RemoteSelectionDecision,\n type RemoteSelectionState,\n sameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport { type RunRoute, type RunRouteResult, runCancellableOperation } from \"./cancellable-operation.js\";\nimport { setSyncStatus } from \"./sync-status.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n decision?: RemoteSelectionDecision;\n origin?: RemoteSelectionOrigin;\n runRoute?: RunRoute;\n cancelLabel?: string;\n /** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n onSelectionResolved?: () => void;\n withStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n | { kind: \"back\" }\n | { kind: \"closed\" }\n | { kind: \"done\" }\n | { kind: \"stale\" }\n | { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n ctx: ExtensionContext,\n setupName?: string,\n signal?: AbortSignal,\n factory: SyncBackendFactory = createSyncBackend,\n options: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n try {\n let decision = options.decision;\n if (!decision) {\n const inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);\n if (!inspected || signal?.aborted) return { kind: \"stale\" };\n // A successful fresh read can supersede an old explicit mismatch without\n // changing local settings. This is not user cancellation or proof of file equality.\n if (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n options.onSelectionResolved?.();\n }\n if (inspected.kind === \"empty\") {\n ctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"same\") {\n ctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"legacy\") {\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n return { kind: \"back\" };\n }\n await showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n return signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n }\n decision = decisionFromState(inspected.config, inspected.state);\n }\n\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n return { kind: \"back\" };\n }\n\n let currentDecision = decision;\n for (;;) {\n if (signal?.aborted) return { kind: \"stale\" };\n const result = await showSelectionDifference(\n ctx,\n currentDecision,\n options.origin ?? \"settings\",\n options.runRoute,\n signal,\n factory,\n options,\n );\n if (result.kind !== \"refresh\") return result;\n const refreshed = await runWithOptionalStateAccess(options, () =>\n inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, signal, factory),\n );\n if (!refreshed || signal?.aborted) return { kind: \"stale\" };\n if (refreshed.kind === \"empty\") {\n options.onSelectionResolved?.();\n ctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n return { kind: \"back\" };\n }\n if (refreshed.state.kind !== \"different\") {\n ctx.ui.notify(\n refreshed.state.kind === \"same\"\n ? \"Remote synced content now matches this sync setup.\"\n : \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n \"info\",\n );\n options.onSelectionResolved?.();\n return { kind: \"done\" };\n }\n currentDecision = decisionFromState(refreshed.config, refreshed.state);\n }\n } catch (error) {\n if (signal?.aborted) return { kind: \"stale\" };\n ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n return { kind: \"back\" };\n } finally {\n setSyncStatus(ctx, undefined);\n }\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n ctx: ExtensionContext,\n initialDecision: RemoteSelectionDecision,\n origin: RemoteSelectionOrigin,\n runRoute: RunRoute | undefined,\n sessionSignal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n options: Pick<RemoteSelectionReviewOptions, \"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\">,\n): Promise<DifferenceFlowResult> {\n type Screen = \"choice\" | \"review\" | \"saved\";\n type Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n interface FlowState {\n decision: RemoteSelectionDecision;\n saved: boolean;\n }\n let flowState: FlowState = { decision: initialDecision, saved: false };\n let continuationReview: PartialConfig | undefined;\n let nextResult: RemoteSelectionReviewResult | undefined;\n let refreshRequested = false;\n const route = origin === \"settings\" ? \"sync\" : origin;\n const menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: ({ state }) => ({\n kind: \"actions\",\n title: \"Synced content differs\",\n lines: selectionSummaryLines(state.decision),\n items: [\n {\n id: \"review\",\n label: \"Review all paths (recommended)\",\n description: \"Compare exact remote-only, device-only, and ordered lists.\",\n to: \"review\",\n },\n {\n id: \"adopt\",\n label: \"Use remote content list\",\n description: \"Save the reviewed list on this device without pulling files.\",\n action: \"adopt\",\n },\n {\n id: \"keep\",\n label: \"Keep this device's content list and update remote\u2026\",\n description: \"Open the existing exact force-push preview without skipping confirmation.\",\n action: \"keep\",\n },\n { id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state }) => ({\n kind: \"review\",\n title: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n content: formatSelectionDifference(state.decision),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n saved: ({ state }) => ({\n kind: \"actions\",\n title: \"Remote content list saved\",\n lines: [\n `Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n \"Only the included-content setting was saved.\",\n \"No files were pulled and sync state was not changed.\",\n ],\n items: [\n ...(runRoute\n ? [\n {\n id: \"continue\",\n label: continueLabel(origin),\n description: \"Start a fresh check and exact preview for this sync setup.\",\n action: \"continue\" as const,\n },\n ]\n : []),\n { id: \"done\", label: \"Done\", action: \"done\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n adopt: async ({ state, signal: actionSignal }) => {\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const currentConfig = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(currentConfig, state.decision);\n if (!currentConfig.include.includes(\"sessions\") && state.decision.remoteInclude.includes(\"sessions\")) {\n const acknowledged = await ctx.ui.confirm(\n \"Use a content list that includes session conversations?\",\n \"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n { signal },\n );\n if (signal.aborted) return { kind: \"close\" as const };\n if (!acknowledged) return { kind: \"stay\" as const };\n }\n const review = await runWithOptionalStateAccess(options, async () => {\n const loaded = await loadAdoptionReview(state.decision, signal, factory);\n if (signal.aborted) throw signal.reason;\n await revalidateAndAdopt(loaded, state.decision, signal);\n return loaded;\n });\n if (signal.aborted) return { kind: \"close\" as const };\n options.onSelectionResolved?.();\n continuationReview = {\n ...review.storageReview,\n setupName: state.decision.setupName,\n include: [...state.decision.remoteInclude],\n automatic: review.config.automatic,\n automaticTransfer: review.config.automaticTransfer,\n agentMode: review.config.agentMode,\n continuous: review.config.continuous,\n onSwitch: review.config.onSwitch,\n showStatus: review.config.showStatus,\n };\n flowState = { decision: state.decision, saved: true };\n return { kind: \"to\" as const, screen: \"saved\" as const };\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n keep: async ({ state, signal: actionSignal }) => {\n if (!runRoute) {\n ctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n return { kind: \"stay\" as const };\n }\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(latest, state.decision);\n const result = await runCancellableOperation(\n ctx,\n \"Preparing this device's push preview\u2026\",\n \"push --force\",\n runRoute,\n {\n commitAware: true,\n cancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n target: state.decision.setupName,\n signal,\n },\n );\n return handleNestedRouteResult(result, \"push\");\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n continue: async ({ state, signal: actionSignal }) => {\n if (!runRoute || !continuationReview) return { kind: \"stay\" as const };\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadPartialConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n if (!sameContinuationReview(latest, continuationReview)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n );\n }\n const result = await runCancellableOperation(ctx, continueBusyLabel(origin), route, runRoute, {\n commitAware: true,\n cancelledMessage: continuationCancelledMessage(route),\n target: state.decision.setupName,\n signal,\n });\n return handleNestedRouteResult(result, route);\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n cancel: async () => ({ kind: \"back\" }),\n done: async () => {\n nextResult = { kind: \"done\" };\n return { kind: \"close\" };\n },\n },\n });\n\n function handleNestedRouteResult(\n result: Awaited<ReturnType<typeof runCancellableOperation>>,\n nestedRoute: \"sync\" | \"pull\" | \"push\",\n ) {\n if (result.kind === \"completed\" && result.outcome === \"applied\") {\n options.onSelectionResolved?.();\n }\n if (result.kind === \"closed\") {\n nextResult = { kind: \"closed\" };\n return { kind: \"close\" as const };\n }\n if (\n result.kind === \"cancelled\" ||\n (result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n result.kind === \"failed\"\n ) {\n return { kind: \"stay\" as const };\n }\n nextResult = { kind: \"route-result\", result, route: nestedRoute };\n return { kind: \"close\" as const };\n }\n\n const menuResult = await runMenu(ctx, menu, {\n getState: () => flowState,\n signal: sessionSignal,\n isCurrent: () => !sessionSignal?.aborted,\n onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n });\n if (sessionSignal?.aborted || menuResult.kind === \"stale\") return { kind: \"stale\" };\n if (refreshRequested) return { kind: \"refresh\" };\n if (nextResult) return nextResult;\n if (menuResult.kind === \"closed\") {\n return menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n }\n return { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n config: AnySyncConfig;\n storageReview: SyncSetupStorageReview;\n backend: SyncBackend;\n reviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n factory: SyncBackendFactory,\n): Promise<AdoptionReview> {\n const config = await loadConfig(decision.setupName);\n throwIfAborted(signal);\n assertLocalSelectionCurrent(config, decision);\n const partial = await loadPartialConfig(decision.setupName);\n throwIfAborted(signal);\n if (!sameSyncInclude(partial.include, decision.localInclude)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`,\n );\n }\n const backend = await factory(config);\n throwIfAborted(signal);\n const reviewedHead = await backend.readHead(signal);\n throwIfAborted(signal);\n if (!reviewedHead) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n throwIfAborted(signal);\n const state = inspectRemoteSelection(config.include, snapshot);\n if (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n return { config, storageReview: partial, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(review: AdoptionReview, decision: RemoteSelectionDecision, signal: AbortSignal) {\n const currentHead = await review.backend.readHead(signal);\n throwIfAborted(signal);\n if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n throwIfAborted(signal);\n const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n if (currentState.kind !== \"different\" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n await updateSyncSetup(\n decision.setupName,\n (setup) => ({\n ...setup,\n sync: { ...setup.sync, include: [...decision.remoteInclude] },\n }),\n {\n expectedStorage: review.storageReview,\n expectedInclude: decision.localInclude,\n signal,\n },\n );\n}\n\nasync function inspectConfiguredRemoteSelection(\n ctx: ExtensionContext,\n setupName: string | undefined,\n signal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n): Promise<\n | { kind: \"empty\"; config: AnySyncConfig }\n | { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n | undefined\n> {\n const config = await loadConfig(setupName);\n if (signal?.aborted) return undefined;\n setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);\n const backend = await factory(config);\n if (signal?.aborted) return undefined;\n const head = await backend.readHead(signal);\n if (signal?.aborted) return undefined;\n if (!head) return { kind: \"empty\", config };\n const snapshot = await readSnapshotForHead(backend, head, signal);\n if (signal?.aborted) return undefined;\n return {\n kind: \"selection\",\n config,\n state: inspectRemoteSelection(config.include, snapshot),\n };\n}\n\nasync function showLegacyDiscovery(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n discovered: string[],\n signal?: AbortSignal,\n) {\n const menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: () => ({\n kind: \"actions\",\n title: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n lines: [\n \"This legacy snapshot has no portable synced-content list.\",\n \"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n ],\n items: [\n { id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n { id: \"back\", label: \"Back\", action: \"back\" },\n ],\n hint: \"close\",\n }),\n review: () => ({\n kind: \"review\",\n title: \"Partial discovery from legacy snapshot\",\n content: [\n \"Partial discovery only \u2014 not an authoritative selection.\",\n \"\",\n ...(discovered.length > 0\n ? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n : [\"No safe paths were discovered.\"]),\n \"\",\n \"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n ].join(\"\\n\"),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: { back: async () => ({ kind: \"close\" }) },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal,\n isCurrent: () => !signal?.aborted,\n });\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Sync setup: ${safeTerminalText(decision.setupName)}`,\n \"Nothing changed. Review both lists before choosing what happens next.\",\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only the ordering differs; membership is the same.\"]\n : [`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`]),\n ];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n : []),\n \"Remote-only paths:\",\n ...(comparison.remoteOnly.length > 0\n ? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Device-only paths:\",\n ...(comparison.localOnly.length > 0\n ? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Remote ordered list:\",\n ...(decision.remoteInclude.length > 0\n ? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"This device's ordered list:\",\n ...(decision.localInclude.length > 0\n ? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Using the remote list saves settings only and does not pull files.\",\n ].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n `Remote-only: ${safeList(comparison.remoteOnly)}`,\n `Device-only: ${safeList(comparison.localOnly)}`,\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\n \"Only ordering differs.\",\n `Remote order: ${safeList(decision.remoteInclude)}`,\n `Device order: ${safeList(decision.localInclude)}`,\n ]\n : []),\n \"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n ].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n return `Remote snapshot for \u201C${safeTerminalText(config.setupName)}\u201D has no portable synced-content list; ${discovered.length} safe path${discovered.length === 1 ? \" was\" : \"s were\"} discovered, but the result is partial and read-only.`;\n}\n\nfunction decisionFromState(\n config: AnySyncConfig,\n state: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n return {\n setupName: config.setupName,\n configIdentity: syncConfigReviewFingerprint(config),\n localInclude: [...config.include],\n remoteInclude: [...state.include],\n };\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n if (\n syncConfigReviewFingerprint(config) === decision.configIdentity &&\n sameSyncInclude(config.include, decision.localInclude)\n ) {\n return;\n }\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n );\n}\n\nfunction sameContinuationReview(left: PartialConfig, right: PartialConfig) {\n return (\n left.setupName === right.setupName &&\n left.connectionName === right.connectionName &&\n left.storageKind === right.storageKind &&\n left.storagePath === right.storagePath &&\n left.bucket === right.bucket &&\n left.branch === right.branch &&\n Boolean(left.agentMode) === Boolean(right.agentMode) &&\n Boolean(left.continuous) === Boolean(right.continuous) &&\n sameSyncInclude(left.include, right.include)\n );\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Continue Pull now\u2026\";\n if (origin === \"push\") return \"Continue Push now\u2026\";\n return \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Checking remote changes\u2026\";\n if (origin === \"push\") return \"Preparing push preview\u2026\";\n return \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n if (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n if (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n return \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StaleRemoteSelectionReviewError\";\n }\n}\n\nfunction isStaleReviewError(error: unknown) {\n return error instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError;\n}\n\nfunction runWithOptionalStateAccess<T>(\n options: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n task: () => Promise<T>,\n) {\n return options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n", "import { BorderedLoader, type ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { isKeyRelease, Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { formatInteractionHints, runCustomInteraction } from \"@narumitw/pi-tui-kit\";\nimport type { SetupPullOutcome } from \"../sync/setup-switch.js\";\nimport type { SyncDecision } from \"../sync/sync-decision.js\";\nimport type { RemoteSelectionDecision } from \"../sync/sync-policy.js\";\n\nexport type RunRouteResult =\n | { kind: \"completed\"; outcome?: SetupPullOutcome }\n | { kind: \"decision-required\"; decision: SyncDecision }\n | { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n | { kind: \"failed\" };\n\nexport type RunRoute = (\n route: string,\n signal?: AbortSignal,\n onCommit?: () => void,\n target?: string,\n onDialog?: (active: boolean) => void,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult = RunRouteResult | { kind: \"closed\" } | { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n commitAware?: boolean;\n cancelAcrossDialogs?: boolean;\n cancelledMessage?: string | null;\n target?: string;\n signal?: AbortSignal;\n}\n\nexport async function runCancellableOperation(\n ctx: ExtensionContext,\n message: string,\n route: string,\n runRoute: RunRoute,\n options: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n const {\n commitAware = false,\n cancelAcrossDialogs = false,\n cancelledMessage = \"Check cancelled; no settings or files were changed.\",\n target,\n signal,\n } = options;\n if (ctx.mode !== \"tui\") {\n return (await runRoute(route, signal, undefined, target)) ?? { kind: \"failed\" };\n }\n let commitStarted = false;\n let routeResult: RunRouteResult | undefined;\n const interaction = await runCustomInteraction<{ cancelled?: boolean; error?: unknown }, ExtensionContext>(ctx, {\n signal,\n isCurrent: () => !signal?.aborted,\n create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n const loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n const cancelHint = formatInteractionHints(keybindings, [\n {\n keys: [...keybindings.getKeys(\"tui.select.cancel\").filter((key) => !hasControlCharacter(key)), \"ctrl+c\"],\n label: \"cancel\",\n },\n ]);\n const cancel = (data: string) => {\n // Raw terminal listeners run before Pi filters Kitty key releases.\n if (isKeyRelease(data)) return false;\n if (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) return false;\n if (commitStarted) {\n ctx.ui.notify(\"Applying or publishing has started and cannot be cancelled safely.\", \"warning\");\n } else complete({ cancelled: true });\n return true;\n };\n // Pi dialogs replace this loader and restore the normal editor. Defer\n // ordinary keys while they are open; retain raw cancellation afterward.\n // Ctrl+C remains the root flow's hard-cancel path regardless of focus.\n let activeDialogs = 0;\n const unsubscribe = cancelAcrossDialogs\n ? ctx.ui.onTerminalInput((data) => {\n if (isKeyRelease(data)) return;\n if (activeDialogs > 0 && !matchesKey(data, Key.ctrl(\"c\"))) return;\n return cancel(data) ? { consume: true } : undefined;\n })\n : undefined;\n let pendingRoute: ReturnType<RunRoute>;\n try {\n pendingRoute = runRoute(\n route,\n interactionSignal,\n commitAware ? () => (commitStarted = true) : undefined,\n target,\n cancelAcrossDialogs\n ? (active) => {\n activeDialogs += active ? 1 : -1;\n }\n : undefined,\n );\n } catch (error) {\n unsubscribe?.();\n loader.dispose();\n throw error;\n }\n const operation = pendingRoute.then(\n (result) => {\n routeResult = result;\n complete({});\n },\n (error: unknown) => complete({ error }),\n );\n return {\n render(width: number) {\n const safeWidth = Math.max(1, width);\n const lines = loader.render(safeWidth);\n const bottomBorder = lines.at(-1);\n return [\n ...lines.slice(0, -1),\n truncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n ...(bottomBorder === undefined ? [] : [bottomBorder]),\n ];\n },\n invalidate: () => loader.invalidate(),\n handleInput: cancel,\n dispose() {\n unsubscribe?.();\n loader.dispose();\n },\n waitForPending: () => operation,\n };\n },\n });\n if (interaction.kind === \"error\") throw interaction.error;\n if (interaction.kind !== \"completed\") return { kind: \"closed\" };\n if (interaction.value.cancelled) {\n if (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n return { kind: \"cancelled\" };\n }\n if (interaction.value.error) throw interaction.value.error;\n return routeResult ?? { kind: \"failed\" };\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Unsafe key labels must be omitted.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport {\n loadConfig,\n loadPartialConfig,\n type SyncSetupStorageReview,\n syncConfigReviewFingerprint,\n} from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig, PartialConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { throwIfAborted } from \"../sync/signals.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n compareSyncInclude,\n inspectRemoteSelection,\n type RemoteSelectionDecision,\n type RemoteSelectionState,\n sameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport { type RunRoute, type RunRouteResult, runCancellableOperation } from \"./cancellable-operation.js\";\nimport { setSyncStatus } from \"./sync-status.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n decision?: RemoteSelectionDecision;\n origin?: RemoteSelectionOrigin;\n runRoute?: RunRoute;\n cancelLabel?: string;\n /** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n onSelectionResolved?: () => void;\n withStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n | { kind: \"back\" }\n | { kind: \"closed\" }\n | { kind: \"done\" }\n | { kind: \"stale\" }\n | { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n ctx: ExtensionContext,\n setupName?: string,\n signal?: AbortSignal,\n factory: SyncBackendFactory = createSyncBackend,\n options: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n try {\n let decision = options.decision;\n if (!decision) {\n const inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);\n if (!inspected || signal?.aborted) return { kind: \"stale\" };\n // A successful fresh read can supersede an old explicit mismatch without\n // changing local settings. This is not user cancellation or proof of file equality.\n if (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n options.onSelectionResolved?.();\n }\n if (inspected.kind === \"empty\") {\n ctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"same\") {\n ctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"legacy\") {\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n return { kind: \"back\" };\n }\n await showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n return signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n }\n decision = decisionFromState(inspected.config, inspected.state);\n }\n\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n return { kind: \"back\" };\n }\n\n let currentDecision = decision;\n for (;;) {\n if (signal?.aborted) return { kind: \"stale\" };\n const result = await showSelectionDifference(\n ctx,\n currentDecision,\n options.origin ?? \"settings\",\n options.runRoute,\n signal,\n factory,\n options,\n );\n if (result.kind !== \"refresh\") return result;\n const refreshed = await runWithOptionalStateAccess(options, () =>\n inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, signal, factory),\n );\n if (!refreshed || signal?.aborted) return { kind: \"stale\" };\n if (refreshed.kind === \"empty\") {\n options.onSelectionResolved?.();\n ctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n return { kind: \"back\" };\n }\n if (refreshed.state.kind !== \"different\") {\n ctx.ui.notify(\n refreshed.state.kind === \"same\"\n ? \"Remote synced content now matches this sync setup.\"\n : \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n \"info\",\n );\n options.onSelectionResolved?.();\n return { kind: \"done\" };\n }\n currentDecision = decisionFromState(refreshed.config, refreshed.state);\n }\n } catch (error) {\n if (signal?.aborted) return { kind: \"stale\" };\n ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n return { kind: \"back\" };\n } finally {\n setSyncStatus(ctx, undefined);\n }\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n ctx: ExtensionContext,\n initialDecision: RemoteSelectionDecision,\n origin: RemoteSelectionOrigin,\n runRoute: RunRoute | undefined,\n sessionSignal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n options: Pick<RemoteSelectionReviewOptions, \"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\">,\n): Promise<DifferenceFlowResult> {\n type Screen = \"choice\" | \"review\" | \"saved\";\n type Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n interface FlowState {\n decision: RemoteSelectionDecision;\n saved: boolean;\n }\n let flowState: FlowState = { decision: initialDecision, saved: false };\n let continuationReview: PartialConfig | undefined;\n let nextResult: RemoteSelectionReviewResult | undefined;\n let refreshRequested = false;\n const route = origin === \"settings\" ? \"sync\" : origin;\n const menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: ({ state }) => ({\n kind: \"actions\",\n title: \"Synced content differs\",\n lines: selectionSummaryLines(state.decision),\n items: [\n {\n id: \"review\",\n label: \"Review all paths (recommended)\",\n description: \"Compare exact remote-only, device-only, and ordered lists.\",\n to: \"review\",\n },\n {\n id: \"adopt\",\n label: \"Use remote content list\",\n description: \"Save the reviewed list on this device without pulling files.\",\n action: \"adopt\",\n },\n {\n id: \"keep\",\n label: \"Keep this device's content list and update remote\u2026\",\n description: \"Open the existing exact force-push preview without skipping confirmation.\",\n action: \"keep\",\n },\n { id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state }) => ({\n kind: \"review\",\n title: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n content: formatSelectionDifference(state.decision),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n saved: ({ state }) => ({\n kind: \"actions\",\n title: \"Remote content list saved\",\n lines: [\n `Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n \"Only the included-content setting was saved.\",\n \"No files were pulled and sync state was not changed.\",\n ],\n items: [\n ...(runRoute\n ? [\n {\n id: \"continue\",\n label: continueLabel(origin),\n description: \"Start a fresh check and exact preview for this sync setup.\",\n action: \"continue\" as const,\n },\n ]\n : []),\n { id: \"done\", label: \"Done\", action: \"done\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n adopt: async ({ state, signal: actionSignal }) => {\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const currentConfig = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(currentConfig, state.decision);\n if (!currentConfig.include.includes(\"sessions\") && state.decision.remoteInclude.includes(\"sessions\")) {\n const acknowledged = await ctx.ui.confirm(\n \"Use a content list that includes session conversations?\",\n \"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n { signal },\n );\n if (signal.aborted) return { kind: \"close\" as const };\n if (!acknowledged) return { kind: \"stay\" as const };\n }\n const review = await runWithOptionalStateAccess(options, async () => {\n const loaded = await loadAdoptionReview(state.decision, signal, factory);\n if (signal.aborted) throw signal.reason;\n await revalidateAndAdopt(loaded, state.decision, signal);\n return loaded;\n });\n if (signal.aborted) return { kind: \"close\" as const };\n options.onSelectionResolved?.();\n continuationReview = {\n ...review.storageReview,\n setupName: state.decision.setupName,\n include: [...state.decision.remoteInclude],\n automatic: review.config.automatic,\n automaticTransfer: review.config.automaticTransfer,\n agentMode: review.config.agentMode,\n continuous: review.config.continuous,\n onSwitch: review.config.onSwitch,\n showStatus: review.config.showStatus,\n };\n flowState = { decision: state.decision, saved: true };\n return { kind: \"to\" as const, screen: \"saved\" as const };\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n keep: async ({ state, signal: actionSignal }) => {\n if (!runRoute) {\n ctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n return { kind: \"stay\" as const };\n }\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(latest, state.decision);\n const result = await runCancellableOperation(\n ctx,\n \"Preparing this device's push preview\u2026\",\n \"push --force\",\n runRoute,\n {\n commitAware: true,\n cancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n target: state.decision.setupName,\n signal,\n },\n );\n return handleNestedRouteResult(result, \"push\");\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n continue: async ({ state, signal: actionSignal }) => {\n if (!runRoute || !continuationReview) return { kind: \"stay\" as const };\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadPartialConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n if (!sameContinuationReview(latest, continuationReview)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n );\n }\n const result = await runCancellableOperation(ctx, continueBusyLabel(origin), route, runRoute, {\n commitAware: true,\n cancelledMessage: continuationCancelledMessage(route),\n target: state.decision.setupName,\n signal,\n });\n return handleNestedRouteResult(result, route);\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n cancel: async () => ({ kind: \"back\" }),\n done: async () => {\n nextResult = { kind: \"done\" };\n return { kind: \"close\" };\n },\n },\n });\n\n function handleNestedRouteResult(\n result: Awaited<ReturnType<typeof runCancellableOperation>>,\n nestedRoute: \"sync\" | \"pull\" | \"push\",\n ) {\n if (result.kind === \"completed\" && result.outcome === \"applied\") {\n options.onSelectionResolved?.();\n }\n if (result.kind === \"closed\") {\n nextResult = { kind: \"closed\" };\n return { kind: \"close\" as const };\n }\n if (\n result.kind === \"cancelled\" ||\n (result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n result.kind === \"failed\"\n ) {\n return { kind: \"stay\" as const };\n }\n nextResult = { kind: \"route-result\", result, route: nestedRoute };\n return { kind: \"close\" as const };\n }\n\n const menuResult = await runMenu(ctx, menu, {\n getState: () => flowState,\n signal: sessionSignal,\n isCurrent: () => !sessionSignal?.aborted,\n onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n });\n if (sessionSignal?.aborted || menuResult.kind === \"stale\") return { kind: \"stale\" };\n if (refreshRequested) return { kind: \"refresh\" };\n if (nextResult) return nextResult;\n if (menuResult.kind === \"closed\") {\n return menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n }\n return { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n config: AnySyncConfig;\n storageReview: SyncSetupStorageReview;\n backend: SyncBackend;\n reviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n factory: SyncBackendFactory,\n): Promise<AdoptionReview> {\n const config = await loadConfig(decision.setupName);\n throwIfAborted(signal);\n assertLocalSelectionCurrent(config, decision);\n const partial = await loadPartialConfig(decision.setupName);\n throwIfAborted(signal);\n if (!sameSyncInclude(partial.include, decision.localInclude)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`,\n );\n }\n const backend = await factory(config);\n throwIfAborted(signal);\n const reviewedHead = await backend.readHead(signal);\n throwIfAborted(signal);\n if (!reviewedHead) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n throwIfAborted(signal);\n const state = inspectRemoteSelection(config.include, snapshot);\n if (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n return { config, storageReview: partial, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(review: AdoptionReview, decision: RemoteSelectionDecision, signal: AbortSignal) {\n const currentHead = await review.backend.readHead(signal);\n throwIfAborted(signal);\n if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n throwIfAborted(signal);\n const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n if (currentState.kind !== \"different\" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n await updateSyncSetup(\n decision.setupName,\n (setup) => ({\n ...setup,\n sync: { ...setup.sync, include: [...decision.remoteInclude] },\n }),\n {\n expectedStorage: review.storageReview,\n expectedInclude: decision.localInclude,\n signal,\n },\n );\n}\n\nasync function inspectConfiguredRemoteSelection(\n ctx: ExtensionContext,\n setupName: string | undefined,\n signal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n): Promise<\n | { kind: \"empty\"; config: AnySyncConfig }\n | { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n | undefined\n> {\n const config = await loadConfig(setupName);\n if (signal?.aborted) return undefined;\n setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);\n const backend = await factory(config);\n if (signal?.aborted) return undefined;\n const head = await backend.readHead(signal);\n if (signal?.aborted) return undefined;\n if (!head) return { kind: \"empty\", config };\n const snapshot = await readSnapshotForHead(backend, head, signal);\n if (signal?.aborted) return undefined;\n return {\n kind: \"selection\",\n config,\n state: inspectRemoteSelection(config.include, snapshot),\n };\n}\n\nasync function showLegacyDiscovery(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n discovered: string[],\n signal?: AbortSignal,\n) {\n const menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: () => ({\n kind: \"actions\",\n title: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n lines: [\n \"This legacy snapshot has no portable synced-content list.\",\n \"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n ],\n items: [\n { id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n { id: \"back\", label: \"Back\", action: \"back\" },\n ],\n hint: \"close\",\n }),\n review: () => ({\n kind: \"review\",\n title: \"Partial discovery from legacy snapshot\",\n content: [\n \"Partial discovery only \u2014 not an authoritative selection.\",\n \"\",\n ...(discovered.length > 0\n ? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n : [\"No safe paths were discovered.\"]),\n \"\",\n \"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n ].join(\"\\n\"),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: { back: async () => ({ kind: \"close\" }) },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal,\n isCurrent: () => !signal?.aborted,\n });\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Sync setup: ${safeTerminalText(decision.setupName)}`,\n \"Nothing changed. Review both lists before choosing what happens next.\",\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only the ordering differs; membership is the same.\"]\n : [`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`]),\n ];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n : []),\n \"Remote-only paths:\",\n ...(comparison.remoteOnly.length > 0\n ? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Device-only paths:\",\n ...(comparison.localOnly.length > 0\n ? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Remote ordered list:\",\n ...(decision.remoteInclude.length > 0\n ? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"This device's ordered list:\",\n ...(decision.localInclude.length > 0\n ? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Using the remote list saves settings only and does not pull files.\",\n ].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n `Remote-only: ${safeList(comparison.remoteOnly)}`,\n `Device-only: ${safeList(comparison.localOnly)}`,\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\n \"Only ordering differs.\",\n `Remote order: ${safeList(decision.remoteInclude)}`,\n `Device order: ${safeList(decision.localInclude)}`,\n ]\n : []),\n \"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n ].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n return `Remote snapshot for \u201C${safeTerminalText(config.setupName)}\u201D has no portable synced-content list; ${discovered.length} safe path${discovered.length === 1 ? \" was\" : \"s were\"} discovered, but the result is partial and read-only.`;\n}\n\nfunction decisionFromState(\n config: AnySyncConfig,\n state: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n return {\n setupName: config.setupName,\n configIdentity: syncConfigReviewFingerprint(config),\n localInclude: [...config.include],\n remoteInclude: [...state.include],\n };\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n if (\n syncConfigReviewFingerprint(config) === decision.configIdentity &&\n sameSyncInclude(config.include, decision.localInclude)\n ) {\n return;\n }\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n );\n}\n\nfunction sameContinuationReview(left: PartialConfig, right: PartialConfig) {\n return (\n left.setupName === right.setupName &&\n left.connectionName === right.connectionName &&\n left.storageKind === right.storageKind &&\n left.storagePath === right.storagePath &&\n left.bucket === right.bucket &&\n left.branch === right.branch &&\n Boolean(left.agentMode) === Boolean(right.agentMode) &&\n Boolean(left.continuous) === Boolean(right.continuous) &&\n sameSyncInclude(left.include, right.include)\n );\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Continue Pull now\u2026\";\n if (origin === \"push\") return \"Continue Push now\u2026\";\n return \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Checking remote changes\u2026\";\n if (origin === \"push\") return \"Preparing push preview\u2026\";\n return \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n if (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n if (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n return \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StaleRemoteSelectionReviewError\";\n }\n}\n\nfunction isStaleReviewError(error: unknown) {\n return error instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError;\n}\n\nfunction runWithOptionalStateAccess<T>(\n options: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n task: () => Promise<T>,\n) {\n return options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n", "import { BorderedLoader, type ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { isKeyRelease, Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { formatInteractionHints, runCustomInteraction } from \"@narumitw/pi-tui-kit\";\nimport type { SetupPullOutcome } from \"../sync/setup-switch.js\";\nimport type { SyncDecision } from \"../sync/sync-decision.js\";\nimport type { RemoteSelectionDecision } from \"../sync/sync-policy.js\";\n\nexport type RunRouteResult =\n | { kind: \"completed\"; outcome?: SetupPullOutcome }\n | { kind: \"decision-required\"; decision: SyncDecision }\n | { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n | { kind: \"failed\" };\n\nexport type RunRoute = (\n route: string,\n signal?: AbortSignal,\n onCommit?: () => void,\n target?: string,\n onDialog?: (active: boolean) => void,\n retryRefusal?: boolean,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult = RunRouteResult | { kind: \"closed\" } | { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n commitAware?: boolean;\n cancelAcrossDialogs?: boolean;\n cancelledMessage?: string | null;\n target?: string;\n signal?: AbortSignal;\n}\n\nexport async function runCancellableOperation(\n ctx: ExtensionContext,\n message: string,\n route: string,\n runRoute: RunRoute,\n options: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n const {\n commitAware = false,\n cancelAcrossDialogs = false,\n cancelledMessage = \"Check cancelled; no settings or files were changed.\",\n target,\n signal,\n } = options;\n if (ctx.mode !== \"tui\") {\n return (await runRoute(route, signal, undefined, target)) ?? { kind: \"failed\" };\n }\n let commitStarted = false;\n let routeResult: RunRouteResult | undefined;\n const interaction = await runCustomInteraction<{ cancelled?: boolean; error?: unknown }, ExtensionContext>(ctx, {\n signal,\n isCurrent: () => !signal?.aborted,\n create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n const loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n const cancelHint = formatInteractionHints(keybindings, [\n {\n keys: [...keybindings.getKeys(\"tui.select.cancel\").filter((key) => !hasControlCharacter(key)), \"ctrl+c\"],\n label: \"cancel\",\n },\n ]);\n const cancel = (data: string) => {\n // Raw terminal listeners run before Pi filters Kitty key releases.\n if (isKeyRelease(data)) return false;\n if (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) return false;\n if (commitStarted) {\n ctx.ui.notify(\"Applying or publishing has started and cannot be cancelled safely.\", \"warning\");\n } else complete({ cancelled: true });\n return true;\n };\n // Pi dialogs replace this loader and restore the normal editor. Defer\n // ordinary keys while they are open; retain raw cancellation afterward.\n // Ctrl+C remains the root flow's hard-cancel path regardless of focus.\n let activeDialogs = 0;\n const unsubscribe = cancelAcrossDialogs\n ? ctx.ui.onTerminalInput((data) => {\n if (isKeyRelease(data)) return;\n if (activeDialogs > 0 && !matchesKey(data, Key.ctrl(\"c\"))) return;\n return cancel(data) ? { consume: true } : undefined;\n })\n : undefined;\n let pendingRoute: ReturnType<RunRoute>;\n try {\n pendingRoute = runRoute(\n route,\n interactionSignal,\n commitAware ? () => (commitStarted = true) : undefined,\n target,\n cancelAcrossDialogs\n ? (active) => {\n activeDialogs += active ? 1 : -1;\n }\n : undefined,\n );\n } catch (error) {\n unsubscribe?.();\n loader.dispose();\n throw error;\n }\n const operation = pendingRoute.then(\n (result) => {\n routeResult = result;\n complete({});\n },\n (error: unknown) => complete({ error }),\n );\n return {\n render(width: number) {\n if (width <= 0) return [];\n const safeWidth = Math.max(1, width);\n const lines = loader.render(safeWidth);\n const bottomBorder = lines.at(-1);\n return [\n ...lines.slice(0, -1),\n truncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n ...(bottomBorder === undefined ? [] : [bottomBorder]),\n ];\n },\n invalidate: () => loader.invalidate(),\n handleInput: cancel,\n dispose() {\n unsubscribe?.();\n loader.dispose();\n },\n waitForPending: () => operation,\n };\n },\n });\n if (interaction.kind === \"error\") throw interaction.error;\n if (interaction.kind !== \"completed\") return { kind: \"closed\" };\n if (interaction.value.cancelled) {\n if (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n return { kind: \"cancelled\" };\n }\n if (interaction.value.error) throw interaction.value.error;\n return routeResult ?? { kind: \"failed\" };\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Unsafe key labels must be omitted.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -5,15 +5,15 @@
5
5
  var createSyncBackend = async (config) => {
6
6
  switch (config.backend.type) {
7
7
  case "s3": {
8
- const { S3SyncBackend } = await import("./s3-backend-Y7WSCLJI.ts");
8
+ const { S3SyncBackend } = await import("./s3-backend-F7PR5FB3.ts");
9
9
  return new S3SyncBackend(config.backend);
10
10
  }
11
11
  case "webdav": {
12
- const { WebDavSyncBackend } = await import("./webdav-backend-6K26F6LT.ts");
12
+ const { WebDavSyncBackend } = await import("./webdav-backend-TGFUH3SF.ts");
13
13
  return new WebDavSyncBackend(config.backend);
14
14
  }
15
15
  case "git": {
16
- const { GitSyncBackend } = await import("./git-backend-KYDZ673X.ts");
16
+ const { GitSyncBackend } = await import("./git-backend-NYKSG5X6.ts");
17
17
  return new GitSyncBackend(config.backend);
18
18
  }
19
19
  }
@@ -22,4 +22,4 @@ var createSyncBackend = async (config) => {
22
22
  export {
23
23
  createSyncBackend
24
24
  };
25
- //# sourceMappingURL=chunk-OEWQVWLC.ts.map
25
+ //# sourceMappingURL=chunk-ORGBI36T.ts.map
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  runCancellableOperation,
5
5
  showRemoteSelectionReview
6
- } from "./chunk-JJTARUSO.ts";
6
+ } from "./chunk-JCH3VXIO.ts";
7
7
  import {
8
8
  safeTerminalText
9
9
  } from "./chunk-AMJRUXFT.ts";
@@ -206,4 +206,4 @@ async function dispatchManagerResult(ctx, initialResult, origin, runRoute, signa
206
206
  export {
207
207
  dispatchManagerResult
208
208
  };
209
- //# sourceMappingURL=chunk-EUMINX7L.ts.map
209
+ //# sourceMappingURL=chunk-P7DD5PWZ.ts.map
@@ -33,6 +33,7 @@ import { createHash } from "node:crypto";
33
33
  import fs from "node:fs/promises";
34
34
  import path from "node:path";
35
35
  import { getAgentDir } from "@earendil-works/pi-coding-agent";
36
+ var CONTINUOUS_RECORD_MAX_BYTES = 131072;
36
37
  function hashContinuous(value) {
37
38
  return createHash("sha256").update(JSON.stringify(value) ?? "null").digest("hex");
38
39
  }
@@ -53,13 +54,17 @@ async function checkContinuousRoot() {
53
54
  throw new Error("Unsafe continuous sync directory; evidence retained.");
54
55
  }
55
56
  async function readContinuousPrivate(name) {
57
+ return (await readContinuousPrivateDocument(name))?.value;
58
+ }
59
+ async function readContinuousPrivateDocument(name) {
56
60
  try {
57
61
  await checkContinuousRoot();
58
62
  const file = path.join(continuousRoot(), name);
59
63
  const stat2 = await fs.lstat(file);
60
- if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.nlink !== 1 || stat2.size > 131072 || process.platform !== "win32" && stat2.mode & 63)
64
+ if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.nlink !== 1 || stat2.size > CONTINUOUS_RECORD_MAX_BYTES || process.platform !== "win32" && stat2.mode & 63)
61
65
  throw new Error("Unsafe continuous sync record; evidence retained.");
62
- return JSON.parse(await fs.readFile(file, "utf8"));
66
+ const bytes = await fs.readFile(file);
67
+ return { value: JSON.parse(bytes.toString("utf8")), bytes: bytes.byteLength };
63
68
  } catch (error) {
64
69
  if (error.code === "ENOENT") return void 0;
65
70
  throw error;
@@ -68,7 +73,7 @@ async function readContinuousPrivate(name) {
68
73
  async function writeContinuousPrivate(name, value) {
69
74
  await checkContinuousRoot();
70
75
  await readContinuousPrivate(name);
71
- await writeJson(path.join(continuousRoot(), name), value, { maxBytes: 131072 });
76
+ await writeJson(path.join(continuousRoot(), name), value, { maxBytes: CONTINUOUS_RECORD_MAX_BYTES });
72
77
  }
73
78
 
74
79
  // src/sync/continuous-lease.ts
@@ -86,8 +91,8 @@ async function continuousLeaseOwner(binding) {
86
91
  if (!validOwner(owner)) throw new Error("Invalid continuous sync owner");
87
92
  try {
88
93
  const guard = await fs2.lstat(path2.join(continuousRoot(), "scheduler.lock"));
89
- if (guard.isDirectory() && !guard.isSymbolicLink() && Date.now() - guard.mtimeMs <= STALE_MS && owner.binding === binding)
90
- return `Local scheduler lease: observed for pid ${owner.pid}; this can be another session`;
94
+ if (guard.isDirectory() && !guard.isSymbolicLink() && Date.now() - guard.mtimeMs <= STALE_MS)
95
+ return `Local scheduler lease: observed for pid ${owner.pid}; ${owner.binding === binding ? "this can be another session" : "another setup; this setup is standby"}`;
91
96
  } catch (error) {
92
97
  if (error.code !== "ENOENT") throw error;
93
98
  }
@@ -266,10 +271,12 @@ function validateContinuousRecord(value, binding) {
266
271
  ))
267
272
  throw new Error("Invalid continuous sync state; evidence retained.");
268
273
  }
274
+ function emptyContinuousRecord(binding) {
275
+ return { version: 1, binding, pending: true, phase: "waiting", next: 0, failures: 0, calls: [], attempts: {} };
276
+ }
269
277
  async function readContinuousRecord(binding) {
270
278
  const value = await readContinuousPrivate(`${binding}.json`);
271
- if (value === void 0)
272
- return { version: 1, binding, pending: true, phase: "waiting", next: 0, failures: 0, calls: [], attempts: {} };
279
+ if (value === void 0) return emptyContinuousRecord(binding);
273
280
  validateContinuousRecord(value, binding);
274
281
  return value;
275
282
  }
@@ -292,16 +299,19 @@ function normalizeContinuousClock(record, now) {
292
299
  record.calls = record.calls.map((call) => ({ ...call, at: Math.min(call.at, now) })).filter((call) => now - call.at < REQUEST_WINDOW_MS);
293
300
  record.next = Math.min(record.next, now + (record.error === "budget" ? REQUEST_WINDOW_MS : 3e5));
294
301
  }
295
- async function reserveContinuousRequest(binding, lease, key, clock = Date.now) {
302
+ async function reserveContinuousRequest(binding, lease, key, clock = Date.now, signal) {
303
+ signal?.throwIfAborted();
296
304
  if (!digest(key)) throw new Error("Invalid continuous candidate key.");
297
305
  let failure;
298
306
  await updateContinuousRecord(binding, lease, (record) => {
307
+ signal?.throwIfAborted();
299
308
  const now = clock();
309
+ signal?.throwIfAborted();
300
310
  normalizeContinuousClock(record, now);
301
311
  if ((record.attempts[key] ?? 0) >= 2)
302
312
  failure = new ContinuousError(
303
313
  "model",
304
- "Automatic request limit reached for this evidence. Use Sync now for an explicit retry."
314
+ "Automatic request limit reached for this evidence. Change the evidence or review /sync; Sync now does not reset this limit."
305
315
  );
306
316
  else if (record.calls.length >= 2)
307
317
  failure = new ContinuousError(
@@ -314,24 +324,79 @@ async function reserveContinuousRequest(binding, lease, key, clock = Date.now) {
314
324
  record.calls.push({ key, at: now });
315
325
  }
316
326
  });
327
+ signal?.throwIfAborted();
317
328
  if (failure) throw failure;
318
329
  }
319
- async function continuousStatusLines(config) {
330
+ var recoveryActions = {
331
+ transient: "Wait for the scheduled retry. Check network and service availability if failures continue.",
332
+ contention: "Wait for the active sync operation to finish. Do not remove a live lock.",
333
+ stale: "Wait for a fresh inspection after the retry delay. Local or remote evidence changed.",
334
+ authentication: "Repair storage or Pi model authentication, then reopen /sync. Do not share credentials.",
335
+ storage: "Repair private-state permissions, free space or storage access. Retain accounting and recovery evidence.",
336
+ unsafe: "Remove secrets or repair unsupported conflicts. Changed evidence is inspected again; review /sync if needed.",
337
+ model: "Review conflict evidence and Pi model access. Sync now reuses cached refusals; a refusal needs changed evidence or a separately confirmed retry.",
338
+ budget: "Wait for the window allowance shown above. Waiting does not restore exhausted candidates or accounting capacity.",
339
+ unknown: "Review /sync diagnostics and reconcile pending recovery before retrying. Do not delete private evidence or blindly republish."
340
+ };
341
+ function serializedBytes(record) {
342
+ return Buffer.byteLength(`${JSON.stringify(record, null, " ")}
343
+ `);
344
+ }
345
+ function hasReservationCapacity(record, now) {
346
+ const existing = Object.keys(record.attempts).find((key2) => record.attempts[key2] === 1);
347
+ let key = existing ?? "0".repeat(64);
348
+ if (!existing) {
349
+ for (let index = 1; record.attempts[key] !== void 0; index++) key = index.toString(16).padStart(64, "0");
350
+ }
351
+ return serializedBytes({
352
+ ...record,
353
+ calls: [...record.calls, { key, at: now }],
354
+ attempts: { ...record.attempts, [key]: (record.attempts[key] ?? 0) + 1 }
355
+ }) <= CONTINUOUS_RECORD_MAX_BYTES;
356
+ }
357
+ async function continuousStatusLines(config, clock = Date.now) {
320
358
  if (!config.continuous) return ["Continuous sync: Off"];
321
359
  if (!config.agentMode) return ["Continuous sync: paused; enable Agent mode first"];
322
360
  try {
323
- const record = await readContinuousRecord(await continuousBinding(config));
361
+ const binding = await continuousBinding(config);
362
+ const document = await readContinuousPrivateDocument(`${binding}.json`);
363
+ const record = document === void 0 ? emptyContinuousRecord(binding) : document.value;
364
+ validateContinuousRecord(record, binding);
365
+ const bytes = serializedBytes(record);
366
+ const now = clock();
367
+ normalizeContinuousClock(record, now);
368
+ const spent = Object.values(record.attempts).filter((count) => count === 2).length;
369
+ const eligible = record.calls.length < 2 ? now : Math.min(...record.calls.map((call) => call.at)) + REQUEST_WINDOW_MS;
370
+ const capacityRecord = { ...record, calls: [...record.calls] };
371
+ normalizeContinuousClock(capacityRecord, eligible);
372
+ const available = hasReservationCapacity(capacityRecord, eligible);
373
+ const owner = await continuousLeaseOwner(binding).catch(
374
+ () => "Local scheduler lease: private owner metadata unavailable; retain evidence and repair access"
375
+ );
324
376
  return [
325
- `Continuous sync: ${record.phase}${record.error ? ` (${record.error})` : ""}`,
326
- await continuousLeaseOwner(record.binding),
327
- `Last successful background check: ${record.checked ? new Date(record.checked).toISOString() : "not yet checked"}`,
328
- `Last successful background transfer: ${record.transferred ? new Date(record.transferred).toISOString() : "none"}`,
377
+ `Continuous sync: ${record.phase}${record.error ? ` (${record.error})` : ""}${document === void 0 ? "; no accounting record yet" : ""}`,
378
+ owner,
379
+ "Scheduler owner model: unavailable; the observing session's selected model is not proof of the owner's model.",
380
+ `Automatic requests (rolling 15 minutes, window only): ${record.calls.length}/2 used; ${2 - record.calls.length} remaining.`,
381
+ `Next request eligibility: ${available ? eligible === now ? "now (window allowance)" : `${new Date(eligible).toISOString()} (window allowance)` : "unavailable (accounting full)"}. Candidate, capacity, ownership and safety checks still apply.`,
382
+ `Spent candidates: ${spent} exhausted / ${Object.keys(record.attempts).length} tracked; 2 automatic requests per candidate. Expired windows do not clear this limit.`,
383
+ `Accounting: ${bytes}/${CONTINUOUS_RECORD_MAX_BYTES} serialized bytes; ${Math.max(0, CONTINUOUS_RECORD_MAX_BYTES - bytes)} bytes free; ${document?.bytes ?? 0} bytes on disk${available ? "." : "; full for another reservation."}`,
384
+ ...!available ? [
385
+ "Accounting recovery: pause Continuous sync and seek reviewed recovery. Do not delete accounting, prune candidates or reset limits to regain requests."
386
+ ] : [],
387
+ `Last successful background check: ${record.checked !== void 0 ? new Date(record.checked).toISOString() : "not yet checked"}`,
388
+ `Last successful background transfer: ${record.transferred !== void 0 ? new Date(record.transferred).toISOString() : "none"}`,
329
389
  ...record.phase === "retry" ? [`Next background attempt: ${new Date(record.next).toISOString()}`] : [],
330
- ...record.phase === "blocked" ? ["Background sync needs changed evidence or repair. Review /sync, or use Sync now for an explicit retry."] : [],
390
+ ...record.error ? [`Recovery (${record.error}): ${recoveryActions[record.error]}`] : [],
391
+ ...record.phase === "blocked" && !record.error ? ["Review /sync diagnostics and repair changed evidence. Retain private recovery state."] : [],
331
392
  "Monitoring requires an eligible open Pi session. Status does not spend model requests or clear retry limits."
332
393
  ];
333
394
  } catch {
334
- return ["Continuous sync: private state unavailable; retain evidence and repair access before retrying."];
395
+ return [
396
+ "Continuous sync: private state unavailable; usage, eligibility and accounting bytes cannot be verified.",
397
+ `Accounting capacity: ${CONTINUOUS_RECORD_MAX_BYTES} bytes; do not treat unavailable accounting as unused allowance.`,
398
+ "Recovery: pause Continuous sync, retain malformed, unknown or unsafe evidence, and repair private-state access. Do not delete accounting or reset limits."
399
+ ];
335
400
  }
336
401
  }
337
402
 
@@ -347,4 +412,4 @@ export {
347
412
  reserveContinuousRequest,
348
413
  continuousStatusLines
349
414
  };
350
- //# sourceMappingURL=chunk-VJN7KU4J.ts.map
415
+ //# sourceMappingURL=chunk-PG7NMFP2.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sync/continuous-lease.ts", "../../src/sync/continuous-storage.ts", "../../src/sync/continuous-record.ts"],
4
+ "sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport { lstatSync, readFileSync, rmdirSync, type Stats, stat } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { withLock } from \"../state/lock.js\";\nimport { LOCKFILE_FS_ADAPTER } from \"../state/lockfile-fs.js\";\nimport {\n continuousRoot,\n prepareContinuousRoot,\n readContinuousPrivate,\n writeContinuousPrivate,\n} from \"./continuous-storage.js\";\n\nconst STALE_MS = 30_000;\nconst localLeases = new Set<string>();\nconst futureGuards = new Map<string, { identity: string; since: number }>();\ninterface Owner {\n version: 1;\n id: string;\n pid: number;\n binding: string;\n}\nexport interface ContinuousLease {\n signal: AbortSignal;\n assert(): void;\n release(): Promise<void>;\n}\nfunction validOwner(value: unknown): value is Owner {\n if (!value || typeof value !== \"object\") return false;\n const owner = value as Owner;\n return (\n Object.keys(owner).sort().join(\",\") === \"binding,id,pid,version\" &&\n owner.version === 1 &&\n typeof owner.id === \"string\" &&\n /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/u.test(owner.id) &&\n Number.isSafeInteger(owner.pid) &&\n owner.pid > 0 &&\n owner.pid <= 2147483647 &&\n typeof owner.binding === \"string\" &&\n /^[a-f0-9]{64}$/u.test(owner.binding)\n );\n}\n\n/** Advisory only: never authority for a transfer or lease takeover. */\nexport async function continuousLeaseOwner(binding: string): Promise<string> {\n const owner = await readContinuousPrivate(\"owner.json\");\n if (owner === undefined) return \"Local scheduler lease: not observed; waiting for an eligible session\";\n if (!validOwner(owner)) throw new Error(\"Invalid continuous sync owner\");\n try {\n const guard = await fs.lstat(path.join(continuousRoot(), \"scheduler.lock\"));\n if (guard.isDirectory() && !guard.isSymbolicLink() && Date.now() - guard.mtimeMs <= STALE_MS)\n return `Local scheduler lease: observed for pid ${owner.pid}; ${owner.binding === binding ? \"this can be another session\" : \"another setup; this setup is standby\"}`;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n return \"Local scheduler lease: not observed; waiting for an eligible session\";\n}\n\n/** Caller holds state-directory access during acquisition; the renewable guard prevents live migration. */\nexport async function acquireContinuousLease(binding: string): Promise<ContinuousLease | undefined> {\n await prepareContinuousRoot();\n const file = path.join(continuousRoot(), \"scheduler\");\n const guardPath = `${file}.lock`;\n if (localLeases.has(file)) return undefined;\n const previousOwner = await readContinuousPrivate(\"owner.json\");\n if (previousOwner !== undefined && !validOwner(previousOwner))\n throw new Error(\"Invalid continuous sync owner; evidence retained.\");\n if (localLeases.has(file)) return undefined;\n localLeases.add(file);\n const acquiredAt = performance.now();\n const ownerPath = path.join(continuousRoot(), \"owner.json\");\n const controller = new AbortController();\n const owner: Owner = { version: 1, id: randomUUID(), pid: process.pid, binding };\n let identity: { dev: number; ino: number } | undefined;\n let published = false;\n // proper-lockfile also uses rmdirSync at process exit. Fence both cleanup paths.\n const removeGuard = (target: string) => {\n if (identity) {\n const current = lstatSync(target);\n if (current.dev !== identity.dev || current.ino !== identity.ino) return;\n }\n let current: unknown;\n try {\n const record = lstatSync(ownerPath);\n if (\n !record.isFile() ||\n record.isSymbolicLink() ||\n record.nlink !== 1 ||\n record.size > 4096 ||\n (process.platform !== \"win32\" && record.mode & 0o077)\n )\n return;\n current = JSON.parse(readFileSync(ownerPath, \"utf8\"));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n if (published && current === undefined) return;\n if (\n current !== undefined &&\n (!validOwner(current) ||\n (current.id !== owner.id && (published || current.id !== (previousOwner as Owner | undefined)?.id)))\n )\n return;\n rmdirSync(target);\n };\n const adapter = {\n ...LOCKFILE_FS_ADAPTER,\n stat: (target: string, callback: (error: NodeJS.ErrnoException | null, value?: Stats) => void) =>\n stat(target, (error, value) => {\n if (!error && value.mtimeMs > Date.now() + STALE_MS) {\n const identity = `${value.dev}:${value.ino}:${value.mtimeMs}`;\n const previous = futureGuards.get(target);\n if (!previous || previous.identity !== identity)\n futureGuards.set(target, { identity, since: performance.now() });\n else if (performance.now() - previous.since > STALE_MS) value.mtime = new Date(Date.now() - STALE_MS - 1);\n } else futureGuards.delete(target);\n callback(error, value);\n }),\n rmdirSync: removeGuard,\n rmdir: (target: string, callback: (error?: NodeJS.ErrnoException | null) => void) => {\n try {\n removeGuard(target);\n callback();\n } catch (error) {\n callback(error as NodeJS.ErrnoException);\n }\n },\n };\n let compromised = false;\n let unlock: () => Promise<void>;\n try {\n unlock = await lockfile.lock(file, {\n fs: adapter,\n realpath: false,\n stale: STALE_MS,\n update: 10_000,\n retries: 0,\n onCompromised: () => {\n compromised = true;\n controller.abort(new DOMException(\"Continuous sync ownership lost\", \"AbortError\"));\n },\n });\n } catch (error) {\n localLeases.delete(file);\n if ((error as NodeJS.ErrnoException).code === \"ELOCKED\") return undefined;\n throw error;\n }\n let released = false;\n const release = async () => {\n if (released) return;\n released = true;\n controller.abort(new DOMException(\"Continuous sync owner released\", \"AbortError\"));\n try {\n if (!compromised) await unlock();\n } finally {\n localLeases.delete(file);\n futureGuards.delete(guardPath);\n }\n };\n try {\n identity = await fs.lstat(guardPath);\n await withLock(\"continuous-owner\", async () => {\n const previous = await readContinuousPrivate(\"owner.json\");\n if (previous !== undefined && !validOwner(previous))\n throw new Error(\"Invalid continuous sync owner; evidence retained.\");\n if (\n (previous as Owner | undefined)?.id !== (previousOwner as Owner | undefined)?.id ||\n performance.now() - acquiredAt > STALE_MS\n )\n throw new Error(\"Continuous lease generation changed before publication.\");\n const current = lstatSync(guardPath);\n if (controller.signal.aborted || current.dev !== identity?.dev || current.ino !== identity.ino)\n throw new Error(\"Continuous lease changed before publication.\");\n await writeContinuousPrivate(\"owner.json\", owner);\n published = true;\n });\n const assert = () => {\n controller.signal.throwIfAborted();\n try {\n const root = lstatSync(continuousRoot());\n if (!root.isDirectory() || root.isSymbolicLink() || (process.platform !== \"win32\" && root.mode & 0o077))\n throw new Error(\"Unsafe lease root\");\n const stat = lstatSync(guardPath);\n if (\n stat.isSymbolicLink() ||\n !stat.isDirectory() ||\n stat.dev !== identity?.dev ||\n stat.ino !== identity.ino ||\n Date.now() - stat.mtimeMs > STALE_MS\n )\n throw new Error(\"Lease guard changed\");\n const record = lstatSync(ownerPath);\n if (\n !record.isFile() ||\n record.isSymbolicLink() ||\n record.nlink !== 1 ||\n record.size > 4096 ||\n (process.platform !== \"win32\" && record.mode & 0o077)\n )\n throw new Error(\"Unsafe owner record\");\n const value: unknown = JSON.parse(readFileSync(ownerPath, \"utf8\"));\n if (!validOwner(value) || value.id !== owner.id || value.binding !== binding || value.pid !== process.pid)\n throw new Error(\"Lease owner changed\");\n } catch {\n controller.abort(new DOMException(\"Continuous sync ownership lost\", \"AbortError\"));\n controller.signal.throwIfAborted();\n }\n };\n assert();\n return { signal: controller.signal, assert, release };\n } catch (error) {\n await release();\n throw error;\n }\n}\n", "import { createHash } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport { backendIdentityCoordinates } from \"../backends/backend-identity.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { writeJson } from \"../state/json-file.js\";\nimport { stateDir } from \"../state/state-directory.js\";\nimport { ensureStateDir } from \"../state/sync-state-store.js\";\n\nexport const CONTINUOUS_RECORD_MAX_BYTES = 131072;\n\nexport function hashContinuous(value: unknown) {\n return createHash(\"sha256\")\n .update(JSON.stringify(value) ?? \"null\")\n .digest(\"hex\");\n}\nexport async function continuousBinding(config: AnySyncConfig) {\n return hashContinuous([await fs.realpath(getAgentDir()), config.setupName, backendIdentityCoordinates(config)]);\n}\nexport function continuousRoot() {\n return path.join(stateDir(), \"continuous\");\n}\nexport async function prepareContinuousRoot() {\n await ensureStateDir();\n await fs.mkdir(continuousRoot(), { recursive: true, mode: 0o700 });\n await checkContinuousRoot();\n}\nexport async function checkContinuousRoot() {\n const stat = await fs.lstat(continuousRoot());\n if (!stat.isDirectory() || stat.isSymbolicLink() || (process.platform !== \"win32\" && stat.mode & 0o077))\n throw new Error(\"Unsafe continuous sync directory; evidence retained.\");\n}\nexport async function readContinuousPrivate(name: string): Promise<unknown> {\n return (await readContinuousPrivateDocument(name))?.value;\n}\n/** Read-only metadata; uses the same private-file checks as runtime reads. */\nexport async function readContinuousPrivateDocument(\n name: string,\n): Promise<{ value: unknown; bytes: number } | undefined> {\n try {\n await checkContinuousRoot();\n const file = path.join(continuousRoot(), name);\n const stat = await fs.lstat(file);\n if (\n !stat.isFile() ||\n stat.isSymbolicLink() ||\n stat.nlink !== 1 ||\n stat.size > CONTINUOUS_RECORD_MAX_BYTES ||\n (process.platform !== \"win32\" && stat.mode & 0o077)\n )\n throw new Error(\"Unsafe continuous sync record; evidence retained.\");\n const bytes = await fs.readFile(file);\n return { value: JSON.parse(bytes.toString(\"utf8\")), bytes: bytes.byteLength };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\nexport async function writeContinuousPrivate(name: string, value: unknown) {\n await checkContinuousRoot();\n await readContinuousPrivate(name); // Never replace unsafe or malformed evidence.\n await writeJson(path.join(continuousRoot(), name), value, { maxBytes: CONTINUOUS_RECORD_MAX_BYTES });\n}\n", "import type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { withLock } from \"../state/lock.js\";\nimport { withStateDirectoryAccess } from \"../state/state-directory.js\";\nimport { ContinuousError, type ContinuousErrorKind } from \"./continuous-errors.js\";\nimport { type ContinuousLease, continuousLeaseOwner } from \"./continuous-lease.js\";\nimport {\n CONTINUOUS_RECORD_MAX_BYTES,\n continuousBinding,\n readContinuousPrivate,\n readContinuousPrivateDocument,\n writeContinuousPrivate,\n} from \"./continuous-storage.js\";\n\nexport const REQUEST_WINDOW_MS = 15 * 60_000;\nexport interface ContinuousRecord {\n version: 1;\n binding: string;\n pending: boolean;\n phase: \"waiting\" | \"syncing\" | \"retry\" | \"blocked\";\n next: number;\n failures: number;\n evidence?: string;\n recovery?: string;\n notice?: string;\n configuration?: string;\n error?: ContinuousErrorKind;\n checked?: number;\n transferred?: number;\n calls: { key: string; at: number }[];\n attempts: Record<string, number>;\n}\nconst digest = (value: unknown) => typeof value === \"string\" && /^[a-f0-9]{64}$/u.test(value);\nconst timestamp = (value: unknown) =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0 && value <= 8_640_000_000_000_000;\nexport function validateContinuousRecord(value: unknown, binding: string): asserts value is ContinuousRecord {\n const record = value as ContinuousRecord;\n if (\n !record ||\n typeof record !== \"object\" ||\n record.version !== 1 ||\n record.binding !== binding ||\n Object.keys(record).some(\n (key) =>\n ![\n \"version\",\n \"binding\",\n \"pending\",\n \"phase\",\n \"next\",\n \"failures\",\n \"evidence\",\n \"recovery\",\n \"notice\",\n \"configuration\",\n \"error\",\n \"checked\",\n \"transferred\",\n \"calls\",\n \"attempts\",\n ].includes(key),\n ) ||\n typeof record.pending !== \"boolean\" ||\n ![\"waiting\", \"syncing\", \"retry\", \"blocked\"].includes(record.phase) ||\n !timestamp(record.next) ||\n !timestamp(record.failures) ||\n record.failures > 30 ||\n (record.evidence !== undefined && !digest(record.evidence)) ||\n (record.recovery !== undefined && !digest(record.recovery)) ||\n (record.notice !== undefined && !digest(record.notice)) ||\n (record.configuration !== undefined && !digest(record.configuration)) ||\n (record.error !== undefined &&\n ![\n \"transient\",\n \"contention\",\n \"stale\",\n \"authentication\",\n \"storage\",\n \"unsafe\",\n \"model\",\n \"budget\",\n \"unknown\",\n ].includes(record.error)) ||\n (record.checked !== undefined && !timestamp(record.checked)) ||\n (record.transferred !== undefined && !timestamp(record.transferred)) ||\n !Array.isArray(record.calls) ||\n record.calls.length > 2 ||\n record.calls.some(\n (call) => !call || Object.keys(call).sort().join(\",\") !== \"at,key\" || !digest(call.key) || !timestamp(call.at),\n ) ||\n !record.attempts ||\n typeof record.attempts !== \"object\" ||\n Array.isArray(record.attempts) ||\n Object.entries(record.attempts).some(\n ([key, count]) => !digest(key) || !Number.isInteger(count) || count < 1 || count > 2,\n ) ||\n record.calls.some(\n (call) => (record.attempts[call.key] ?? 0) < record.calls.filter((other) => other.key === call.key).length,\n )\n )\n throw new Error(\"Invalid continuous sync state; evidence retained.\");\n}\nfunction emptyContinuousRecord(binding: string): ContinuousRecord {\n return { version: 1, binding, pending: true, phase: \"waiting\", next: 0, failures: 0, calls: [], attempts: {} };\n}\nexport async function readContinuousRecord(binding: string): Promise<ContinuousRecord> {\n const value = await readContinuousPrivate(`${binding}.json`);\n if (value === undefined) return emptyContinuousRecord(binding);\n validateContinuousRecord(value, binding);\n return value;\n}\nexport async function updateContinuousRecord<T>(\n binding: string,\n lease: ContinuousLease,\n update: (record: ContinuousRecord) => T,\n): Promise<T> {\n return withStateDirectoryAccess(() =>\n withLock(\"continuous-state\", async () => {\n lease.assert();\n const record = await readContinuousRecord(binding);\n lease.assert();\n const result = update(record);\n validateContinuousRecord(record, binding);\n lease.assert();\n await writeContinuousPrivate(`${binding}.json`, record);\n lease.assert();\n return result;\n }),\n );\n}\nexport function normalizeContinuousClock(record: ContinuousRecord, now: number) {\n // A backward wall-clock jump cannot grant more calls: retain them for a full window.\n record.calls = record.calls\n .map((call) => ({ ...call, at: Math.min(call.at, now) }))\n .filter((call) => now - call.at < REQUEST_WINDOW_MS);\n record.next = Math.min(record.next, now + (record.error === \"budget\" ? REQUEST_WINDOW_MS : 300_000));\n}\nexport async function reserveContinuousRequest(\n binding: string,\n lease: ContinuousLease,\n key: string,\n clock: () => number = Date.now,\n signal?: AbortSignal,\n) {\n signal?.throwIfAborted();\n if (!digest(key)) throw new Error(\"Invalid continuous candidate key.\");\n let failure: ContinuousError | undefined;\n await updateContinuousRecord(binding, lease, (record) => {\n signal?.throwIfAborted();\n const now = clock();\n signal?.throwIfAborted();\n normalizeContinuousClock(record, now);\n if ((record.attempts[key] ?? 0) >= 2)\n failure = new ContinuousError(\n \"model\",\n \"Automatic request limit reached for this evidence. Change the evidence or review /sync; Sync now does not reset this limit.\",\n );\n else if (record.calls.length >= 2)\n failure = new ContinuousError(\n \"budget\",\n \"Automatic request window is full.\",\n Math.max(0, (record.calls[0]?.at ?? now) + REQUEST_WINDOW_MS - now),\n );\n else {\n record.attempts[key] = (record.attempts[key] ?? 0) + 1;\n record.calls.push({ key, at: now });\n }\n });\n // Atomic publication is not interruptible. A reservation written before cancellation stays spent.\n signal?.throwIfAborted();\n if (failure) throw failure;\n}\n\nconst recoveryActions: Record<ContinuousErrorKind, string> = {\n transient: \"Wait for the scheduled retry. Check network and service availability if failures continue.\",\n contention: \"Wait for the active sync operation to finish. Do not remove a live lock.\",\n stale: \"Wait for a fresh inspection after the retry delay. Local or remote evidence changed.\",\n authentication: \"Repair storage or Pi model authentication, then reopen /sync. Do not share credentials.\",\n storage: \"Repair private-state permissions, free space or storage access. Retain accounting and recovery evidence.\",\n unsafe:\n \"Remove secrets or repair unsupported conflicts. Changed evidence is inspected again; review /sync if needed.\",\n model:\n \"Review conflict evidence and Pi model access. Sync now reuses cached refusals; a refusal needs changed evidence or a separately confirmed retry.\",\n budget:\n \"Wait for the window allowance shown above. Waiting does not restore exhausted candidates or accounting capacity.\",\n unknown:\n \"Review /sync diagnostics and reconcile pending recovery before retrying. Do not delete private evidence or blindly republish.\",\n};\n\nfunction serializedBytes(record: ContinuousRecord): number {\n // Keep this aligned with writeJson's private-document encoding.\n return Buffer.byteLength(`${JSON.stringify(record, null, \"\\t\")}\\n`);\n}\n\n/** Check space for one reservation without retaining or publishing the synthetic candidate. */\nfunction hasReservationCapacity(record: ContinuousRecord, now: number): boolean {\n const existing = Object.keys(record.attempts).find((key) => record.attempts[key] === 1);\n let key = existing ?? \"0\".repeat(64);\n if (!existing) {\n for (let index = 1; record.attempts[key] !== undefined; index++) key = index.toString(16).padStart(64, \"0\");\n }\n return (\n serializedBytes({\n ...record,\n calls: [...record.calls, { key, at: now }],\n attempts: { ...record.attempts, [key]: (record.attempts[key] ?? 0) + 1 },\n }) <= CONTINUOUS_RECORD_MAX_BYTES\n );\n}\n\n/** Read-only status: no directory creation, lease, mutation, request reservation or provider call. */\nexport async function continuousStatusLines(config: AnySyncConfig, clock: () => number = Date.now): Promise<string[]> {\n if (!config.continuous) return [\"Continuous sync: Off\"];\n if (!config.agentMode) return [\"Continuous sync: paused; enable Agent mode first\"];\n try {\n const binding = await continuousBinding(config);\n const document = await readContinuousPrivateDocument(`${binding}.json`);\n const record = document === undefined ? emptyContinuousRecord(binding) : document.value;\n validateContinuousRecord(record, binding);\n const bytes = serializedBytes(record);\n // Only this detached read is normalized. A Status read never publishes clock repairs or expires durable calls.\n const now = clock();\n normalizeContinuousClock(record, now);\n const spent = Object.values(record.attempts).filter((count) => count === 2).length;\n const eligible =\n record.calls.length < 2 ? now : Math.min(...record.calls.map((call) => call.at)) + REQUEST_WINDOW_MS;\n const capacityRecord = { ...record, calls: [...record.calls] };\n normalizeContinuousClock(capacityRecord, eligible);\n const available = hasReservationCapacity(capacityRecord, eligible);\n const owner = await continuousLeaseOwner(binding).catch(\n () => \"Local scheduler lease: private owner metadata unavailable; retain evidence and repair access\",\n );\n return [\n `Continuous sync: ${record.phase}${record.error ? ` (${record.error})` : \"\"}${document === undefined ? \"; no accounting record yet\" : \"\"}`,\n owner,\n \"Scheduler owner model: unavailable; the observing session's selected model is not proof of the owner's model.\",\n `Automatic requests (rolling 15 minutes, window only): ${record.calls.length}/2 used; ${2 - record.calls.length} remaining.`,\n `Next request eligibility: ${available ? (eligible === now ? \"now (window allowance)\" : `${new Date(eligible).toISOString()} (window allowance)`) : \"unavailable (accounting full)\"}. Candidate, capacity, ownership and safety checks still apply.`,\n `Spent candidates: ${spent} exhausted / ${Object.keys(record.attempts).length} tracked; 2 automatic requests per candidate. Expired windows do not clear this limit.`,\n `Accounting: ${bytes}/${CONTINUOUS_RECORD_MAX_BYTES} serialized bytes; ${Math.max(0, CONTINUOUS_RECORD_MAX_BYTES - bytes)} bytes free; ${document?.bytes ?? 0} bytes on disk${available ? \".\" : \"; full for another reservation.\"}`,\n ...(!available\n ? [\n \"Accounting recovery: pause Continuous sync and seek reviewed recovery. Do not delete accounting, prune candidates or reset limits to regain requests.\",\n ]\n : []),\n `Last successful background check: ${record.checked !== undefined ? new Date(record.checked).toISOString() : \"not yet checked\"}`,\n `Last successful background transfer: ${record.transferred !== undefined ? new Date(record.transferred).toISOString() : \"none\"}`,\n ...(record.phase === \"retry\" ? [`Next background attempt: ${new Date(record.next).toISOString()}`] : []),\n ...(record.error ? [`Recovery (${record.error}): ${recoveryActions[record.error]}`] : []),\n ...(record.phase === \"blocked\" && !record.error\n ? [\"Review /sync diagnostics and repair changed evidence. Retain private recovery state.\"]\n : []),\n \"Monitoring requires an eligible open Pi session. Status does not spend model requests or clear retry limits.\",\n ];\n } catch {\n return [\n \"Continuous sync: private state unavailable; usage, eligibility and accounting bytes cannot be verified.\",\n `Accounting capacity: ${CONTINUOUS_RECORD_MAX_BYTES} bytes; do not treat unavailable accounting as unused allowance.`,\n \"Recovery: pause Continuous sync, retain malformed, unknown or unsafe evidence, and repair private-state access. Do not delete accounting or reset limits.\",\n ];\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs", "path", "stat", "fs", "path", "current", "identity", "stat", "key"]
7
+ }