dsh-config-manager 0.1.71 → 0.1.73

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 (596) hide show
  1. package/README.md +149 -98
  2. package/README.zh-CN.md +245 -88
  3. package/lib/adapters/agent-instructions.js +1 -1
  4. package/lib/adapters/file-collection.js +1 -1
  5. package/lib/adapters/index.d.ts +2 -1
  6. package/lib/adapters/index.js +6 -1
  7. package/lib/adapters/link-report.d.ts +1 -0
  8. package/lib/adapters/link-report.js +27 -3
  9. package/lib/adapters/messages.d.ts +21 -0
  10. package/lib/adapters/messages.js +57 -0
  11. package/lib/adapters/plugin-data.d.ts +114 -0
  12. package/lib/adapters/plugin-data.js +309 -0
  13. package/lib/adapters/plugin-files.js +3 -2
  14. package/lib/adapters/plugins.js +4 -3
  15. package/lib/adapters/prompts.d.ts +1 -0
  16. package/lib/adapters/prompts.js +7 -1
  17. package/lib/adapters/self.d.ts +8 -2
  18. package/lib/adapters/self.js +3 -2
  19. package/lib/adapters/sessions.d.ts +1 -0
  20. package/lib/adapters/sessions.js +4 -2
  21. package/lib/adapters/test-helpers.d.ts +9 -0
  22. package/lib/adapters/test-helpers.js +14 -0
  23. package/lib/adapters/ui.d.ts +2 -2
  24. package/lib/adapters/ui.js +25 -25
  25. package/lib/adapters/workspaces.d.ts +1 -0
  26. package/lib/adapters/workspaces.js +7 -3
  27. package/lib/cli/actions.d.ts +9 -1
  28. package/lib/cli/actions.js +5 -2
  29. package/lib/cli/help.js +23 -10
  30. package/lib/cli/index.d.ts +23 -0
  31. package/lib/cli/index.js +90 -32
  32. package/lib/cli/sessions-inspect.js +3 -1
  33. package/lib/cli/sessions-repair.js +25 -6
  34. package/lib/cli/web/page.d.ts +12 -0
  35. package/lib/cli/web/page.js +21 -12
  36. package/lib/cli/web/routes.js +2 -2
  37. package/lib/cli/web/server.js +4 -4
  38. package/lib/client.d.ts +1442 -494
  39. package/lib/client.js +15326 -8520
  40. package/lib/core/analyzer.d.ts +11 -2
  41. package/lib/core/analyzer.js +31 -8
  42. package/lib/core/backup-plan.d.ts +10 -0
  43. package/lib/core/backup-plan.js +51 -20
  44. package/lib/core/backup-verify.js +24 -23
  45. package/lib/core/backup.d.ts +25 -1
  46. package/lib/core/backup.js +99 -28
  47. package/lib/core/boot-rescue.js +4 -3
  48. package/lib/core/boot-safety.js +2 -1
  49. package/lib/core/command-rollback.d.ts +182 -0
  50. package/lib/core/command-rollback.js +293 -0
  51. package/lib/core/consult-source.js +7 -6
  52. package/lib/core/disk-usage.d.ts +74 -10
  53. package/lib/core/disk-usage.js +67 -4
  54. package/lib/core/engine-locale.d.ts +87 -0
  55. package/lib/core/engine-locale.js +125 -0
  56. package/lib/core/exporter.js +3 -3
  57. package/lib/core/fork-reconcile.d.ts +128 -0
  58. package/lib/core/fork-reconcile.js +150 -0
  59. package/lib/core/journal.js +6 -5
  60. package/lib/core/local-plugin-host.js +3 -2
  61. package/lib/core/local-plugin-pack.js +11 -6
  62. package/lib/core/messages-core.d.ts +294 -0
  63. package/lib/core/messages-core.js +619 -0
  64. package/lib/core/messages.d.ts +61 -2
  65. package/lib/core/messages.js +118 -13
  66. package/lib/core/migration-consult.js +21 -20
  67. package/lib/core/migration-history.js +19 -5
  68. package/lib/core/model-tools.d.ts +0 -22
  69. package/lib/core/model-tools.js +50 -27
  70. package/lib/core/phase3-host.js +30 -5
  71. package/lib/core/plugin-cli.js +18 -19
  72. package/lib/core/plugin-data-registry.d.ts +124 -0
  73. package/lib/core/plugin-data-registry.js +198 -0
  74. package/lib/core/reconcile.d.ts +2 -14
  75. package/lib/core/reconcile.js +87 -17
  76. package/lib/core/recovery-orchestrator.js +19 -18
  77. package/lib/core/reinstall.d.ts +4 -0
  78. package/lib/core/reinstall.js +26 -21
  79. package/lib/core/restore.js +20 -17
  80. package/lib/core/rollback-gate.d.ts +33 -0
  81. package/lib/core/rollback-gate.js +57 -0
  82. package/lib/core/rollback-ignore-rules.d.ts +31 -0
  83. package/lib/core/rollback-ignore-rules.js +140 -0
  84. package/lib/core/rollback-ledger.d.ts +248 -0
  85. package/lib/core/rollback-ledger.js +1282 -0
  86. package/lib/core/rollback-point.d.ts +1391 -0
  87. package/lib/core/rollback-point.js +3503 -0
  88. package/lib/core/rollback.js +6 -4
  89. package/lib/core/run-registry.js +6 -5
  90. package/lib/core/session-health.d.ts +15 -0
  91. package/lib/core/session-meta.d.ts +42 -2
  92. package/lib/core/session-meta.js +140 -1
  93. package/lib/core/session-title.d.ts +28 -0
  94. package/lib/core/session-title.js +185 -0
  95. package/lib/core/startup-barrier.d.ts +24 -0
  96. package/lib/core/startup-barrier.js +22 -0
  97. package/lib/core/transaction-coordinator.js +4 -3
  98. package/lib/core/types.d.ts +37 -1
  99. package/lib/core/validator.js +5 -4
  100. package/lib/core/verify-recovery.js +31 -30
  101. package/lib/foreign/bundle.js +3 -2
  102. package/lib/foreign/continue.js +2 -1
  103. package/lib/foreign/crush.js +2 -1
  104. package/lib/foreign/gemini.js +2 -1
  105. package/lib/foreign/goose.js +2 -1
  106. package/lib/foreign/kilocode.js +2 -1
  107. package/lib/foreign/kimi.js +2 -1
  108. package/lib/foreign/messages.d.ts +15 -0
  109. package/lib/foreign/messages.js +40 -0
  110. package/lib/foreign/mimocode.js +2 -1
  111. package/lib/foreign/openclaw.js +2 -1
  112. package/lib/foreign/opencode.js +2 -1
  113. package/lib/foreign/pi.js +2 -1
  114. package/lib/foreign/qoder.js +2 -1
  115. package/lib/foreign/qwen.js +2 -1
  116. package/lib/foreign/registry.d.ts +1 -1
  117. package/lib/foreign/registry.js +8 -7
  118. package/lib/foreign/teleagent.js +2 -1
  119. package/lib/foreign/workbuddy.js +2 -1
  120. package/lib/foreign/zcode.js +2 -1
  121. package/lib/foreign/zed.js +2 -1
  122. package/lib/index.d.ts +227 -7
  123. package/lib/index.js +799 -54
  124. package/lib/market/git-file-writer.js +20 -19
  125. package/lib/market/github-repos.js +35 -19
  126. package/lib/market/index-parser.js +31 -30
  127. package/lib/market/messages-market.d.ts +138 -0
  128. package/lib/market/messages-market.js +305 -0
  129. package/lib/market/my-repo.d.ts +2 -2
  130. package/lib/market/my-repo.js +32 -29
  131. package/lib/market/prepare.js +18 -15
  132. package/lib/market/security.js +20 -19
  133. package/lib/market/types.js +2 -1
  134. package/lib/market/url.js +2 -1
  135. package/lib/migrations/index.js +6 -5
  136. package/lib/migrations/messages-migrations.d.ts +32 -0
  137. package/lib/migrations/messages-migrations.js +58 -0
  138. package/lib/profiles/dsh-profile-launcher.js +2 -1
  139. package/lib/profiles/dsh-profile-runtime.js +2 -1
  140. package/lib/profiles/messages.d.ts +7 -0
  141. package/lib/profiles/messages.js +27 -0
  142. package/lib/routes/backup.js +18 -2
  143. package/lib/routes/import.js +3 -3
  144. package/lib/routes/index.d.ts +1 -1
  145. package/lib/routes/kit.d.ts +3 -2
  146. package/lib/routes/kit.js +6 -1
  147. package/lib/routes/market.js +1 -1
  148. package/lib/routes/messages.d.ts +43 -0
  149. package/lib/routes/messages.js +102 -0
  150. package/lib/routes/prefs.js +26 -3
  151. package/lib/routes/profiles.js +12 -6
  152. package/lib/routes/recovery.d.ts +21 -0
  153. package/lib/routes/recovery.js +478 -94
  154. package/lib/routes/snapshots.js +51 -4
  155. package/lib/routes/sync.js +79 -17
  156. package/lib/schema/config.d.ts +11 -1
  157. package/lib/schema/config.js +52 -20
  158. package/lib/schema/index.d.ts +8 -6
  159. package/lib/schema/index.js +8 -6
  160. package/lib/schema/manifest.js +19 -18
  161. package/lib/schema/messages.d.ts +47 -0
  162. package/lib/schema/messages.js +110 -0
  163. package/lib/schema/section-registry.d.ts +42 -15
  164. package/lib/schema/section-registry.js +67 -32
  165. package/lib/schema/types.d.ts +1 -1
  166. package/lib/schema/versions.js +6 -5
  167. package/lib/security/encryption.js +16 -15
  168. package/lib/security/integrity.js +8 -7
  169. package/lib/security/messages.d.ts +30 -0
  170. package/lib/security/messages.js +77 -0
  171. package/lib/security/redaction.js +12 -0
  172. package/lib/security/secret-scanner.js +16 -13
  173. package/lib/security/vault.js +2 -1
  174. package/lib/security/zip-security.js +4 -3
  175. package/lib/sync/ancestor.js +2 -1
  176. package/lib/sync/autosync-config.d.ts +11 -0
  177. package/lib/sync/autosync-config.js +12 -0
  178. package/lib/sync/autosync-scheduler.d.ts +11 -1
  179. package/lib/sync/autosync-scheduler.js +115 -76
  180. package/lib/sync/backup-files.js +3 -2
  181. package/lib/sync/backup-scheduler.js +6 -5
  182. package/lib/sync/blob-store.js +2 -1
  183. package/lib/sync/git/git-transport.d.ts +55 -0
  184. package/lib/sync/git/git-transport.js +152 -2
  185. package/lib/sync/github-auth.js +10 -9
  186. package/lib/sync/layout.js +13 -12
  187. package/lib/sync/messages.d.ts +63 -0
  188. package/lib/sync/messages.js +149 -0
  189. package/lib/sync/review-queue.js +6 -5
  190. package/lib/sync/s3/messages.d.ts +7 -0
  191. package/lib/sync/s3/messages.js +16 -0
  192. package/lib/sync/s3/s3-providers.d.ts +4 -1
  193. package/lib/sync/s3/s3-providers.js +5 -5
  194. package/lib/sync/s3/s3-transport.js +1 -1
  195. package/lib/sync/s3/sigv4.js +2 -1
  196. package/lib/sync/snapshot-crypto.js +6 -5
  197. package/lib/sync/snapshot-json.js +3 -2
  198. package/lib/sync/sync-engine.d.ts +58 -22
  199. package/lib/sync/sync-engine.js +119 -48
  200. package/lib/sync/sync-history.js +7 -6
  201. package/lib/sync/sync-selection.d.ts +15 -4
  202. package/lib/sync/sync-selection.js +17 -5
  203. package/lib/sync/ui-prefs.d.ts +22 -0
  204. package/lib/sync/ui-prefs.js +28 -0
  205. package/lib/sync/webdav/webdav-transport.d.ts +1 -0
  206. package/lib/sync/webdav/webdav-transport.js +4 -1
  207. package/lib/ui/artifact-view.js +4 -3
  208. package/lib/ui/commands.d.ts +1 -1
  209. package/lib/ui/commands.js +10 -0
  210. package/lib/ui/diff-view.d.ts +10 -0
  211. package/lib/ui/diff-view.js +17 -0
  212. package/lib/ui/disk-usage-view.d.ts +33 -4
  213. package/lib/ui/disk-usage-view.js +29 -1
  214. package/lib/ui/errors.d.ts +1 -1
  215. package/lib/ui/errors.js +4 -3
  216. package/lib/ui/export-flow.js +26 -20
  217. package/lib/ui/foreign-view.d.ts +5 -1
  218. package/lib/ui/foreign-view.js +26 -2
  219. package/lib/ui/i18n.d.ts +68 -1
  220. package/lib/ui/i18n.js +120 -2
  221. package/lib/ui/import-wizard.d.ts +7 -0
  222. package/lib/ui/import-wizard.js +13 -10
  223. package/lib/ui/progress.d.ts +2 -2
  224. package/lib/ui/progress.js +1 -2
  225. package/lib/ui/report.d.ts +5 -5
  226. package/lib/ui/report.js +6 -6
  227. package/lib/ui/rollback-view.d.ts +815 -0
  228. package/lib/ui/rollback-view.js +738 -0
  229. package/lib/ui/selection-model.d.ts +41 -0
  230. package/lib/ui/selection-model.js +30 -0
  231. package/lib/ui/session-inventory-view.d.ts +97 -3
  232. package/lib/ui/session-inventory-view.js +76 -2
  233. package/lib/ui/session-issue-labels.d.ts +43 -0
  234. package/lib/ui/session-issue-labels.js +48 -0
  235. package/lib/ui/sync-settings-view.d.ts +33 -0
  236. package/lib/ui/sync-settings-view.js +40 -0
  237. package/lib/ui/test-helpers.js +2 -1
  238. package/lib/ui/types.d.ts +8 -3
  239. package/lib/ui/types.js +1 -1
  240. package/lib/utils/atomic-write.js +6 -5
  241. package/lib/utils/bundle-scan.d.ts +11 -1
  242. package/lib/utils/bundle-scan.js +12 -1
  243. package/lib/utils/env-lock.d.ts +10 -0
  244. package/lib/utils/env-lock.js +73 -46
  245. package/lib/utils/json.js +6 -5
  246. package/lib/utils/messages-utils.d.ts +96 -0
  247. package/lib/utils/messages-utils.js +216 -0
  248. package/lib/utils/proxy.js +18 -5
  249. package/lib/utils/recursive-walk.d.ts +22 -0
  250. package/lib/utils/recursive-walk.js +75 -1
  251. package/lib/utils/session-log-repair.js +10 -9
  252. package/lib/utils/zip.js +27 -26
  253. package/package.json +12 -2
  254. package/src/adapters/agent-instructions.ts +1 -1
  255. package/src/adapters/file-collection.test.ts +1 -0
  256. package/src/adapters/file-collection.ts +1 -1
  257. package/src/adapters/files.test.ts +27 -0
  258. package/src/adapters/index.ts +6 -1
  259. package/src/adapters/link-report.test.ts +22 -2
  260. package/src/adapters/link-report.ts +29 -4
  261. package/src/adapters/messages.ts +61 -0
  262. package/src/adapters/plugin-data.test.ts +225 -0
  263. package/src/adapters/plugin-data.ts +351 -0
  264. package/src/adapters/plugin-files.ts +3 -2
  265. package/src/adapters/plugins.ts +4 -3
  266. package/src/adapters/prompts.ts +7 -1
  267. package/src/adapters/self.test.ts +26 -0
  268. package/src/adapters/self.ts +10 -3
  269. package/src/adapters/sessions.ts +4 -2
  270. package/src/adapters/settings.test.ts +38 -1
  271. package/src/adapters/test-helpers.ts +15 -0
  272. package/src/adapters/ui.test.ts +2 -2
  273. package/src/adapters/ui.ts +27 -26
  274. package/src/adapters/workspaces.ts +7 -3
  275. package/src/cli/actions.test.ts +28 -0
  276. package/src/cli/actions.ts +11 -2
  277. package/src/cli/help.ts +23 -10
  278. package/src/cli/index-guards.test.ts +193 -0
  279. package/src/cli/index.ts +106 -31
  280. package/src/cli/sessions-inspect.test.ts +15 -1
  281. package/src/cli/sessions-inspect.ts +3 -1
  282. package/src/cli/sessions-repair.test.ts +84 -0
  283. package/src/cli/sessions-repair.ts +33 -7
  284. package/src/cli/web/console-route-parity.test.ts +115 -0
  285. package/src/cli/web/page.ts +23 -12
  286. package/src/cli/web/routes.ts +2 -1
  287. package/src/cli/web/server.ts +4 -4
  288. package/src/cli/web/web.test.ts +2 -2
  289. package/src/client/ConfigManagerSection.tsx +30 -2
  290. package/src/client/about/AboutPanel.tsx +2 -2
  291. package/src/client/about/PluginUpdateDialog.tsx +1 -1
  292. package/src/client/about/ReleaseNotesDialog.tsx +2 -2
  293. package/src/client/about/about-view.test.ts +13 -3
  294. package/src/client/about/about-view.ts +10 -6
  295. package/src/client/about/release-notes-view.test.ts +14 -4
  296. package/src/client/about/release-notes-view.ts +4 -2
  297. package/src/client/api.ts +18 -6
  298. package/src/client/chat/ChatEntryView.tsx +411 -0
  299. package/src/client/chat/RollbackDiffTab.tsx +108 -0
  300. package/src/client/chat/RollbackFileIcon.tsx +96 -0
  301. package/src/client/chat/RollbackReviewDialog.tsx +607 -0
  302. package/src/client/chat/chat-entry-view.test.ts +1174 -0
  303. package/src/client/chat/chat-entry-view.ts +758 -0
  304. package/src/client/chat/chat-locales.ts +152 -0
  305. package/src/client/chat/chat-node-registration.ts +64 -0
  306. package/src/client/chat/chat-point-window.ts +183 -0
  307. package/src/client/chat/chat-slots.ts +107 -0
  308. package/src/client/chat/rollback-diff-tab.test.ts +105 -0
  309. package/src/client/chat/rollback-diff-tab.ts +174 -0
  310. package/src/client/chat/rollback-entry-view.test.ts +1469 -0
  311. package/src/client/chat/rollback-entry-view.ts +946 -0
  312. package/src/client/chat/sidebar-slots.ts +59 -0
  313. package/src/client/common/ConfirmDialog.tsx +7 -3
  314. package/src/client/common/ContentPicker.tsx +48 -10
  315. package/src/client/common/DiffTable.tsx +133 -0
  316. package/src/client/common/ErrorBanner.tsx +4 -4
  317. package/src/client/common/Icon.tsx +2 -0
  318. package/src/client/common/Modal.tsx +8 -1
  319. package/src/client/common/ProgressBar.tsx +8 -2
  320. package/src/client/common/ReportView.tsx +4 -4
  321. package/src/client/common/RunsCenter.tsx +1 -0
  322. package/src/client/common/client-route-parity.test.ts +84 -0
  323. package/src/client/common/info-hint-guard.test.ts +46 -13
  324. package/src/client/common/picker-lazy-units.test.ts +42 -0
  325. package/src/client/common/plan-text-redaction.test.ts +17 -6
  326. package/src/client/common/progress-view-edge.test.ts +8 -7
  327. package/src/client/common/progress-view.test.ts +9 -9
  328. package/src/client/common/progress-view.ts +2 -2
  329. package/src/client/common/routes.ts +38 -0
  330. package/src/client/common/section-labels.test.ts +1 -0
  331. package/src/client/common/section-labels.ts +2 -0
  332. package/src/client/common/ui.tsx +73 -10
  333. package/src/client/config-manager.module.css +1109 -31
  334. package/src/client/css-scale-guard.test.ts +30 -0
  335. package/src/client/environment/EnvironmentPanel.tsx +11 -4
  336. package/src/client/environment/maintenance/DiskUsageCard.tsx +23 -2
  337. package/src/client/export/ExportView.tsx +13 -8
  338. package/src/client/history/HistoryPanel.tsx +4 -3
  339. package/src/client/history/history-api.ts +2 -2
  340. package/src/client/history/history-locales.ts +5 -1
  341. package/src/client/home/HomePanel.tsx +29 -8
  342. package/src/client/import/ForeignImportView.tsx +4 -5
  343. package/src/client/import/ImportWizardView.tsx +5 -3
  344. package/src/client/import/import-wizard-split.test.ts +3 -1
  345. package/src/client/import/import-wizard-steps.tsx +9 -9
  346. package/src/client/index.ts +232 -3
  347. package/src/client/library/LibraryActions.tsx +32 -7
  348. package/src/client/library/LibraryPanel.tsx +23 -3
  349. package/src/client/library/RestorePlanView.tsx +9 -66
  350. package/src/client/locales.ts +62 -9
  351. package/src/client/lucide-icons.d.ts +1 -0
  352. package/src/client/market/MarketPanel.tsx +13 -2
  353. package/src/client/market/MyConfigsView.tsx +5 -4
  354. package/src/client/market/MyConfigsWizard.tsx +10 -8
  355. package/src/client/market/market-api.test.ts +9 -8
  356. package/src/client/market/market-api.ts +2 -2
  357. package/src/client/market/market-locales.ts +3 -0
  358. package/src/client/market/market-view.test.ts +6 -6
  359. package/src/client/market/market-view.ts +3 -3
  360. package/src/client/market/my-configs-api.ts +2 -2
  361. package/src/client/market/my-configs-view.test.ts +23 -22
  362. package/src/client/market/my-configs-view.ts +8 -8
  363. package/src/client/recovery/IncompleteCopiesSection.tsx +2 -1
  364. package/src/client/recovery/RecoveryPanel.tsx +442 -283
  365. package/src/client/recovery/RollbackCard.tsx +859 -0
  366. package/src/client/recovery/RollbackDiffPane.tsx +69 -0
  367. package/src/client/recovery/RollbackFileChanges.tsx +163 -0
  368. package/src/client/recovery/incident-api.ts +2 -2
  369. package/src/client/recovery/recovery-api.ts +144 -6
  370. package/src/client/recovery/recovery-locales.test.ts +299 -0
  371. package/src/client/recovery/recovery-locales.ts +520 -149
  372. package/src/client/recovery/recovery-panel-layout.test.ts +132 -2
  373. package/src/client/recovery/rollback-enabled.ts +41 -0
  374. package/src/client/recovery/rollback-file-changes.test.ts +114 -0
  375. package/src/client/recovery/session-dialog-mount.test.ts +54 -0
  376. package/src/client/run-store.ts +84 -21
  377. package/src/client/sync/AutosyncCard.tsx +25 -1
  378. package/src/client/sync/ChannelClearConfirmDialog.tsx +6 -3
  379. package/src/client/sync/ChannelConfigDialog.tsx +10 -10
  380. package/src/client/sync/DecryptPasswordCard.tsx +2 -2
  381. package/src/client/sync/SecurityOptionsCard.tsx +27 -17
  382. package/src/client/sync/SyncChannelEntryCard.tsx +14 -2
  383. package/src/client/sync/SyncConfirmView.tsx +46 -8
  384. package/src/client/sync/SyncLogList.tsx +1 -1
  385. package/src/client/sync/SyncPanel.tsx +31 -23
  386. package/src/client/sync/SyncRepositoryPicker.tsx +3 -5
  387. package/src/client/sync/SyncSectionPickerDialog.tsx +11 -2
  388. package/src/client/sync/SyncSettingsView.test.ts +20 -1
  389. package/src/client/sync/UnreadableSnapshotsBanner.tsx +1 -1
  390. package/src/client/sync/WorkDirCard.tsx +112 -0
  391. package/src/client/sync/history-model.test.ts +42 -9
  392. package/src/client/sync/history-model.ts +30 -15
  393. package/src/client/sync/sync-api.test.ts +57 -33
  394. package/src/client/sync/sync-api.ts +80 -6
  395. package/src/client/sync/sync-locales.ts +104 -3
  396. package/src/client/sync/sync-view-v2.test.ts +65 -13
  397. package/src/client/sync/sync-view.test.ts +107 -52
  398. package/src/client/sync/sync-view.ts +124 -41
  399. package/src/core/analyzer.ts +31 -9
  400. package/src/core/backup-plan.test.ts +48 -5
  401. package/src/core/backup-plan.ts +51 -20
  402. package/src/core/backup-verify.ts +24 -23
  403. package/src/core/backup.test.ts +76 -0
  404. package/src/core/backup.ts +105 -29
  405. package/src/core/boot-rescue.ts +4 -3
  406. package/src/core/boot-safety.ts +2 -1
  407. package/src/core/command-rollback.test.ts +536 -0
  408. package/src/core/command-rollback.ts +406 -0
  409. package/src/core/consult-source.ts +7 -6
  410. package/src/core/disk-usage.test.ts +257 -1
  411. package/src/core/disk-usage.ts +134 -14
  412. package/src/core/engine-locale.test.ts +593 -0
  413. package/src/core/engine-locale.ts +175 -0
  414. package/src/core/exporter.ts +3 -3
  415. package/src/core/fork-reconcile.test.ts +279 -0
  416. package/src/core/fork-reconcile.ts +234 -0
  417. package/src/core/journal.ts +6 -5
  418. package/src/core/local-plugin-host.ts +3 -2
  419. package/src/core/local-plugin-pack.ts +11 -6
  420. package/src/core/messages-core.ts +661 -0
  421. package/src/core/messages.ts +125 -17
  422. package/src/core/migration-consult.ts +21 -20
  423. package/src/core/migration-history.ts +19 -5
  424. package/src/core/model-tools.ts +28 -27
  425. package/src/core/phase3-host.ts +21 -5
  426. package/src/core/phase3-p2b-fingerprint.test.ts +22 -0
  427. package/src/core/plugin-cli.ts +18 -19
  428. package/src/core/plugin-data-registry.test.ts +113 -0
  429. package/src/core/plugin-data-registry.ts +261 -0
  430. package/src/core/reconcile.test.ts +117 -0
  431. package/src/core/reconcile.ts +85 -17
  432. package/src/core/recovery-orchestrator.ts +19 -18
  433. package/src/core/reinstall.ts +26 -21
  434. package/src/core/restore.ts +20 -17
  435. package/src/core/rollback-file-diff.test.ts +159 -0
  436. package/src/core/rollback-gate.test.ts +66 -0
  437. package/src/core/rollback-gate.ts +61 -0
  438. package/src/core/rollback-ignore-rules.ts +126 -0
  439. package/src/core/rollback-ledger.test.ts +655 -0
  440. package/src/core/rollback-ledger.ts +1314 -0
  441. package/src/core/rollback-point.test.ts +2853 -0
  442. package/src/core/rollback-point.ts +4340 -0
  443. package/src/core/rollback.ts +5 -3
  444. package/src/core/run-registry.ts +6 -5
  445. package/src/core/session-health.ts +15 -0
  446. package/src/core/session-meta.test.ts +117 -1
  447. package/src/core/session-meta.ts +149 -2
  448. package/src/core/session-title.test.ts +127 -0
  449. package/src/core/session-title.ts +189 -0
  450. package/src/core/startup-barrier.test.ts +69 -0
  451. package/src/core/startup-barrier.ts +27 -0
  452. package/src/core/transaction-coordinator.ts +4 -3
  453. package/src/core/types.ts +37 -1
  454. package/src/core/validator.ts +5 -4
  455. package/src/core/verify-recovery.ts +31 -30
  456. package/src/foreign/bundle.ts +3 -2
  457. package/src/foreign/continue.ts +2 -1
  458. package/src/foreign/crush.ts +2 -1
  459. package/src/foreign/file-budget.test.ts +2 -0
  460. package/src/foreign/gemini.ts +2 -1
  461. package/src/foreign/goose.ts +2 -1
  462. package/src/foreign/kilocode.ts +2 -1
  463. package/src/foreign/kimi.ts +2 -1
  464. package/src/foreign/messages.ts +44 -0
  465. package/src/foreign/mimocode.ts +2 -1
  466. package/src/foreign/openclaw.ts +2 -1
  467. package/src/foreign/opencode.ts +2 -1
  468. package/src/foreign/pi.ts +2 -1
  469. package/src/foreign/qoder.ts +2 -1
  470. package/src/foreign/qwen.ts +2 -1
  471. package/src/foreign/registry.test.ts +1 -1
  472. package/src/foreign/registry.ts +8 -7
  473. package/src/foreign/teleagent.ts +2 -1
  474. package/src/foreign/workbuddy.ts +2 -1
  475. package/src/foreign/zcode.ts +2 -1
  476. package/src/foreign/zed.ts +2 -1
  477. package/src/index.facade.test.ts +340 -1
  478. package/src/index.ts +876 -57
  479. package/src/market/git-file-writer.ts +20 -19
  480. package/src/market/github-repos.test.ts +23 -0
  481. package/src/market/github-repos.ts +37 -19
  482. package/src/market/index-parser.ts +31 -30
  483. package/src/market/messages-market.ts +325 -0
  484. package/src/market/my-repo.ts +32 -29
  485. package/src/market/prepare.ts +18 -15
  486. package/src/market/security.ts +20 -19
  487. package/src/market/types.ts +2 -1
  488. package/src/market/url.ts +2 -1
  489. package/src/migrations/index.ts +6 -5
  490. package/src/migrations/messages-migrations.ts +59 -0
  491. package/src/profiles/dsh-profile-launcher.ts +2 -1
  492. package/src/profiles/dsh-profile-runtime.ts +2 -1
  493. package/src/profiles/messages.ts +31 -0
  494. package/src/routes/backup.ts +18 -2
  495. package/src/routes/import.ts +3 -3
  496. package/src/routes/index.ts +1 -1
  497. package/src/routes/kit.ts +9 -3
  498. package/src/routes/market.ts +1 -1
  499. package/src/routes/messages.ts +106 -0
  500. package/src/routes/prefs.ts +31 -2
  501. package/src/routes/profiles.ts +12 -6
  502. package/src/routes/recovery.test.ts +405 -1
  503. package/src/routes/recovery.ts +477 -94
  504. package/src/routes/snapshots.ts +51 -4
  505. package/src/routes/sync.ts +82 -17
  506. package/src/schema/config.ts +53 -20
  507. package/src/schema/index.ts +7 -5
  508. package/src/schema/manifest-schema.test.ts +4 -4
  509. package/src/schema/manifest.ts +19 -18
  510. package/src/schema/messages.ts +120 -0
  511. package/src/schema/registry.test.ts +28 -7
  512. package/src/schema/section-registry.ts +96 -42
  513. package/src/schema/types.ts +2 -1
  514. package/src/schema/versions.ts +6 -5
  515. package/src/security/encryption.ts +16 -15
  516. package/src/security/integrity.ts +8 -7
  517. package/src/security/messages.ts +87 -0
  518. package/src/security/redaction.test.ts +17 -1
  519. package/src/security/redaction.ts +13 -0
  520. package/src/security/secret-scanner.ts +19 -12
  521. package/src/security/security.test.ts +47 -0
  522. package/src/security/vault.ts +2 -1
  523. package/src/security/zip-security.ts +4 -3
  524. package/src/sync/ancestor.ts +2 -1
  525. package/src/sync/autosync-config.ts +21 -0
  526. package/src/sync/autosync-scheduler.test.ts +63 -7
  527. package/src/sync/autosync-scheduler.ts +118 -78
  528. package/src/sync/backup-files.ts +3 -2
  529. package/src/sync/backup-scheduler.ts +6 -5
  530. package/src/sync/blob-store.ts +2 -1
  531. package/src/sync/git/git-transport.test.ts +170 -8
  532. package/src/sync/git/git-transport.ts +176 -2
  533. package/src/sync/github-auth.ts +10 -9
  534. package/src/sync/layout.ts +13 -12
  535. package/src/sync/messages.ts +153 -0
  536. package/src/sync/review-queue.ts +6 -5
  537. package/src/sync/s3/messages.ts +16 -0
  538. package/src/sync/s3/s3-providers.ts +9 -6
  539. package/src/sync/s3/s3-transport.ts +1 -1
  540. package/src/sync/s3/sigv4.ts +3 -1
  541. package/src/sync/snapshot-crypto.ts +6 -5
  542. package/src/sync/snapshot-json.ts +3 -2
  543. package/src/sync/sync-credentials.test.ts +119 -0
  544. package/src/sync/sync-engine-download-tombstone.test.ts +1 -1
  545. package/src/sync/sync-engine.test.ts +226 -8
  546. package/src/sync/sync-engine.ts +154 -52
  547. package/src/sync/sync-history.ts +7 -6
  548. package/src/sync/sync-selection.test.ts +12 -2
  549. package/src/sync/sync-selection.ts +18 -5
  550. package/src/sync/transport.test.ts +1 -0
  551. package/src/sync/ui-prefs.test.ts +44 -1
  552. package/src/sync/ui-prefs.ts +39 -0
  553. package/src/sync/webdav/webdav-transport.ts +4 -1
  554. package/src/ui/artifact-view.ts +4 -3
  555. package/src/ui/commands.test.ts +1 -0
  556. package/src/ui/commands.ts +11 -1
  557. package/src/ui/diff-view.test.ts +9 -1
  558. package/src/ui/diff-view.ts +22 -0
  559. package/src/ui/disk-usage-view.test.ts +113 -6
  560. package/src/ui/disk-usage-view.ts +63 -7
  561. package/src/ui/errors.ts +4 -3
  562. package/src/ui/export-flow.ts +26 -20
  563. package/src/ui/foreign-view.test.ts +43 -0
  564. package/src/ui/foreign-view.ts +30 -3
  565. package/src/ui/i18n.ts +131 -2
  566. package/src/ui/import-wizard.ts +18 -10
  567. package/src/ui/progress.ts +2 -2
  568. package/src/ui/report.ts +7 -6
  569. package/src/ui/rollback-view.test.ts +836 -0
  570. package/src/ui/rollback-view.ts +1405 -0
  571. package/src/ui/selection-model.test.ts +33 -1
  572. package/src/ui/selection-model.ts +53 -0
  573. package/src/ui/session-inventory-view.test.ts +109 -0
  574. package/src/ui/session-inventory-view.ts +138 -3
  575. package/src/ui/session-issue-labels.test.ts +51 -0
  576. package/src/ui/session-issue-labels.ts +70 -0
  577. package/src/ui/sync-settings-view.test.ts +36 -0
  578. package/src/ui/sync-settings-view.ts +49 -0
  579. package/src/ui/test-helpers.ts +2 -1
  580. package/src/ui/types.ts +10 -4
  581. package/src/utils/atomic-write.ts +6 -5
  582. package/src/utils/bundle-scan.test.ts +2 -2
  583. package/src/utils/bundle-scan.ts +12 -1
  584. package/src/utils/env-lock.ts +83 -49
  585. package/src/utils/json.ts +7 -5
  586. package/src/utils/messages-utils.ts +232 -0
  587. package/src/utils/proxy.test.ts +25 -0
  588. package/src/utils/proxy.ts +19 -5
  589. package/src/utils/recursive-walk.test.ts +43 -0
  590. package/src/utils/recursive-walk.ts +75 -1
  591. package/src/utils/session-log-repair.ts +10 -9
  592. package/src/utils/zip.ts +27 -26
  593. package/lib/core/checkpoint.d.ts +0 -362
  594. package/lib/core/checkpoint.js +0 -1309
  595. package/src/core/checkpoint.test.ts +0 -665
  596. package/src/core/checkpoint.ts +0 -1614
