@narumitw/pi-sync 0.57.11 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +29 -21
  3. package/dist/chunks/{agent-candidate-OCDPRI5G.ts → agent-candidate-U2NU3GUX.ts} +2 -2
  4. package/dist/chunks/{agent-plan-P5B5RGZ7.ts → agent-plan-3YXDIJXO.ts} +13 -10
  5. package/dist/chunks/agent-plan-3YXDIJXO.ts.map +7 -0
  6. package/dist/chunks/{agent-runner-WMSCKSCB.ts → agent-runner-FCRV2Z75.ts} +11 -10
  7. package/dist/chunks/agent-runner-FCRV2Z75.ts.map +7 -0
  8. package/dist/chunks/{agent-store-RJSMNOYP.ts → agent-store-7GINKTS7.ts} +2 -2
  9. package/dist/chunks/{agent-store-RJSMNOYP.ts.map → agent-store-7GINKTS7.ts.map} +2 -2
  10. package/dist/chunks/{agent-sync-EUK2CPSS.ts → agent-sync-2R4GG2MF.ts} +3 -3
  11. package/dist/chunks/{chunk-67INJPKR.ts → chunk-CQD2TJHE.ts} +4 -4
  12. package/dist/chunks/{chunk-67INJPKR.ts.map → chunk-CQD2TJHE.ts.map} +2 -2
  13. package/dist/chunks/{chunk-ZDDBZH72.ts → chunk-JYILGR3K.ts} +2 -2
  14. package/dist/chunks/{chunk-OKPPZA4D.ts → chunk-MG66XM5U.ts} +3 -3
  15. package/dist/chunks/{chunk-OKPPZA4D.ts.map → chunk-MG66XM5U.ts.map} +2 -2
  16. package/dist/chunks/{chunk-7OLLPPLU.ts → chunk-MMQIEDZ6.ts} +6 -6
  17. package/dist/chunks/{chunk-7OLLPPLU.ts.map → chunk-MMQIEDZ6.ts.map} +2 -2
  18. package/dist/chunks/{chunk-Q23JJW7E.ts → chunk-MW6KUQYA.ts} +7 -5
  19. package/dist/chunks/chunk-MW6KUQYA.ts.map +7 -0
  20. package/dist/chunks/{chunk-NLWS55B6.ts → chunk-QPC5HT3A.ts} +2 -2
  21. package/dist/chunks/{chunk-NLWS55B6.ts.map → chunk-QPC5HT3A.ts.map} +1 -1
  22. package/dist/chunks/{chunk-DRTC4PKM.ts → chunk-S5OCYVPS.ts} +2 -2
  23. package/dist/chunks/{chunk-DRTC4PKM.ts.map → chunk-S5OCYVPS.ts.map} +2 -2
  24. package/dist/chunks/{chunk-3IYAPMST.ts → chunk-U6GXGY5G.ts} +2 -2
  25. package/dist/chunks/{chunk-F7E3VFXU.ts → chunk-WQMYV4DW.ts} +8 -8
  26. package/dist/chunks/chunk-WQMYV4DW.ts.map +7 -0
  27. package/dist/chunks/{chunk-CPT2BN6N.ts → chunk-XEODG2PE.ts} +2 -2
  28. package/dist/chunks/chunk-YIPK23JW.ts +171 -0
  29. package/dist/chunks/chunk-YIPK23JW.ts.map +7 -0
  30. package/dist/chunks/{command-handler-F2E7A5T5.ts → command-handler-KCB6MCWS.ts} +12 -12
  31. package/dist/chunks/{command-handler-F2E7A5T5.ts.map → command-handler-KCB6MCWS.ts.map} +2 -2
  32. package/dist/chunks/{conflict-review-2QMO2K6Q.ts → conflict-review-GXA6Y7KY.ts} +2 -2
  33. package/dist/chunks/{continuous-record-AH7JGYKM.ts → continuous-record-EPHGR2DU.ts} +2 -2
  34. package/dist/chunks/{continuous-sync-VRMXCA5X.ts → continuous-sync-FAFNLEUW.ts} +19 -11
  35. package/dist/chunks/continuous-sync-FAFNLEUW.ts.map +7 -0
  36. package/dist/chunks/{manager-result-dispatcher-6W52NM7F.ts → manager-result-dispatcher-XCYPW7RC.ts} +4 -4
  37. package/dist/chunks/{manager-ui-LM7DSJ2Y.ts → manager-ui-FMZXKPX2.ts} +153 -183
  38. package/dist/chunks/manager-ui-FMZXKPX2.ts.map +7 -0
  39. package/dist/chunks/{remote-selection-ui-TD4C4W3J.ts → remote-selection-ui-MYM2YCPF.ts} +3 -3
  40. package/dist/chunks/{setup-switch-PIPXYPCW.ts → setup-switch-KLGESLQX.ts} +3 -3
  41. package/dist/chunks/{setup-wizard-RR5U3SUB.ts → setup-wizard-ZQAK35BP.ts} +3 -3
  42. package/dist/chunks/{sync-operations-CV3TULLD.ts → sync-operations-45APGOL3.ts} +9 -9
  43. package/dist/chunks/sync-operations-45APGOL3.ts.map +7 -0
  44. package/dist/index.ts +80 -65
  45. package/dist/index.ts.map +2 -2
  46. package/docs/agent-continuous-hardening.md +5 -5
  47. package/docs/agent-mode-verification.md +3 -3
  48. package/docs/agent-quality-verification.md +3 -3
  49. package/docs/continuous-sync-verification.md +2 -2
  50. package/docs/settings.md +9 -5
  51. package/docs/tui-contract.md +57 -3
  52. package/package.json +3 -3
  53. package/skills/configure-pi-sync/SKILL.md +3 -1
  54. package/skills/configure-pi-sync/references/configuration.md +61 -38
  55. package/src/commands/command-execution.ts +3 -3
  56. package/src/commands/command.ts +1 -1
  57. package/src/settings/settings-types.ts +1 -1
  58. package/src/sync/agent-candidate.ts +3 -3
  59. package/src/sync/agent-plan.ts +11 -8
  60. package/src/sync/agent-runner.ts +10 -9
  61. package/src/sync/agent-store.ts +1 -1
  62. package/src/sync/agent-sync.ts +3 -3
  63. package/src/sync/continuous-record.ts +1 -1
  64. package/src/sync/continuous-sync.ts +15 -6
  65. package/src/sync/merged-sync.ts +4 -4
  66. package/src/sync/startup-check.ts +1 -1
  67. package/src/sync/sync-mutations.ts +3 -3
  68. package/src/sync/sync-queries.ts +2 -2
  69. package/src/sync-extension.ts +71 -57
  70. package/src/ui/agent-mode-setting.ts +6 -6
  71. package/src/ui/manager-state.ts +1 -1
  72. package/src/ui/remote-selection-ui.ts +1 -1
  73. package/src/ui/settings-ui.ts +19 -55
  74. package/src/ui/setup/setup-switcher.ts +2 -2
  75. package/src/ui/sync-attention.ts +5 -3
  76. package/src/ui/sync-setups-ui.ts +2 -2
  77. package/src/ui/sync-status.ts +214 -3
  78. package/dist/chunks/agent-plan-P5B5RGZ7.ts.map +0 -7
  79. package/dist/chunks/agent-runner-WMSCKSCB.ts.map +0 -7
  80. package/dist/chunks/chunk-F7E3VFXU.ts.map +0 -7
  81. package/dist/chunks/chunk-K3RIEL6J.ts +0 -20
  82. package/dist/chunks/chunk-K3RIEL6J.ts.map +0 -7
  83. package/dist/chunks/chunk-Q23JJW7E.ts.map +0 -7
  84. package/dist/chunks/continuous-sync-VRMXCA5X.ts.map +0 -7
  85. package/dist/chunks/manager-ui-LM7DSJ2Y.ts.map +0 -7
  86. package/dist/chunks/sync-operations-CV3TULLD.ts.map +0 -7
  87. /package/dist/chunks/{agent-candidate-OCDPRI5G.ts.map → agent-candidate-U2NU3GUX.ts.map} +0 -0
  88. /package/dist/chunks/{agent-sync-EUK2CPSS.ts.map → agent-sync-2R4GG2MF.ts.map} +0 -0
  89. /package/dist/chunks/{chunk-ZDDBZH72.ts.map → chunk-JYILGR3K.ts.map} +0 -0
  90. /package/dist/chunks/{chunk-3IYAPMST.ts.map → chunk-U6GXGY5G.ts.map} +0 -0
  91. /package/dist/chunks/{chunk-CPT2BN6N.ts.map → chunk-XEODG2PE.ts.map} +0 -0
  92. /package/dist/chunks/{conflict-review-2QMO2K6Q.ts.map → conflict-review-GXA6Y7KY.ts.map} +0 -0
  93. /package/dist/chunks/{continuous-record-AH7JGYKM.ts.map → continuous-record-EPHGR2DU.ts.map} +0 -0
  94. /package/dist/chunks/{manager-result-dispatcher-6W52NM7F.ts.map → manager-result-dispatcher-XCYPW7RC.ts.map} +0 -0
  95. /package/dist/chunks/{remote-selection-ui-TD4C4W3J.ts.map → remote-selection-ui-MYM2YCPF.ts.map} +0 -0
  96. /package/dist/chunks/{setup-switch-PIPXYPCW.ts.map → setup-switch-KLGESLQX.ts.map} +0 -0
  97. /package/dist/chunks/{setup-wizard-RR5U3SUB.ts.map → setup-wizard-ZQAK35BP.ts.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sync/continuous-watch.ts", "../../src/sync/continuous-sync.ts"],
4
+ "sourcesContent": ["import { type FSWatcher, watch } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport { isDeniedPath } from \"../paths.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\n\n/** Hints only. The scheduler's periodic snapshot scan remains required. */\nexport async function watchContinuous(\n config: AnySyncConfig,\n changed: (settings: boolean) => void,\n): Promise<() => void> {\n const root = getAgentDir();\n const watchers: FSWatcher[] = [];\n const selected = config.include.map((item) => path.resolve(root, item));\n const relevant = (target: string) =>\n selected.some(\n (item) => target === item || target.startsWith(`${item}${path.sep}`) || item.startsWith(`${target}${path.sep}`),\n );\n const add = (directory: string, recursive: boolean) => {\n try {\n const watcher = watch(directory, { recursive, persistent: false }, (_event, file) => {\n // Unknown names can be our own private writes. Periodic scans cover them.\n if (!file) return;\n const target = path.resolve(directory, String(file));\n if (target === path.join(root, \"pi-sync.json\")) changed(true);\n else if (isDeniedPath(path.relative(root, target))) return;\n else if (relevant(target)) changed(false);\n });\n watcher.on(\"error\", () => watcher.close());\n watchers.push(watcher);\n } catch {\n /* Periodic scans cover unavailable or unsupported watchers. */\n }\n };\n add(root, false);\n const directories = new Set<string>();\n try {\n for (const target of selected) {\n try {\n const stat = await fs.lstat(target);\n if (stat.isSymbolicLink()) continue;\n const directory = stat.isDirectory() ? target : path.dirname(target);\n if (directory === root || directories.has(directory)) continue;\n directories.add(directory);\n add(directory, stat.isDirectory());\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") continue;\n // Missing targets are found by the parent hint or the next periodic scan.\n }\n }\n return () => {\n for (const watcher of watchers) watcher.close();\n };\n } catch (error) {\n for (const watcher of watchers) watcher.close();\n throw error;\n }\n}\n", "import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { loadConfigForCheck, syncCheckConfigFingerprint } from \"../settings/config.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport { withLock } from \"../state/lock.js\";\nimport { withStateDirectoryAccess } from \"../state/state-directory.js\";\nimport { readStateForConfig } from \"../state/sync-state-store.js\";\nimport { setSyncStatus, syncStatusFailureReason } from \"../ui/sync-status.js\";\nimport { withAgentSyncLock } from \"./agent-sync.js\";\nimport { ContinuousError, continuousFailure } from \"./continuous-errors.js\";\nimport { acquireContinuousLease, type ContinuousLease } from \"./continuous-lease.js\";\nimport {\n normalizeContinuousClock,\n readContinuousRecord,\n reserveContinuousRequest,\n updateContinuousRecord,\n} from \"./continuous-record.js\";\nimport { continuousBinding, hashContinuous } from \"./continuous-storage.js\";\nimport { watchContinuous } from \"./continuous-watch.js\";\nimport { readMergeJournal } from \"./merge-journal.js\";\nimport { createStartupTimings, type StartupTimingPublisher, type StartupTimings } from \"./startup-timings.js\";\nimport type { SyncLoaders } from \"./sync-loaders.js\";\nimport { captureMutationOwner } from \"./sync-local.js\";\nimport { fileHashMap } from \"./sync-state.js\";\n\nexport function continuousEnabled(config: Pick<AnySyncConfig, \"continuous\" | \"agentMode\">) {\n return Boolean(config.continuous && config.agentMode);\n}\nexport interface ContinuousClock {\n now(): number;\n random(): number;\n schedule(ms: number, run: () => void, kind?: \"wait\" | \"authorization\"): () => void;\n}\nconst systemClock: ContinuousClock = {\n now: () => Date.now(),\n random: () => Math.random(),\n schedule: (ms, run) => {\n const timer = setTimeout(run, ms);\n timer.unref?.();\n return () => clearTimeout(timer);\n },\n};\nconst LOCAL_CHECK_MS = 5_000;\nconst POLL_MS = 60_000;\nconst DEBOUNCE_MS = 1_000;\n\ninterface ContinuousStartup {\n signal: AbortSignal;\n debug: boolean;\n reported: boolean;\n}\n\n/** Created on first enabled session. No module/factory-owned timers or watchers. */\nexport function createContinuousSync(\n loaders: SyncLoaders,\n clock: ContinuousClock = systemClock,\n publish?: StartupTimingPublisher,\n) {\n const startups = new WeakMap<ExtensionContext[\"sessionManager\"], ContinuousStartup>();\n const repairNotices = new WeakSet<ExtensionContext[\"sessionManager\"]>();\n let task:\n | { owner: ExtensionContext[\"sessionManager\"]; controller: AbortController; promise: Promise<void>; clear(): void }\n | undefined;\n return {\n start(ctx: ExtensionContext, sessionSignal: AbortSignal, explicitRetry = false, debug = false) {\n if (!ctx.hasUI || (ctx.mode !== \"tui\" && ctx.mode !== \"rpc\") || sessionSignal.aborted || task) return;\n const controller = new AbortController();\n const signal = AbortSignal.any([sessionSignal, controller.signal]);\n const validateContext = captureMutationOwner(ctx);\n // The caller supplies the session-start debug value, including first activation after settings edits.\n const previousStartup = startups.get(ctx.sessionManager);\n const startup: ContinuousStartup =\n previousStartup?.signal === sessionSignal ? previousStartup : { signal: sessionSignal, debug, reported: false };\n startups.set(ctx.sessionManager, startup);\n const current = {\n owner: ctx.sessionManager,\n controller,\n promise: Promise.resolve(),\n clear: () => {\n try {\n validateContext();\n setSyncStatus(ctx, undefined);\n } catch {\n /* replaced session */\n }\n },\n };\n task = current;\n current.promise = (async () => {\n let explicit = explicitRetry;\n while (!signal.aborted) {\n try {\n await run(ctx, signal, explicit, startup);\n return;\n } catch {\n if (signal.aborted) return;\n try {\n validateContext();\n setSyncStatus(ctx, \"sync blocked: private state or settings need repair\", {\n activity: \"blocked\",\n reason: \"repair\",\n });\n if (!repairNotices.has(ctx.sessionManager)) {\n repairNotices.add(ctx.sessionManager);\n ctx.ui.notify(\n \"Continuous sync blocked: private state or settings need repair. Use /sync. Evidence was retained.\",\n \"warning\",\n );\n }\n } catch {\n return;\n }\n }\n explicit = false;\n // Only local prerequisites are retried here. No remote/model request can\n // pass a malformed settings/state read. A repair can resume monitoring.\n await wait(clock, LOCAL_CHECK_MS, signal);\n }\n })()\n .catch(() => {\n /* Cancellation/UI disposal must not leak a detached rejection. */\n })\n .finally(() => {\n if (task === current) task = undefined;\n });\n },\n async stop(owner?: ExtensionContext[\"sessionManager\"]) {\n const current = task;\n if (!current || (owner && current.owner !== owner)) return;\n current.controller.abort(new DOMException(\"Continuous sync interrupted\", \"AbortError\"));\n current.clear();\n await current.promise;\n },\n };\n\n async function run(ctx: ExtensionContext, signal: AbortSignal, explicitRetry: boolean, startup: ContinuousStartup) {\n const validateOwner = captureMutationOwner(ctx, signal);\n try {\n while (!signal.aborted) {\n validateOwner();\n const config = await loadConfigForCheck();\n validateOwner();\n if (!continuousEnabled(config)) return;\n try {\n if (ctx.isIdle()) {\n let lease: ContinuousLease | undefined;\n let binding = \"\";\n try {\n await withStateDirectoryAccess(async () => {\n validateOwner();\n binding = await continuousBinding(config);\n validateOwner();\n lease = await acquireContinuousLease(binding);\n validateOwner();\n });\n if (lease) {\n await monitor(ctx, config, binding, lease, signal, explicitRetry, startup);\n explicitRetry = false;\n } else setSyncStatus(ctx, \"sync waiting: another local owner\", { activity: \"idle\" });\n } finally {\n await lease?.release();\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n const failure = continuousFailure(error);\n if (!failure.retry && !(error instanceof Error && error.name === \"AbortError\")) throw error;\n setSyncStatus(ctx, `sync retry scheduled: ${failure.kind}`, {\n activity: \"retry\",\n reason: syncStatusFailureReason(failure.kind),\n });\n }\n validateOwner();\n if (!continuousEnabled(await loadConfigForCheck())) return;\n validateOwner();\n await wait(clock, LOCAL_CHECK_MS, signal);\n }\n } finally {\n // Shutdown/replacement owns clearing the old UI; do not call it from a stale continuation.\n if (!signal.aborted) {\n try {\n validateOwner();\n setSyncStatus(ctx, undefined);\n } catch {\n /* stale context */\n }\n }\n }\n }\n\n async function monitor(\n ctx: ExtensionContext,\n initial: AnySyncConfig,\n binding: string,\n lease: ContinuousLease,\n parent: AbortSignal,\n explicitRetry: boolean,\n startup: ContinuousStartup,\n ) {\n const signal = AbortSignal.any([parent, lease.signal]);\n const validateOwner = captureMutationOwner(ctx, signal);\n let config = initial;\n let closeWatch = () => {};\n let wake = () => {};\n let dirtyAt: number | undefined;\n let cycle: AbortController | undefined;\n const changed = (settings: boolean) => {\n dirtyAt = clock.now();\n if (settings) cycle?.abort(new DOMException(\"Continuous settings changed\", \"AbortError\"));\n wake();\n };\n const validate = () => {\n validateOwner();\n lease.assert();\n if (!ctx.isIdle()) throw new DOMException(\"Owning session became busy\", \"AbortError\");\n };\n const stopWatch = () => {\n closeWatch();\n wake();\n };\n signal.addEventListener(\"abort\", stopWatch, { once: true });\n let pollDue = 0;\n try {\n closeWatch = await watchContinuous(config, changed);\n validate();\n while (!signal.aborted && ctx.isIdle()) {\n validate();\n const latest = await loadConfigForCheck();\n validate();\n if (!continuousEnabled(latest) || (await continuousBinding(latest)) !== binding) return;\n validate();\n if (syncCheckConfigFingerprint(latest) !== syncCheckConfigFingerprint(config)) {\n closeWatch();\n config = latest;\n closeWatch = await watchContinuous(config, changed);\n validate();\n pollDue = 0;\n }\n const record = await readContinuousRecord(binding);\n validate();\n const now = clock.now();\n const oldClock = JSON.stringify([record.next, record.calls]);\n normalizeContinuousClock(record, now);\n if (oldClock !== JSON.stringify([record.next, record.calls])) {\n await updateContinuousRecord(binding, lease, (current) => normalizeContinuousClock(current, now));\n validate();\n }\n const configuration = hashContinuous([{ ...config, showStatus: undefined, debug: undefined }, ctx.model]);\n const controlChanged = record.configuration !== configuration;\n if (controlChanged || explicitRetry) {\n record.next = 0;\n pollDue = 0;\n }\n const hintDue = dirtyAt === undefined ? Number.POSITIVE_INFINITY : dirtyAt + DEBOUNCE_MS;\n const due = Math.max(record.error === \"budget\" ? 0 : record.next, Math.min(pollDue, hintDue));\n if (now >= due) {\n const timings = createStartupTimings(publish);\n const report = !startup.reported && startup.debug;\n startup.reported = true;\n let outcome: \"completed\" | \"stopped\" = \"stopped\";\n const force = explicitRetry || controlChanged;\n explicitRetry = false;\n const expectedModel = hashContinuous(ctx.model);\n const expectedConfig = syncCheckConfigFingerprint(config);\n dirtyAt = undefined;\n cycle = new AbortController();\n const cancelDeadline = clock.schedule(30_000, () =>\n cycle?.abort(new DOMException(\"Continuous cycle timed out\", \"TimeoutError\")),\n );\n const guard = new AbortController();\n const guardSignal = AbortSignal.any([signal, cycle.signal, guard.signal]);\n const activeCycle = cycle;\n // Transfer entrypoints supply each fresh settings read. Never let a new\n // transfer adopt authorization that changed after this cycle's inspection.\n const validateCycle = (latest?: AnySyncConfig) => {\n validate();\n if (\n (latest && syncCheckConfigFingerprint(latest) !== expectedConfig) ||\n hashContinuous(ctx.model) !== expectedModel\n )\n activeCycle.abort(new DOMException(\"Continuous authorization changed\", \"AbortError\"));\n activeCycle.signal.throwIfAborted();\n };\n const guardTask = (async () => {\n while (!guardSignal.aborted) {\n await wait(clock, LOCAL_CHECK_MS, guardSignal, undefined, \"authorization\");\n if (guardSignal.aborted) return;\n try {\n validate();\n const latest = await loadConfigForCheck();\n if (guardSignal.aborted) return;\n validateCycle(latest);\n } catch {\n activeCycle.abort(new DOMException(\"Continuous authorization unavailable\", \"AbortError\"));\n }\n }\n })().catch(() => {});\n try {\n await performCycle(\n ctx,\n config,\n binding,\n lease,\n AbortSignal.any([signal, cycle.signal]),\n validateCycle,\n configuration,\n force,\n timings,\n );\n outcome = \"completed\";\n } catch (error) {\n if (signal.aborted || !ctx.isIdle()) return;\n // A settings hint interrupts the old authorization; load it afresh, not as a failed transfer.\n if (cycle.signal.aborted && cycle.signal.reason?.name !== \"TimeoutError\") {\n pollDue = 0;\n continue;\n }\n const failure = continuousFailure(error);\n let announce = false;\n await updateContinuousRecord(binding, lease, (current) => {\n const now = clock.now();\n normalizeContinuousClock(current, now);\n const notice = hashContinuous([failure.kind, current.evidence, configuration]);\n announce = current.notice !== notice;\n if (!failure.retry) current.notice = notice;\n current.configuration = configuration;\n current.pending = true;\n current.error = failure.kind;\n current.phase = failure.retry ? \"retry\" : \"blocked\";\n current.failures = Math.min(30, current.failures + 1);\n const base = Math.min(300_000, 5_000 * 2 ** Math.min(6, current.failures - 1));\n const delay = Math.min(300_000, base + Math.floor(clock.random() * base * 0.2));\n current.next = now + Math.max(delay, failure.delay ?? 0);\n });\n validate();\n if (announce && !failure.retry)\n ctx.ui.notify(\n `Continuous sync blocked (${failure.kind}). Review /sync or repair the setup. Evidence was retained.`,\n \"warning\",\n );\n } finally {\n cancelDeadline();\n guard.abort();\n await guardTask;\n cycle = undefined;\n timings.publish(ctx, report, signal, \"continuous startup\", outcome);\n }\n pollDue = clock.now() + POLL_MS + Math.floor(clock.random() * 6_000);\n closeWatch();\n closeWatch = () => {};\n closeWatch = await watchContinuous(config, changed);\n validate();\n }\n validate();\n const state = await readContinuousRecord(binding);\n validate();\n setSyncStatus(\n ctx,\n state.phase === \"blocked\"\n ? `sync blocked: ${state.error}`\n : state.phase === \"retry\"\n ? `sync retry scheduled: ${state.error}`\n : \"sync waiting for changes\",\n state.phase === \"blocked\" || state.phase === \"retry\"\n ? { activity: state.phase, reason: syncStatusFailureReason(state.error) }\n : { activity: \"idle\" },\n );\n if (state.phase === \"retry\") pollDue = Math.min(pollDue, state.next);\n const next = Math.max(\n state.error === \"budget\" ? 0 : state.next,\n Math.min(pollDue, dirtyAt === undefined ? Number.POSITIVE_INFINITY : dirtyAt + DEBOUNCE_MS),\n );\n await wait(clock, Math.max(1, Math.min(LOCAL_CHECK_MS, next - clock.now())), signal, (callback) => {\n wake = callback;\n });\n }\n } finally {\n signal.removeEventListener(\"abort\", stopWatch);\n closeWatch();\n cycle?.abort();\n }\n }\n\n async function performCycle(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n binding: string,\n lease: ContinuousLease,\n signal: AbortSignal,\n validateOwner: (config?: AnySyncConfig) => void,\n configuration: string,\n force: boolean,\n timings: StartupTimings,\n ) {\n const validate = (latest?: AnySyncConfig) => {\n signal.throwIfAborted();\n validateOwner(latest);\n };\n validate();\n const current = await readContinuousRecord(binding);\n validate();\n // A newly pending journal may prove an uncertain commit. It is never authority to republish.\n const pending = await guardedLock(\"continuous-journal\", () => readMergeJournal(config));\n validate();\n if (\n !force &&\n !pending &&\n current.phase === \"blocked\" &&\n [\"authentication\", \"storage\", \"unknown\"].includes(current.error ?? \"\")\n )\n return;\n setSyncStatus(ctx, \"sync checking\", { activity: \"checking\" });\n const inspectionModule = await timings.measure(\"inspection import\", () => loaders.inspection());\n validate();\n const observed = await timings.measure(\"inspection and guards\", () =>\n guardedLock(\"continuous-check\", async () => {\n validate();\n const inspection = await inspectionModule.inspectSync(\n config,\n snapshotOptionsForContext(ctx, config),\n signal,\n undefined,\n timings,\n );\n validate();\n let localIdentity = inspection.localIdentity;\n if (!localIdentity) {\n const snapshotModule = await loaders.snapshot();\n validate();\n const local = await snapshotModule.createSnapshot(config.snapshotIdentity, {\n ...snapshotOptionsForContext(ctx, config),\n signal,\n });\n validate();\n localIdentity = hashContinuous(fileHashMap(local));\n }\n const journal = await readMergeJournal(config);\n validate();\n return { inspection, journal, localIdentity };\n }),\n );\n validate();\n const evidence = hashContinuous([\n configuration,\n observed.localIdentity,\n observed.inspection.head?.revision,\n observed.inspection.stateIdentity,\n ]);\n const recovery = observed.journal ? hashContinuous([evidence, observed.journal]) : undefined;\n const blocked =\n !force &&\n current.evidence === evidence &&\n ((current.phase === \"blocked\" && (!recovery || recovery === current.recovery)) ||\n (current.error === \"budget\" && current.next > clock.now() && !observed.journal));\n await updateContinuousRecord(binding, lease, (record) => {\n if (record.configuration !== configuration) {\n record.failures = 0;\n record.next = 0;\n }\n record.configuration = configuration;\n record.checked = clock.now();\n record.evidence = evidence;\n if (!blocked) {\n if (record.phase !== \"blocked\") record.phase = \"syncing\";\n record.pending = true;\n if (recovery) record.recovery = recovery;\n }\n });\n validate();\n if (blocked) return;\n if (\n !observed.journal &&\n (observed.inspection.firstSync ||\n !observed.inspection.head ||\n observed.inspection.selectionState?.kind !== \"same\")\n )\n throw new ContinuousError(\"unsafe\", \"Continuous sync needs an accepted baseline and matching remote selection.\");\n let transferred = false;\n if (observed.journal || observed.inspection.localChanged || observed.inspection.remoteChanged) {\n const operations = await timings.measure(\"operations import\", () => loaders.operations());\n validate();\n setSyncStatus(ctx, \"sync syncing\", { activity: \"working\" });\n const result = await timings.measure(\"automatic transfer\", () =>\n withStateDirectoryAccess(() =>\n withAgentSyncLock(\n ctx,\n {\n args: [],\n yes: true,\n force: false,\n stale: false,\n silent: true,\n reload: false,\n auto: true,\n signal,\n startupTimings: timings,\n background: {\n validate,\n reserve: (key, requestSignal) =>\n reserveContinuousRequest(binding, lease, key, () => clock.now(), requestSignal),\n },\n },\n (options) => operations.syncBoth(ctx, options),\n ),\n ),\n );\n validate();\n transferred = result === \"applied\";\n }\n const state = await guardedLock(\"continuous-result\", () => readStateForConfig(config));\n validate();\n const unresolved = state.unresolved;\n let announcePartial = false;\n await updateContinuousRecord(binding, lease, (record) => {\n record.phase = unresolved?.length ? \"blocked\" : \"waiting\";\n record.pending = Boolean(unresolved?.length);\n record.failures = 0;\n record.next = 0;\n if (unresolved?.length) {\n record.error = \"unsafe\";\n const notice = hashContinuous([\"partial\", unresolved, configuration]);\n announcePartial = record.notice !== notice;\n record.notice = notice;\n } else {\n delete record.error;\n delete record.notice;\n }\n if (transferred) record.transferred = clock.now();\n });\n validate();\n if (announcePartial)\n ctx.ui.notify(\n \"Continuous sync retained unresolved groups. Review /sync conflicts; independent partial progress was preserved.\",\n \"warning\",\n );\n }\n}\n\nfunction guardedLock<T>(command: string, run: () => Promise<T>) {\n return withStateDirectoryAccess(() => withLock(command, run));\n}\n\nfunction wait(\n clock: ContinuousClock,\n ms: number,\n signal: AbortSignal,\n expose?: (wake: () => void) => void,\n kind: \"wait\" | \"authorization\" = \"wait\",\n) {\n signal.throwIfAborted();\n return new Promise<void>((resolve) => {\n const done = () => {\n cancel();\n signal.removeEventListener(\"abort\", done);\n expose?.(() => {});\n resolve();\n };\n const cancel = clock.schedule(ms, done, kind);\n signal.addEventListener(\"abort\", done, { once: true });\n expose?.(done);\n if (signal.aborted) done();\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["latest", "now"]
7
+ }
@@ -2,8 +2,8 @@
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
3
  import {
4
4
  dispatchManagerResult
5
- } from "./chunk-ZDDBZH72.ts";
6
- import "./chunk-OKPPZA4D.ts";
5
+ } from "./chunk-JYILGR3K.ts";
6
+ import "./chunk-MG66XM5U.ts";
7
7
  import "./chunk-TIMWN2RH.ts";
8
8
  import "./chunk-OJARL2TG.ts";
9
9
  import "./chunk-TZC7GDJE.ts";
@@ -12,7 +12,7 @@ import "./chunk-FLHCOJCD.ts";
12
12
  import "./chunk-MKSMJPVA.ts";
13
13
  import "./chunk-GNYGNHFF.ts";
14
14
  import "./chunk-AMJRUXFT.ts";
15
- import "./chunk-K3RIEL6J.ts";
15
+ import "./chunk-YIPK23JW.ts";
16
16
  import "./chunk-7D5SF7P3.ts";
17
17
  import "./chunk-OVBAW7KV.ts";
18
18
  import "./chunk-X7R6DCVF.ts";
@@ -29,4 +29,4 @@ import "./chunk-FHE2DCA2.ts";
29
29
  export {
30
30
  dispatchManagerResult
31
31
  };
32
- //# sourceMappingURL=manager-result-dispatcher-6W52NM7F.ts.map
32
+ //# sourceMappingURL=manager-result-dispatcher-XCYPW7RC.ts.map
@@ -6,7 +6,7 @@ import {
6
6
  setupSwitchActionFromLabel,
7
7
  setupSwitchActionLabel,
8
8
  useSyncSetup
9
- } from "./chunk-CPT2BN6N.ts";
9
+ } from "./chunk-XEODG2PE.ts";
10
10
  import {
11
11
  applyS3CredentialUpdate,
12
12
  chooseS3CredentialUpdate,
@@ -26,16 +26,16 @@ import {
26
26
  showEditS3Target,
27
27
  showEditWebDavStorageProfile,
28
28
  showEditWebDavTarget
29
- } from "./chunk-3IYAPMST.ts";
29
+ } from "./chunk-U6GXGY5G.ts";
30
30
  import {
31
31
  automaticSyncSummary
32
32
  } from "./chunk-ECYCNZOE.ts";