@@ -44,6 +44,23 @@ export const zh = {
44
44
  'channel.configured': '已配置',
45
45
  'channel.notConfigured': '未配置',
46
46
  'channel.currentUrl': '当前地址',
47
+ // issue #79:Git 工作副本(origin 是否跟随仓库地址 + 显式重建入口)
48
+ 'workdir.title': '工作副本',
49
+ 'workdir.hint': '同步使用的 Git 工作副本。每次同步都会让它的 origin 跟随当前仓库地址;改地址后若仍失败,可在这里重指向或重新克隆。',
50
+ 'workdir.path': '路径',
51
+ 'workdir.origin': 'origin',
52
+ 'workdir.match': '已跟随仓库地址',
53
+ 'workdir.mismatch': '仍指向旧地址',
54
+ 'workdir.missing': '尚未创建(首次同步时克隆)',
55
+ 'workdir.unknown': '读不出工作副本状态',
56
+ 'workdir.relink': '重指向仓库地址',
57
+ 'workdir.reclone': '重新克隆工作副本',
58
+ 'workdir.recloneConfirmTitle': '重新克隆工作副本?',
59
+ 'workdir.recloneConfirmMessage': '将删除本机工作副本目录并从远端重新克隆。本机配置与远端快照都不受影响,但工作副本里尚未推送的本地提交会被丢弃 —— 需要时请先在同步页执行一次推送。',
60
+ 'workdir.recloneConfirm': '重新克隆',
61
+ 'toast.workdirRelinked': '工作副本已重指向当前仓库地址',
62
+ 'toast.workdirRecloned': '工作副本已重新克隆',
63
+ 'toast.workdirResetFailed': '重建工作副本失败',
47
64
  'syncStatus.lastSync': '上次同步',
48
65
  'syncStatus.sections': '可同步分区',
49
66
  'syncStatus.state': '配置状态',
@@ -58,6 +75,14 @@ export const zh = {
58
75
  'webdav.passwordSaved': '凭据已配置',
59
76
  'webdav.passwordPlaceholder': '密码(可选)',
60
77
  'webdav.presetHint': '选择常见 WebDAV 服务器可快速填入地址;含 <占位符> 的模板请替换为你的真实服务器/用户名。',
78
+ // 预设服务器的显示名(英文界面零中文:中文名只住在 zh 目录,en 用品牌英文名)
79
+ 'webdav.preset.custom': 'Custom URL',
80
+ 'webdav.preset.jianguoyun': '坚果云 (Jianguoyun)',
81
+ 'webdav.preset.nextcloud': 'Nextcloud',
82
+ 'webdav.preset.owncloud': 'ownCloud',
83
+ 'webdav.preset.seafile': 'Seafile',
84
+ 'webdav.preset.synology': 'Synology NAS (WebDAV)',
85
+ 'webdav.preset.box': 'Box',
61
86
  // GitHub OAuth 登录(device flow,无需手动输入 token)
62
87
  'github.title': 'GitHub 登录',
63
88
  'github.description': '通过 GitHub OAuth 设备码流程授权:无需手动输入 token,在浏览器中确认授权后,token 自动写入 DSH credentials。',
@@ -146,10 +171,18 @@ export const zh = {
146
171
  'syncflow.rollback': '回滚到应用前',
147
172
  'syncflow.rollingBack': '正在回滚…',
148
173
  'syncflow.rollbackDone': '已回滚到应用前',
174
+ // 诚实性(2026-10):部分回滚绝不报「已回滚」——列出未恢复项与人工提示
175
+ 'syncflow.rollbackPartialToast': '回滚未完成:{n} 项没能恢复',
176
+ 'syncflow.rollbackIncomplete': '回滚未完成:{n} 项无法自动恢复(配置可能停留在中间状态)',
177
+ 'syncflow.rollbackFailedItems': '未回滚项(需人工处理)',
178
+ 'syncflow.importRollbackIncomplete': '导入失败,且整体回滚未完成:有改动没能恢复(见下方告警)',
149
179
  'syncflow.needsRestart': '部分改动需要重启 DSH 后生效',
150
180
  // P0-②:push 前只读预览确认弹窗
151
181
  'syncflow.pushPreviewTitle': '确认推送',
152
182
  'syncflow.pushPreviewSections': '将推送的分区',
183
+ // 推送预览逐行标签(原先硬编码英文 'changed' / 'unchanged',中文界面里是英文枚举)
184
+ 'syncflow.pushChanged': '有改动',
185
+ 'syncflow.pushUnchanged': '无改动',
153
186
  'syncflow.pushConfirm': '确认推送',
154
187
  'syncflow.pushing': '正在推送…',
155
188
  'syncflow.pushFirstBaseline': '远端暂无快照:本次将创建首个同步基线',
@@ -157,11 +190,13 @@ export const zh = {
157
190
  'mode.title': '同步分区',
158
191
  'mode.hint': '点按钮在弹窗里勾选要同步的分区:勾选集合就是同步范围(默认已勾选推荐分区,可随时改)。',
159
192
  'mode.selectedCount': '已勾选 {n} 个分区',
160
- 'mode.sectionsHint': '默认可同步的是可移植分区;设备相关分区(插件文件、凭据状态、历史会话)只有你在这里主动勾选才参与同步。',
193
+ 'mode.sectionsHint': '默认可同步的是可移植分区;平台相关分区(MCP 服务器)与设备相关分区(插件文件、凭据状态、历史会话)只有你在这里主动勾选才参与同步。',
161
194
  'mode.atLeastOne': '请至少勾选一个同步分区',
162
195
  'mode.sectionPortable': '可移植',
163
196
  'mode.sectionRecommended': '推荐',
164
197
  'mode.sectionDeviceSpecific': '设备相关',
198
+ 'mode.sectionPlatformSpecific': '平台相关',
199
+ 'mode.mcpHint': 'MCP 服务器按 patch 行写回(导入时落回原层)。按包安装的 stdio 服务器(npx / uvx / pipx)配置本身可跨机;若 command / args / cwd 里是绝对路径,或目标机没装对应运行时,导入分析会给出提示 —— 配置会照常写入,但服务器在目标机可能起不来。',
165
200
  'mode.sessionsLimit': '同步最近多少个会话',
166
201
  'mode.sessionsLimitHint': '历史会话内容敏感,默认只带最近的 5 个(0 = 只勾选不带会话);单位是一个会话目录,同一会话的全部日志一起走。',
167
202
  'mode.sessionsPick': '选择具体对话',
@@ -170,6 +205,7 @@ export const zh = {
170
205
  'mode.sessionsPickHint': '点名后只同步勾中的对话(优先于上面的数量上限);一个都不勾 = 回到「最近 N 个」模式。',
171
206
  'mode.sessionsPickReset': '改为「最近 N 个」',
172
207
  'mode.sessionsWorkspaceWarn': '已勾选历史对话,但没有勾选「工作区」分区:目标机上这些对话可能归属不到任何工作区而显示不出来。建议一并勾选「工作区」。',
208
+ 'mode.gistSessionsWarn': '当前通道是 GitHub Gist,且勾选了「历史会话」:gist 会一次取回全部文件内容、单文件超限即截断、文件数还有上限,大分区同步可能失败或内容被截断。建议改用 Git / WebDAV / 对象存储通道同步历史会话,或取消勾选该分区。',
173
209
  'mode.persistHint': '分区选择已保存到本机:自动同步和手动推送都会使用此配置(重启后仍生效)。',
174
210
  'mode.choose': '选择同步分区',
175
211
  'mode.pickerTitle': '选择同步分区',
@@ -219,6 +255,10 @@ export const zh = {
219
255
  'autosync.skipped': '已跳过',
220
256
  'autosync.failed': '失败',
221
257
  'autosync.partial': '部分成功',
258
+ // issue #79:跳过原因上状态行(改造前只进 info 级日志,界面完全看不到「为什么没同步」)
259
+ 'autosync.skipReasonLabel': '跳过原因',
260
+ 'autosync.skipReasonConflictCount': '{reason}(远端另有 {n} 个分区待确认,可在同步页手动处理)',
261
+ 'autosync.lastMessage': '本轮消息',
222
262
  // 同步历史(含自动同步记录)
223
263
  'history.title': '同步历史',
224
264
  'history.empty': '尚无同步历史',
@@ -239,6 +279,12 @@ export const zh = {
239
279
  'history.autosyncReasonNoRemote': '无远端快照',
240
280
  'history.autosyncReasonNotConfigured': '未配置仓库',
241
281
  'history.autosyncReasonNetwork': '网络问题',
282
+ // F1 残留补齐(英文界面零中文):这三类此前只有硬编码中文,只住在这里
283
+ 'history.autosyncReasonEncrypted': '远端快照已加密,自动同步跳过(请手动同步)',
284
+ 'history.autosyncReasonMutationLocked': '环境锁被占用(另一项任务进行中,或存在需回收的残留锁)',
285
+ 'history.autosyncReasonUnknown': '未知',
286
+ 'history.autosyncReasonUpToDate': '无变化(本地与远端一致)',
287
+ 'history.autosyncReasonUnchanged': '远端无新快照,无需合并',
242
288
  'history.autosyncConflicted': '跳过冲突分区:{sections}',
243
289
  'history.autosyncApplied': '应用分区:{sections}',
244
290
  'history.autosyncError': '错误:{error}',
@@ -284,6 +330,10 @@ export const zh = {
284
330
  'load.failed': '加载同步状态失败',
285
331
  // 公共
286
332
  'common.close': '关闭',
333
+ // 标点/连接符也属界面文案(英文界面不得出现全角标点):按当前语言取词
334
+ 'common.labelSeparator': ':',
335
+ 'common.parens': '({text})',
336
+ 'common.listSeparator': '、',
287
337
  'common.retry': '重试',
288
338
  'common.loading': '加载中…',
289
339
  'common.infoHint': '查看说明',
@@ -326,6 +376,8 @@ export const zh = {
326
376
  'cloud.secretPlaceholder': '••••••••',
327
377
  'cloud.gistId': 'Gist ID',
328
378
  'cloud.gistIdHint': 'gist 地址末段的十六进制 id(如 https://gist.github.com/<用户>/<id>)。',
379
+ // G-34:gist 刻意不做内容寻址外置(一次 GET 全量、单文件超限截断、文件数上限)→ 大分区不适合
380
+ 'cloud.gistLargeSectionHint': 'gist 通道不做内容外置:一次请求就把全部文件内容取回、单文件超限会被截断,且文件数有上限 —— 历史会话这类大分区不适合走 gist,请改用 Git / WebDAV / 对象存储通道。',
329
381
  'cloud.apiBaseUrl': 'API 根地址(可选)',
330
382
  'cloud.apiBaseUrlHint': '留空 = https://api.github.com;GitHub Enterprise 可改为自建地址。',
331
383
  'cloud.filePrefix': '文件名前缀(可选)',
@@ -387,6 +439,23 @@ export const en: Record<keyof typeof zh, string> = {
387
439
  'channel.configured': 'Configured',
388
440
  'channel.notConfigured': 'Not configured',
389
441
  'channel.currentUrl': 'Current URL',
442
+ // issue #79: Git working copy (origin follows the repository address; explicit rebuild entry)
443
+ 'workdir.title': 'Working copy',
444
+ 'workdir.hint': 'The Git working copy used for sync. Every sync makes its origin follow the configured repository address; if it still fails after an address change, re-point or clone it again here.',
445
+ 'workdir.path': 'Path',
446
+ 'workdir.origin': 'origin',
447
+ 'workdir.match': 'Following the repository address',
448
+ 'workdir.mismatch': 'Still pointing at the old address',
449
+ 'workdir.missing': 'Not created yet (cloned on first sync)',
450
+ 'workdir.unknown': 'Working-copy state unreadable',
451
+ 'workdir.relink': 'Re-point repository address',
452
+ 'workdir.reclone': 'Clone working copy again',
453
+ 'workdir.recloneConfirmTitle': 'Clone the working copy again?',
454
+ 'workdir.recloneConfirmMessage': 'The local working-copy directory will be deleted and cloned again from the remote. Your local config and the remote snapshots are unaffected, but local commits that were never pushed will be lost — push once from the sync page first if you need them.',
455
+ 'workdir.recloneConfirm': 'Clone again',
456
+ 'toast.workdirRelinked': 'Working copy now points at the configured repository address',
457
+ 'toast.workdirRecloned': 'Working copy cloned again',
458
+ 'toast.workdirResetFailed': 'Rebuilding the working copy failed',
390
459
  'syncStatus.lastSync': 'Last sync',
391
460
  'syncStatus.sections': 'Syncable sections',
392
461
  'syncStatus.state': 'State',
@@ -400,6 +469,13 @@ export const en: Record<keyof typeof zh, string> = {
400
469
  'webdav.passwordSaved': 'Credential configured',
401
470
  'webdav.passwordPlaceholder': 'Password (optional)',
402
471
  'webdav.presetHint': 'Pick a common WebDAV server to prefill the URL; templates containing <placeholders> need to be replaced with your real server/username.',
472
+ 'webdav.preset.custom': 'Custom URL',
473
+ 'webdav.preset.jianguoyun': 'Jianguoyun (Nutstore)',
474
+ 'webdav.preset.nextcloud': 'Nextcloud',
475
+ 'webdav.preset.owncloud': 'ownCloud',
476
+ 'webdav.preset.seafile': 'Seafile',
477
+ 'webdav.preset.synology': 'Synology NAS (WebDAV)',
478
+ 'webdav.preset.box': 'Box',
403
479
  'github.title': 'GitHub Sign-in',
404
480
  'github.description': 'Authorize via the GitHub OAuth device flow: no manual token entry — after you approve in the browser, the token is written into DSH credentials automatically.',
405
481
  'github.login': 'Sign in with GitHub',
@@ -419,7 +495,7 @@ export const en: Record<keyof typeof zh, string> = {
419
495
  'repoPicker.empty': 'No private repository available — use "Create a new private repository".',
420
496
  'repoPicker.loadFailed': 'Could not load the repository list — retry, or type the address below.',
421
497
  'repoPicker.updatedAt': 'Updated {time}',
422
- 'repoPicker.create': '+ New private repository…',
498
+ 'repoPicker.create': '+ New private repository…',
423
499
  'repoPicker.createTitle': 'Create a private repository',
424
500
  'repoPicker.name': 'Repository name',
425
501
  'repoPicker.namePlaceholder': 'e.g. dsh-configs',
@@ -483,10 +559,18 @@ export const en: Record<keyof typeof zh, string> = {
483
559
  'syncflow.rollback': 'Rollback',
484
560
  'syncflow.rollingBack': 'Rolling back…',
485
561
  'syncflow.rollbackDone': 'Rolled back',
562
+ // Honesty (2026-10): a partial rollback is never reported as "rolled back"
563
+ 'syncflow.rollbackPartialToast': 'Rollback incomplete: {n} item(s) could not be restored',
564
+ 'syncflow.rollbackIncomplete': 'Rollback incomplete: {n} item(s) could not be restored automatically (the configuration may be left partially changed)',
565
+ 'syncflow.rollbackFailedItems': 'Items not rolled back (need manual handling)',
566
+ 'syncflow.importRollbackIncomplete': 'Import failed and the overall rollback did not complete: some changes could not be restored (see the warnings below)',
486
567
  'syncflow.needsRestart': 'Some changes require a DSH restart to take effect',
487
568
  // P0-②: push read-only preview confirm dialog
488
569
  'syncflow.pushPreviewTitle': 'Confirm Push',
489
570
  'syncflow.pushPreviewSections': 'Sections to push',
571
+ // Per-row labels for the push preview (previously hardcoded English literals)
572
+ 'syncflow.pushChanged': 'Changed',
573
+ 'syncflow.pushUnchanged': 'Unchanged',
490
574
  'syncflow.pushConfirm': 'Push',
491
575
  'syncflow.pushing': 'Pushing…',
492
576
  'syncflow.pushFirstBaseline': 'No remote snapshots yet: this push creates the first sync baseline',
@@ -494,11 +578,13 @@ export const en: Record<keyof typeof zh, string> = {
494
578
  'mode.title': 'Sync Sections',
495
579
  'mode.hint': 'Click the button to tick the sections to sync: the ticked set is the sync scope (recommended sections are ticked by default and can be changed any time).',
496
580
  'mode.selectedCount': '{n} section(s) selected',
497
- 'mode.sectionsHint': 'Portable sections sync by default; device-specific sections (plugin files, credentials status, sessions) only participate when you explicitly tick them here.',
581
+ 'mode.sectionsHint': 'Portable sections sync by default; platform-dependent sections (MCP servers) and device-specific sections (plugin files, credentials status, sessions) only participate when you explicitly tick them here.',
498
582
  'mode.atLeastOne': 'Select at least one section to sync',
499
583
  'mode.sectionPortable': 'Portable',
500
584
  'mode.sectionRecommended': 'Recommended',
501
585
  'mode.sectionDeviceSpecific': 'Device-specific',
586
+ 'mode.sectionPlatformSpecific': 'Platform-dependent',
587
+ 'mode.mcpHint': 'MCP servers are written back as patch lines (restored to their original layer on import). Stdio servers installed from a package (npx / uvx / pipx) are portable by themselves; if command / args / cwd contain absolute paths, or the target machine lacks the runtime, the import analysis will say so — the config is still written, but the server may fail to start there.',
502
588
  'mode.sessionsLimit': 'How many recent sessions to sync',
503
589
  'mode.sessionsLimitHint': 'Session content is sensitive, so only the latest 5 are included by default (0 = select the section but carry no sessions); the unit is a session directory, so all logs of one session travel together.',
504
590
  'mode.sessionsPick': 'Pick specific conversations',
@@ -507,6 +593,7 @@ export const en: Record<keyof typeof zh, string> = {
507
593
  'mode.sessionsPickHint': 'Only the picked conversations are synced (this wins over the count above). Picking none returns to the "latest N" mode.',
508
594
  'mode.sessionsPickReset': 'Use "latest N" instead',
509
595
  'mode.sessionsWorkspaceWarn': 'Conversations are selected but the "Workspaces" section is not: on the target machine they may not be attributed to any workspace and stay invisible. Selecting "Workspaces" too is recommended.',
596
+ 'mode.gistSessionsWarn': 'The current channel is GitHub Gist and "Conversations" is selected: a gist returns all file content in one request, truncates any oversized single file, and caps the number of files, so syncing a large section may fail or be truncated. Use a Git / WebDAV / object-storage channel for conversations, or clear that section.',
510
597
  'mode.persistHint': 'The section selection is saved locally: both auto sync and manual push use this configuration (persists across restarts).',
511
598
  'mode.choose': 'Choose sync sections',
512
599
  'mode.pickerTitle': 'Choose Sync Sections',
@@ -555,6 +642,10 @@ export const en: Record<keyof typeof zh, string> = {
555
642
  'autosync.skipped': 'Skipped',
556
643
  'autosync.failed': 'Failed',
557
644
  'autosync.partial': 'Partial',
645
+ // issue #79: surface the skip reason in the status line (previously info-level log only)
646
+ 'autosync.skipReasonLabel': 'Skip reason',
647
+ 'autosync.skipReasonConflictCount': '{reason} ({n} more section(s) on the remote need confirmation — handle them on the sync page)',
648
+ 'autosync.lastMessage': 'Last message',
558
649
  'history.title': 'Sync History',
559
650
  'history.empty': 'No sync history yet',
560
651
  'history.emptyHint': 'Records appear here after your first push / one-click sync / auto sync.',
@@ -574,6 +665,11 @@ export const en: Record<keyof typeof zh, string> = {
574
665
  'history.autosyncReasonNoRemote': 'No remote snapshot',
575
666
  'history.autosyncReasonNotConfigured': 'No repository configured',
576
667
  'history.autosyncReasonNetwork': 'Network issue',
668
+ 'history.autosyncReasonEncrypted': 'The remote snapshot is encrypted, so auto sync skipped it (sync manually)',
669
+ 'history.autosyncReasonMutationLocked': 'The environment lock is held (another task is running, or a stale lock needs reclaiming)',
670
+ 'history.autosyncReasonUnknown': 'Unknown',
671
+ 'history.autosyncReasonUpToDate': 'No changes (local and remote match)',
672
+ 'history.autosyncReasonUnchanged': 'No new remote snapshot to merge',
577
673
  'history.autosyncConflicted': 'Skipped conflict sections: {sections}',
578
674
  'history.autosyncApplied': 'Applied sections: {sections}',
579
675
  'history.autosyncError': 'Error: {error}',
@@ -616,6 +712,9 @@ export const en: Record<keyof typeof zh, string> = {
616
712
  // Page-level load failure (M-16: inline error state; loadError had no render point before)
617
713
  'load.failed': 'Failed to load sync status',
618
714
  'common.close': 'Close',
715
+ 'common.labelSeparator': ': ',
716
+ 'common.parens': '({text})',
717
+ 'common.listSeparator': ', ',
619
718
  'common.retry': 'Retry',
620
719
  'common.loading': 'Loading…',
621
720
  'common.infoHint': 'Show description',
@@ -658,6 +757,8 @@ export const en: Record<keyof typeof zh, string> = {
658
757
  'cloud.secretPlaceholder': '••••••••',
659
758
  'cloud.gistId': 'Gist ID',
660
759
  'cloud.gistIdHint': 'The hex id at the end of the gist URL (e.g. https://gist.github.com/<user>/<id>).',
760
+ // G-34: gist deliberately has no content-addressed offloading (one full GET, per-file truncation, file cap)
761
+ 'cloud.gistLargeSectionHint': 'The gist channel does no content offloading: a single request returns all file content, any oversized single file is truncated, and the number of files is capped — large sections such as conversations are a poor fit. Use a Git / WebDAV / object-storage channel instead.',
661
762
  'cloud.apiBaseUrl': 'API base URL (optional)',
662
763
  'cloud.apiBaseUrlHint': 'Blank = https://api.github.com; change it for GitHub Enterprise.',
663
764
  'cloud.filePrefix': 'File name prefix (optional)',
@@ -8,9 +8,11 @@ import assert from 'node:assert/strict'
8
8
  import type { ApplyItemsResponse, AutosyncStatusResponse, SyncConfirmItem } from './sync-api.ts'
9
9
  import {
10
10
  applyItemsReportView, autosyncIntervalMs, autosyncStatusText, buildAdoptions, confirmListSummary,
11
- computeAutosyncCountdown, hasBulkDecidable, isBulkDecidable, isReviewItem, isToolchainChangeItem,
11
+ computeAutosyncCountdown, GIST_LARGE_SECTION_HINT_KEY, gistSessionsRiskKey, hasBulkDecidable,
12
+ isBulkDecidable, isReviewItem, isToolchainChangeItem,
12
13
  keepLocalAll, needsGitToken, reviewItems, summarizeConfirmItems, useRemoteAll,
13
14
  } from './sync-view.ts'
15
+ import { zhUiT } from '../../ui/i18n.ts'
14
16
 
15
17
  /* ---------------------------------------------------------------- 一键同步差异确认 */
16
18
 
@@ -163,7 +165,7 @@ test('sync-view: buildAdoptions 收集用户决策;未列出项视为 adopt=fa
163
165
  ['c', true],
164
166
  ])
165
167
  const resolutions = new Map<string, 'useRemote' | 'keepLocal'>([['c', 'useRemote']])
166
- const out = buildAdoptions(items, adopted, resolutions)
168
+ const out = buildAdoptions(items, adopted, resolutions, zhUiT)
167
169
  // 只有 adopt=true 的项进列表(a、c);b 未采纳剔除
168
170
  const ids = out.map((o) => o.itemId)
169
171
  assert.deepEqual(ids, ['a', 'c'])
@@ -176,7 +178,7 @@ test('sync-view: buildAdoptions Conflict 项未给 resolution → 抛错(强
176
178
  ]
177
179
  const adopted = new Map<string, boolean>([['c', true]])
178
180
  const resolutions = new Map<string, 'useRemote' | 'keepLocal'>()
179
- assert.throws(() => buildAdoptions(items, adopted, resolutions), /解决/)
181
+ assert.throws(() => buildAdoptions(items, adopted, resolutions, zhUiT), /解决/)
180
182
  })
181
183
 
182
184
  test('sync-view: applyItemsReportView 成功 → ok 头部含 applied 计数与 restoreId', () => {
@@ -184,7 +186,7 @@ test('sync-view: applyItemsReportView 成功 → ok 头部含 applied 计数与
184
186
  ok: true, applied: ['settings', 'plugins'], skipped: [], needsRestart: false,
185
187
  warnings: [], restoreId: 'rest-1', rolledBack: false, failed: [], result: {},
186
188
  }
187
- const view = applyItemsReportView(report)
189
+ const view = applyItemsReportView(report, zhUiT)
188
190
  assert.notEqual(view, null)
189
191
  assert.equal(view?.kind, 'ok')
190
192
  assert.match(view?.headline ?? '', /2/)
@@ -197,13 +199,13 @@ test('sync-view: applyItemsReportView 失败且整体回滚 → rolledBack 渲
197
199
  warnings: [], restoreId: 'rest-2', rolledBack: true,
198
200
  failed: [{ itemId: 'x', message: '导入失败' }], result: {},
199
201
  }
200
- const view = applyItemsReportView(report)
202
+ const view = applyItemsReportView(report, zhUiT)
201
203
  assert.equal(view?.kind, 'rolledBack')
202
204
  assert.equal(view?.restoreId, 'rest-2')
203
205
  })
204
206
 
205
207
  test('sync-view: applyItemsReportView null → null', () => {
206
- assert.equal(applyItemsReportView(null), null)
208
+ assert.equal(applyItemsReportView(null, zhUiT), null)
207
209
  })
208
210
 
209
211
  /* ---------- issue #56:ok=true 但有未生效项(warning)必须呈现为「部分成功」 ---------- */
@@ -217,7 +219,7 @@ test('issue#56:有未生效项时 kind=partial(不得显示为成功)', ()
217
219
  ineffective: [{ itemId: 'plugins:some-plugin', adapter: 'plugins', message: '插件 some-plugin 安装失败:release-age-violation' }],
218
220
  result: {},
219
221
  }
220
- const view = applyItemsReportView(report)
222
+ const view = applyItemsReportView(report, zhUiT)
221
223
  assert.equal(view?.kind, 'partial', 'ok=true 但有未生效项 ⇒ partial,绝不是 ok')
222
224
  assert.match(view?.headline ?? '', /1/, '头部要给出未生效条数')
223
225
  assert.deepEqual(view?.ineffective.map((i) => i.itemId), ['plugins:some-plugin'])
@@ -231,9 +233,9 @@ test('issue#56:未生效项不影响「全部成功」判定(空/缺字段
231
233
  warnings: [], restoreId: 'r', rolledBack: false, failed: [], result: {},
232
234
  } as ApplyItemsResponse
233
235
  // 空数组(新宿主明确回报「没有未生效项」)
234
- assert.equal(applyItemsReportView({ ...base, ineffective: [] })?.kind, 'ok')
236
+ assert.equal(applyItemsReportView({ ...base, ineffective: [] }, zhUiT)?.kind, 'ok')
235
237
  // 缺字段(旧宿主)→ 按无未生效项处理,绝不误报部分成功
236
- assert.equal(applyItemsReportView(base)?.kind, 'ok')
238
+ assert.equal(applyItemsReportView(base, zhUiT)?.kind, 'ok')
237
239
  })
238
240
 
239
241
  /* ---------------------------------------------------------------- 自动同步 */
@@ -276,16 +278,66 @@ test('sync-view: autosyncStatusText 覆盖未运行 / 各状态', () => {
276
278
  const status: AutosyncStatusResponse = {
277
279
  enabled: true, interval: '30m', consecutiveFailures: 0, elapsedMs: -1,
278
280
  }
279
- assert.match(autosyncStatusText(status), /从未运行/)
281
+ assert.match(autosyncStatusText(status, zhUiT), /从未运行/)
280
282
  const ran: AutosyncStatusResponse = {
281
283
  enabled: true, interval: '30m', consecutiveFailures: 0, elapsedMs: 0,
282
284
  lastRunAt: '2026-08-17T10:00:00.000Z', lastRunStatus: 'success',
283
285
  }
284
- assert.match(autosyncStatusText(ran), /成功/)
286
+ assert.match(autosyncStatusText(ran, zhUiT), /成功/)
285
287
  const failed: AutosyncStatusResponse = {
286
288
  enabled: true, interval: '30m', consecutiveFailures: 3, elapsedMs: 0,
287
289
  lastRunAt: '2026-08-17T10:00:00.000Z', lastRunStatus: 'failed', lastRunMessage: '认证失败',
288
290
  }
289
- assert.match(autosyncStatusText(failed), /失败/)
290
- assert.match(autosyncStatusText(failed), /连续失败 3 次/)
291
+ assert.match(autosyncStatusText(failed, zhUiT), /失败/)
292
+ assert.match(autosyncStatusText(failed, zhUiT), /连续失败 3 次/)
293
+ })
294
+
295
+ /* ---------------------- 诚实性:整体回滚「未完成」必须单独成态 ---------------------- */
296
+
297
+ test('回滚未完成(rollbackFull=false):kind=rollbackIncomplete,绝不渲染成「已整体回滚」', () => {
298
+ const report: ApplyItemsResponse = {
299
+ ok: false, applied: [], skipped: [], needsRestart: false,
300
+ warnings: ['回滚未完成:credentialsStatus:K —— DSH 不回读凭据值,无法自动恢复(请重新补录该凭据)'],
301
+ restoreId: 'rest-x', rolledBack: true, rollbackFull: false,
302
+ failed: [{ itemId: 'x', message: '导入失败' }], result: {},
303
+ }
304
+ const view = applyItemsReportView(report, zhUiT)
305
+ assert.equal(view?.kind, 'rollbackIncomplete', '半回滚必须与 rolledBack(整体已回滚)分开')
306
+ assert.equal(view?.rollbackFull, false)
307
+ assert.doesNotMatch(view?.headline ?? '', /已整体回滚/, '不得复用断言「已整体回滚」的失败文案')
308
+ assert.match(view?.headline ?? '', /回滚未完成/)
309
+ // 未恢复项在 warnings 里逐条给出(引擎已并入),界面据此列出
310
+ assert.match(view?.warnings.join(' ') ?? '', /credentialsStatus:K/)
311
+ })
312
+
313
+ test('回滚未完成:headline 走 sync 字典专用键(可注入本地化取词器)', () => {
314
+ const report: ApplyItemsResponse = {
315
+ ok: false, applied: [], skipped: [], needsRestart: false, warnings: [],
316
+ restoreId: 'r', rolledBack: true, rollbackFull: false, failed: [], result: {},
317
+ }
318
+ const view = applyItemsReportView(report, zhUiT, (key) => 'SYNC:' + key)
319
+ assert.equal(view?.headline, 'SYNC:syncflow.importRollbackIncomplete')
320
+ })
321
+
322
+ test('旧宿主不返回 rollbackFull:rolledBack=true 仍按「已整体回滚」处理(不误报半回滚)', () => {
323
+ const report: ApplyItemsResponse = {
324
+ ok: false, applied: [], skipped: [], needsRestart: false, warnings: [],
325
+ restoreId: 'r', rolledBack: true, failed: [{ itemId: 'x' }], result: {},
326
+ }
327
+ assert.equal(applyItemsReportView(report, zhUiT)?.kind, 'rolledBack')
328
+ })
329
+
330
+ /* ---------------------- G-34:gist 通道不适合大分区 ---------------------- */
331
+
332
+ test('G-34:通道=gist 且勾选 sessions → 风险提示键;其它组合 → null', () => {
333
+ assert.equal(gistSessionsRiskKey('gist', ['sessions']), 'mode.gistSessionsWarn')
334
+ assert.equal(gistSessionsRiskKey('gist', ['skills', 'sessions']), 'mode.gistSessionsWarn', '顺序无关')
335
+ assert.equal(gistSessionsRiskKey('git', ['sessions']), null, '非 gist 通道不提示')
336
+ assert.equal(gistSessionsRiskKey('s3', ['sessions']), null)
337
+ assert.equal(gistSessionsRiskKey('gist', ['skills']), null, '没勾 sessions 不提示')
338
+ assert.equal(gistSessionsRiskKey('gist', []), null)
339
+ })
340
+
341
+ test('G-34:gist 表单常驻提示键指向 sync 字典的专用文案', () => {
342
+ assert.equal(GIST_LARGE_SECTION_HINT_KEY, 'cloud.gistLargeSectionHint')
291
343
  })