33
33
  import {
34
34
  dispatchManagerResult
35
- } from "./chunk-ZDDBZH72.ts";
35
+ } from "./chunk-JYILGR3K.ts";
36
36
  import {
37
37
  runCancellableOperation
38
- } from "./chunk-OKPPZA4D.ts";
38
+ } from "./chunk-MG66XM5U.ts";
39
39
  import "./chunk-TIMWN2RH.ts";
40
40
  import "./chunk-OJARL2TG.ts";
41
41
  import {
@@ -60,12 +60,12 @@ import {
60
60
  observationMatchesConfig,
61
61
  observationSummary,
62
62
  syncAttentionMatchesConfig
63
- } from "./chunk-Q23JJW7E.ts";
63
+ } from "./chunk-MW6KUQYA.ts";
64
64
  import {
65
65
  AUTOMATIC_SYNC_DESCRIPTION,
66
66
  STARTUP_TRANSFER_DESCRIPTION,
67
67
  startupTransferSummary
68
- } from "./chunk-NLWS55B6.ts";
68
+ } from "./chunk-QPC5HT3A.ts";
69
69
  import {
70
70
  captureMutationOwner
71
71
  } from "./chunk-GNYGNHFF.ts";
@@ -74,7 +74,7 @@ import {
74
74
  } from "./chunk-AMJRUXFT.ts";
75
75
  import {
76
76
  configureSyncStatus
77
- } from "./chunk-K3RIEL6J.ts";
77
+ } from "./chunk-YIPK23JW.ts";
78
78
  import {
79
79
  errorMessage
80
80
  } from "./chunk-7D5SF7P3.ts";
@@ -190,7 +190,7 @@ function blockedSyncMenuItem(label, manager) {
190
190
  };
191
191
  }
192
192
  async function showManagerAttention(ctx, attention, runRoute, signal, onSelectionResolved) {
193
- const { showRemoteSelectionReview } = await import("./remote-selection-ui-TD4C4W3J.ts");
193
+ const { showRemoteSelectionReview } = await import("./remote-selection-ui-MYM2YCPF.ts");
194
194
  if (signal?.aborted) return "close";
195
195
  const review = await showRemoteSelectionReview(ctx, attention.decision.setupName, signal, void 0, {
196
196
  decision: attention.decision,
@@ -409,8 +409,8 @@ async function loadSetupMenuState(selectedName, signal) {
409
409
  `Sessions: ${selection.sessions ? "On \u2014 privacy-sensitive" : "Off"}`,
410
410
  `Automatic sync: ${config.automatic ? "On" : "Off"}`,
411
411
  `Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 may upload, replace, or delete selected files; no reload" : "Off"}`,
412
- `Agent mode: ${config.agentMode ? "On (experimental; autonomous merged sync)" : "Off"}`,
413
- `Continuous sync: ${config.continuous ? config.agentMode ? "On (experimental; recurring requests and transfers)" : "Saved On; paused until Agent mode is enabled" : "Off"}`,
412
+ `Autonomous sync: ${config.agentMode ? "On (autonomous merged sync)" : "Off"}`,
413
+ `Continuous sync: ${config.continuous ? config.agentMode ? "On (recurring requests and transfers)" : "Saved On; paused until Autonomous sync is enabled" : "Off"}`,
414
414
  isCurrent ? "Edit included content and automatic sync in /sync \u2192 Settings." : "To edit included content or automatic sync, make this setup current, then open /sync \u2192 Settings."
415
415
  ];
416
416
  } catch (error) {
@@ -559,8 +559,8 @@ async function describeManagerState(signal, attention, inspectOperation = inspec
559
559
  `Included: ${selection.builtIns.length} built-in group${selection.builtIns.length === 1 ? "" : "s"} \xB7 ${selection.custom.length} extra path${selection.custom.length === 1 ? "" : "s"} \xB7 Sessions ${selection.sessions ? "on" : "off"}`,
560
560
  `Automatic sync: ${automaticSyncSummary(config.automatic)}`,
561
561
  `Startup transfer: ${startupTransferSummary(config)}`,
562
- `Agent mode: ${config.agentMode ? "On (experimental; autonomous merged sync)" : "Off"}`,
563
- ...config.continuous ? await (await import("./continuous-record-AH7JGYKM.ts")).continuousStatusLines(config) : [],
562
+ `Autonomous sync: ${config.agentMode ? "On (autonomous merged sync)" : "Off"}`,
563
+ ...config.continuous ? await (await import("./continuous-record-EPHGR2DU.ts")).continuousStatusLines(config) : [],
564
564
  `Last applied: ${lastAppliedSnapshot}`,
565
565
  ...noSyncedContent ? ["", "No included content is selected. Choose included content in Settings before syncing."] : [],
566
566
  "",
@@ -655,8 +655,8 @@ import { defineMenu as defineMenu4, runMenu as runMenu4 } from "@narumitw/pi-tui
655
655
 
656
656
  // src/ui/agent-mode-setting.ts
657
657
  import { isDeepStrictEqual } from "node:util";
658
- var AGENT_MODE_DESCRIPTION = "This setup, experimental: one autonomous merged sync next startup and on Sync now. Sends eligible conflict text to the selected Pi model; may incur costs and replace/delete selected local and remote content without transfer prompts. No automatic reload. Unsupported conflicts pause.";
659
- var CONTINUOUS_DESCRIPTION = "This setup, experimental: recurring sync while Pi is open. Requires Agent mode. Watches selected files, checks the remote every 60\u201366 seconds, and retries temporary failures. Local changes and retries can cause extra requests between polls. May disclose conflict text and incur model/storage costs. No automatic reload.";
658
+ var AGENT_MODE_DESCRIPTION = "This setup: sync eligible changes at session startup and on Sync now without transfer confirmation. Use the selected Pi model to resolve supported text and settings conflicts. Eligible conflict content may be sent to its provider and incur costs. Selected local and remote content can be replaced or deleted. Unresolved conflicts pause unless partial sync permits independent progress. Continuous sync is a separate opt-in. No automatic reload.";
659
+ var CONTINUOUS_DESCRIPTION = "This setup: recurring sync while Pi is open. Requires Autonomous sync. Watches selected files, checks the remote every 60\u201366 seconds, and retries temporary failures. Local changes and retries can cause extra requests between polls. May disclose conflict text and incur model/storage costs. No automatic reload.";
660
660
  function saveContinuousMode(ctx, setupName, enabled, signal) {
661
661
  return saveAgentMode(ctx, setupName, enabled, signal, "continuous");
662
662
  }
@@ -667,8 +667,8 @@ async function saveAgentMode(ctx, setupName, enabled, signal, preference = "agen
667
667
  const setup = settings.syncSetups[setupName];
668
668
  if (!setup || settings.activeSyncSetup !== setupName) throw new Error("Current sync setup changed; reopen Settings.");
669
669
  const continuous = preference === "continuous";
670
- const label = continuous ? "Continuous sync" : "Agent mode";
671
- if (enabled && continuous && !setup.sync.agentMode) throw new Error("Enable Agent mode before Continuous sync.");
670
+ const label = continuous ? "Continuous sync" : "Autonomous sync";
671
+ if (enabled && continuous && !setup.sync.agentMode) throw new Error("Enable Autonomous sync before Continuous sync.");
672
672
  if (Boolean(setup.sync[preference]) === enabled) return true;
673
673
  if (enabled) {
674
674
  const summary = [
@@ -688,7 +688,7 @@ async function saveAgentMode(ctx, setupName, enabled, signal, preference = "agen
688
688
  ].join("\n\n");
689
689
  if (!await confirmMergeReview(
690
690
  ctx,
691
- `Enable experimental ${label}?`,
691
+ `Enable ${label}?`,
692
692
  summary,
693
693
  signal,
694
694
  () => !signal?.aborted,
@@ -704,7 +704,7 @@ async function saveAgentMode(ctx, setupName, enabled, signal, preference = "agen
704
704
  current.storageConnections[setup.storage.connection],
705
705
  settings.storageConnections[setup.storage.connection]
706
706
  ))
707
- throw new Error("Sync setup or connection changed during Agent mode review; reopen Settings.");
707
+ throw new Error("Sync setup or connection changed during Autonomous sync review; reopen Settings.");
708
708
  return {
709
709
  ...current,
710
710
  syncSetups: { ...current.syncSetups, [setupName]: { ...setup, sync: { ...setup.sync, [preference]: enabled } } }
@@ -1165,8 +1165,8 @@ async function showSetupSwitcher(ctx, runRoute, selectedName, signal) {
1165
1165
  `Included content: ${config.include.length} paths`,
1166
1166
  `Automatic sync: ${automaticSyncSummary(config.automatic)} \xB7 Sessions: ${config.include.includes("sessions") ? "On" : "Off"}`,
1167
1167
  `Automatic transfer at startup: ${config.automaticTransfer ? "On \u2014 may upload, replace, or delete selected files; no reload" : "Off"}`,
1168
- `Agent mode: ${config.agentMode ? "On (experimental; autonomous merged sync)" : "Off"}`,
1169
- `Continuous sync: ${config.continuous ? config.agentMode ? "On (experimental; recurring requests and transfers)" : "Saved On; paused until Agent mode is enabled" : "Off"}`,
1168
+ `Autonomous sync: ${config.agentMode ? "On (autonomous merged sync)" : "Off"}`,
1169
+ `Continuous sync: ${config.continuous ? config.agentMode ? "On (recurring requests and transfers)" : "Saved On; paused until Autonomous sync is enabled" : "Off"}`,
1170
1170
  "",
1171
1171
  switchEffect
1172
1172
  ].join("\n"),
@@ -1356,172 +1356,142 @@ async function showSyncSettings(ctx, runRoute, signal, reviewedSetup) {
1356
1356
  const initial = await loadConfig(reviewedSetup);
1357
1357
  if (signal?.aborted) return "back";
1358
1358
  const setupName = initial.setupName;
1359
- const groups = {
1360
- content: { label: "Sync content", ids: ["include", "remoteInclude", "localFields"] },
1361
- behavior: {
1362
- label: "Sync behavior",
1363
- ids: ["automatic", "automaticTransfer", "agentMode", "continuous", "onSwitch"]
1364
- },
1365
- storage: { label: "Storage & setups", ids: ["storageLocation", "setups", "connections"] },
1366
- advanced: { label: "Advanced", ids: ["mergeSettings", "contentPolicy", "skipSecretScan", "showStatus", "debug"] },
1367
- all: { label: "All settings (search)", ids: [] }
1368
- };
1369
1359
  let saveStatus = "Simple choices save immediately. Back does not undo saved changes.";
1370
- const settingsScreen = (state, group) => ({
1371
- kind: "settings",
1372
- title: `Pi Sync Settings \xB7 ${groups[group].label}`,
1373
- lines: [
1374
- `Setup: ${safeTerminalText(state.setupName)} \xB7 Connection: ${safeTerminalText(state.connectionName)}`,
1375
- saveStatus
1376
- ],
1377
- items: [
1378
- {
1379
- id: "include",
1380
- label: "Included paths",
1381
- description: "This setup: choose paths in a draft, then review and Save or Discard. No transfer is started.",
1382
- currentValue: `${state.include.length} paths \xB7 Edit`,
1383
- action: "include"
1384
- },
1385
- {
1386
- id: "remoteInclude",
1387
- label: "Compare included paths",
1388
- description: "This setup: compare included-path policies, not file contents. Review before saving either list; no files transfer unless you explicitly Continue.",
1389
- currentValue: "Review",
1390
- action: "remote-include"
1391
- },
1392
- {
1393
- id: "localFields",
1394
- label: "Machine-local fields",
1395
- description: "This setup: settings.json root fields excluded from future portable snapshots, not project overrides. Policy changes require reviewed directional migration; old history remains.",
1396
- currentValue: `${state.localFields?.length ?? 0} fields \xB7 Edit`,
1397
- action: "local-fields"
1398
- },
1399
- {
1400
- id: "storageLocation",
1401
- label: "Storage location",
1402
- description: "This setup: review and save bucket, branch, or path changes. Remote history is not moved.",
1403
- currentValue: state.backend.type === "s3" ? `${safeTerminalText(state.backend.destination.bucket)} \xB7 ${safeTerminalText(state.backend.destination.prefix)}` : state.backend.type === "git" ? `${safeTerminalText(state.backend.destination.branch)} \xB7 ${safeTerminalText(state.backend.destination.directory)}` : safeTerminalText(state.backend.destination.path),
1404
- action: "storage-location"
1405
- },
1406
- {
1407
- id: "setups",
1408
- label: "Manage sync setups",
1409
- description: "This device: add, switch, edit, or remove sync setups. Each edit identifies its owner before saving.",
1410
- currentValue: "Open",
1411
- action: "setups"
1412
- },
1413
- {
1414
- id: "connections",
1415
- label: "Manage storage connections",
1416
- description: "Shared connections on this device: review affected setups before saving server or credential changes.",
1417
- currentValue: "Open",
1418
- action: "connections"
1419
- },
1420
- {
1421
- id: "automatic",
1422
- label: "Automatic sync",
1423
- description: AUTOMATIC_SYNC_DESCRIPTION,
1424
- currentValue: state.automatic ? "On" : "Off",
1425
- values: ["On", "Off"],
1426
- action: "automatic"
1427
- },
1428
- {
1429
- id: "automaticTransfer",
1430
- label: "Startup transfer",
1431
- description: `${STARTUP_TRANSFER_DESCRIPTION} Saved preference and requirements: ${startupTransferSummary(state)}.`,
1432
- currentValue: state.automaticTransfer ? "On" : "Off",
1433
- values: ["On", "Off"],
1434
- action: "automatic-transfer"
1435
- },
1436
- {
1437
- id: "agentMode",
1438
- label: "Agent mode (experimental)",
1439
- description: AGENT_MODE_DESCRIPTION,
1440
- currentValue: state.agentMode ? "On" : "Off",
1441
- values: ["On", "Off"],
1442
- action: "agent-mode"
1443
- },
1444
- {
1445
- id: "continuous",
1446
- label: "Continuous sync (experimental)",
1447
- description: `${CONTINUOUS_DESCRIPTION}${state.continuous && !state.agentMode ? " Saved On, but paused until Agent mode is enabled." : ""}`,
1448
- currentValue: state.continuous ? "On" : "Off",
1449
- values: ["On", "Off"],
1450
- action: "continuous"
1451
- },
1452
- {
1453
- id: "onSwitch",
1454
- label: "On setup switch",
1455
- description: "All setups on this device: ask before a pull review, open it automatically, or switch without pulling. Applies to subsequent switches.",
1456
- currentValue: setupSwitchActionLabel(state.onSwitch),
1457
- values: SETUP_SWITCH_ACTION_OPTIONS.map(({ label }) => label),
1458
- action: "on-switch"
1459
- },
1460
- {
1461
- id: "mergeSettings",
1462
- label: "Merge settings fields",
1463
- description: "This setup, experimental opt-in: merge independent global settings.json root fields with a verified private ancestor. Arrays and nested objects remain atomic. Applies to subsequent sync; no reload.",
1464
- currentValue: state.mergeSettings ? "On" : "Off",
1465
- values: ["On", "Off"],
1466
- action: "merge-settings"
1467
- },
1468
- {
1469
- id: "contentPolicy",
1470
- label: "Content merge / partial progress",
1471
- description: "This setup, experimental opt-in: review the version-5 upgrade before saving. Merge bounded text and prefix-only sessions; partial progress keeps withheld versions and baselines. Applies to subsequent sync; disabling does not clear recovery evidence.",
1472
- currentValue: state.mergeContent ? state.partialSync ? "Merge + partial" : "Merge only" : state.partialSync ? "Partial only" : "Off",
1473
- values: ["Off", "Merge only", "Merge + partial", "Partial only"],
1474
- action: "content-policy"
1475
- },
1476
- {
1477
- id: "skipSecretScan",
1478
- label: "Skip secret scan",
1479
- description: "All setups on this device: skip possible-secret checks on subsequent pushes, including automatic pushes. Other safety checks remain. Diagnostics still scans.",
1480
- currentValue: state.skipSecretScan ? "On" : "Off",
1481
- values: ["On", "Off"],
1482
- action: "skip-secret-scan"
1483
- },
1484
- {
1485
- id: "showStatus",
1486
- label: "Show sync status",
1487
- description: "All setups on this device: saved and applied immediately to Pi status. Review widgets and notifications remain available.",
1488
- currentValue: state.showStatus ? "On" : "Off",
1489
- values: ["On", "Off"],
1490
- action: "show-status"
1491
- },
1492
- {
1493
- id: "debug",
1494
- label: "Debug startup timings",
1495
- description: "All setups on this device: show startup durations in the TUI transcript or RPC notifications, including initial Continuous sync. Applies next session start; no credentials or file contents.",
1496
- currentValue: state.debug ? "On" : "Off",
1497
- values: ["On", "Off"],
1498
- action: "debug"
1499
- }
1500
- ].filter((item) => group === "all" || groups[group].ids.includes(item.id))
1501
- });
1502
1360
  const menu = defineMenu4({
1503
- start: "categories",
1361
+ start: "settings",
1504
1362
  screens: {
1505
- categories: ({ state }) => ({
1506
- kind: "actions",
1363
+ settings: ({ state }) => ({
1364
+ kind: "settings",
1507
1365
  title: "Pi Sync Settings",
1508
1366
  lines: [
1509
1367
  `Setup: ${safeTerminalText(state.setupName)} \xB7 Connection: ${safeTerminalText(state.connectionName)}`,
1510
- "Choose a task, or search all settings. Scope is shown in each setting's description.",
1511
1368
  saveStatus
1512
1369
  ],
1513
- items: Object.entries(groups).map(([id, group]) => ({
1514
- id,
1515
- label: group.label,
1516
- to: id
1517
- })),
1518
- hint: "back"
1519
- }),
1520
- content: ({ state }) => settingsScreen(state, "content"),
1521
- behavior: ({ state }) => settingsScreen(state, "behavior"),
1522
- storage: ({ state }) => settingsScreen(state, "storage"),
1523
- advanced: ({ state }) => settingsScreen(state, "advanced"),
1524
- all: ({ state }) => settingsScreen(state, "all")
1370
+ items: [
1371
+ {
1372
+ id: "include",
1373
+ label: "Included paths",
1374
+ description: "This setup: choose paths in a draft, then review and Save or Discard. No transfer is started.",
1375
+ currentValue: `${state.include.length} paths \xB7 Edit`,
1376
+ action: "include"
1377
+ },
1378
+ {
1379
+ id: "remoteInclude",
1380
+ label: "Compare included paths",
1381
+ description: "This setup: compare included-path policies, not file contents. Review before saving either list; no files transfer unless you explicitly Continue.",
1382
+ currentValue: "Review",
1383
+ action: "remote-include"
1384
+ },
1385
+ {
1386
+ id: "localFields",
1387
+ label: "Machine-local fields",
1388
+ description: "This setup: settings.json root fields excluded from future portable snapshots, not project overrides. Policy changes require reviewed directional migration; old history remains.",
1389
+ currentValue: `${state.localFields?.length ?? 0} fields \xB7 Edit`,
1390
+ action: "local-fields"
1391
+ },
1392
+ {
1393
+ id: "storageLocation",
1394
+ label: "Storage location",
1395
+ description: "This setup: review and save bucket, branch, or path changes. Remote history is not moved.",
1396
+ currentValue: state.backend.type === "s3" ? `${safeTerminalText(state.backend.destination.bucket)} \xB7 ${safeTerminalText(state.backend.destination.prefix)}` : state.backend.type === "git" ? `${safeTerminalText(state.backend.destination.branch)} \xB7 ${safeTerminalText(state.backend.destination.directory)}` : safeTerminalText(state.backend.destination.path),
1397
+ action: "storage-location"
1398
+ },
1399
+ {
1400
+ id: "setups",
1401
+ label: "Manage sync setups",
1402
+ description: "This device: add, switch, edit, or remove sync setups. Each edit identifies its owner before saving.",
1403
+ currentValue: "Open",
1404
+ action: "setups"
1405
+ },
1406
+ {
1407
+ id: "connections",
1408
+ label: "Manage storage connections",
1409
+ description: "Shared connections on this device: review affected setups before saving server or credential changes.",
1410
+ currentValue: "Open",
1411
+ action: "connections"
1412
+ },
1413
+ {
1414
+ id: "automatic",
1415
+ label: "Automatic sync",
1416
+ description: AUTOMATIC_SYNC_DESCRIPTION,
1417
+ currentValue: state.automatic ? "On" : "Off",
1418
+ values: ["On", "Off"],
1419
+ action: "automatic"
1420
+ },
1421
+ {
1422
+ id: "automaticTransfer",
1423
+ label: "Startup transfer",
1424
+ description: `${STARTUP_TRANSFER_DESCRIPTION} Saved preference and requirements: ${startupTransferSummary(state)}.`,
1425
+ currentValue: state.automaticTransfer ? "On" : "Off",
1426
+ values: ["On", "Off"],
1427
+ action: "automatic-transfer"
1428
+ },
1429
+ {
1430
+ id: "agentMode",
1431
+ label: "Autonomous sync",
1432
+ description: AGENT_MODE_DESCRIPTION,
1433
+ currentValue: state.agentMode ? "On" : "Off",
1434
+ values: ["On", "Off"],
1435
+ action: "agent-mode"
1436
+ },
1437
+ {
1438
+ id: "continuous",
1439
+ label: "Continuous sync",
1440
+ description: `${CONTINUOUS_DESCRIPTION}${state.continuous && !state.agentMode ? " Saved On, but paused until Autonomous sync is enabled." : ""}`,
1441
+ currentValue: state.continuous ? "On" : "Off",
1442
+ values: ["On", "Off"],
1443
+ action: "continuous"
1444
+ },
1445
+ {
1446
+ id: "onSwitch",
1447
+ label: "On setup switch",
1448
+ description: "All setups on this device: ask before a pull review, open it automatically, or switch without pulling. Applies to subsequent switches.",
1449
+ currentValue: setupSwitchActionLabel(state.onSwitch),
1450
+ values: SETUP_SWITCH_ACTION_OPTIONS.map(({ label }) => label),
1451
+ action: "on-switch"
1452
+ },
1453
+ {
1454
+ id: "mergeSettings",
1455
+ label: "Merge settings fields",
1456
+ description: "This setup, opt-in: merge independent global settings.json root fields with a verified private ancestor. Arrays and nested objects remain atomic. Applies to subsequent sync; no reload.",
1457
+ currentValue: state.mergeSettings ? "On" : "Off",
1458
+ values: ["On", "Off"],
1459
+ action: "merge-settings"
1460
+ },
1461
+ {
1462
+ id: "contentPolicy",
1463
+ label: "Content merge / partial progress",
1464
+ description: "This setup, opt-in: review the version-5 upgrade before saving. Merge bounded text and prefix-only sessions; partial progress keeps withheld versions and baselines. Applies to subsequent sync; disabling does not clear recovery evidence.",
1465
+ currentValue: state.mergeContent ? state.partialSync ? "Merge + partial" : "Merge only" : state.partialSync ? "Partial only" : "Off",
1466
+ values: ["Off", "Merge only", "Merge + partial", "Partial only"],
1467
+ action: "content-policy"
1468
+ },
1469
+ {
1470
+ id: "skipSecretScan",
1471
+ label: "Skip secret scan",
1472
+ description: "All setups on this device: skip possible-secret checks on subsequent pushes, including automatic pushes. Other safety checks remain. Diagnostics still scans.",
1473
+ currentValue: state.skipSecretScan ? "On" : "Off",
1474
+ values: ["On", "Off"],
1475
+ action: "skip-secret-scan"
1476
+ },
1477
+ {
1478
+ id: "showStatus",
1479
+ label: "Show sync status",
1480
+ description: "All setups on this device: saved and applied immediately to Pi status. Review widgets and notifications remain available.",
1481
+ currentValue: state.showStatus ? "On" : "Off",
1482
+ values: ["On", "Off"],
1483
+ action: "show-status"
1484
+ },
1485
+ {
1486
+ id: "debug",
1487
+ label: "Debug startup timings",
1488
+ description: "All setups on this device: show startup durations in the TUI transcript or RPC notifications, including initial Continuous sync. Applies next session start; no credentials or file contents.",
1489
+ currentValue: state.debug ? "On" : "Off",
1490
+ values: ["On", "Off"],
1491
+ action: "debug"
1492
+ }
1493
+ ]
1494
+ })
1525
1495
  },
1526
1496
  actions: {
1527
1497
  "storage-location": async ({ signal: actionSignal }) => {
@@ -1548,7 +1518,7 @@ async function showSyncSettings(ctx, runRoute, signal, reviewedSetup) {
1548
1518
  const mergeContent = value === "Merge only" || value === "Merge + partial";
1549
1519
  const partialSync = value === "Partial only" || value === "Merge + partial";
1550
1520
  if (!await ctx.ui.confirm(
1551
- "Save experimental content policy?",
1521
+ "Save content policy?",
1552
1522
  "This explicitly upgrades settings to version 5; partial snapshots use version 3 and older clients must refuse them. Text/session merge is conservative. Partial sync preserves withheld versions and old baselines. Disabling does not clear unresolved groups or recovery evidence. Review a directional migration first if portable policy changes.",
1553
1523
  { signal: mutationSignal }
1554
1524
  ))
@@ -1676,7 +1646,7 @@ async function showSyncSettings(ctx, runRoute, signal, reviewedSetup) {
1676
1646
  try {
1677
1647
  validate();
1678
1648
  ctx.ui.notify(
1679
- "Agent mode saved. Applies to subsequent sync and the next session start; no transfer started.",
1649
+ "Autonomous sync saved. Applies to subsequent sync and the next session start; no transfer started.",
1680
1650
  "info"
1681
1651
  );
1682
1652
  } catch {
@@ -1804,7 +1774,7 @@ async function showSyncSettings(ctx, runRoute, signal, reviewedSetup) {
1804
1774
  },
1805
1775
  "remote-include": async ({ signal: actionSignal }) => {
1806
1776
  const reviewSignal = signal ? AbortSignal.any([signal, actionSignal]) : actionSignal;
1807
- const { showRemoteSelectionReview } = await import("./remote-selection-ui-TD4C4W3J.ts");
1777
+ const { showRemoteSelectionReview } = await import("./remote-selection-ui-MYM2YCPF.ts");
1808
1778
  if (reviewSignal.aborted) return { kind: "rejected" };
1809
1779
  const review = await showRemoteSelectionReview(ctx, setupName, reviewSignal, void 0, {
1810
1780
  origin: "settings",
@@ -1909,7 +1879,7 @@ async function showSyncManager(ctx, runRoute, sessionSignal, options = {}) {
1909
1879
  if (!attention) {
1910
1880
  const observation = state.manager.observation;
1911
1881
  if (!observation) return { kind: "stay" };
1912
- const { showRemoteSelectionReview } = await import("./remote-selection-ui-TD4C4W3J.ts");
1882
+ const { showRemoteSelectionReview } = await import("./remote-selection-ui-MYM2YCPF.ts");
1913
1883
  if (sessionSignal?.aborted) return { kind: "close" };
1914
1884
  const config = await loadConfig();
1915
1885
  if (sessionSignal?.aborted) return { kind: "close" };
@@ -2188,4 +2158,4 @@ function syncMainMenuItem(label) {
2188
2158
  export {
2189
2159
  showSyncManager
2190
2160
  };
2191
- //# sourceMappingURL=manager-ui-LM7DSJ2Y.ts.map
2161
+ //# sourceMappingURL=manager-ui-FMZXKPX2.ts.map