dsh-archived-chats 1.3.2 → 1.3.3

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.
package/lib/index.js CHANGED
@@ -88,14 +88,6 @@ import { createRetentionStore } from './retention.js';
88
88
  import { startRetentionScheduler } from './auto-retention.js';
89
89
  import { createRetentionService } from './retention-service.js';
90
90
  import { projectLineage } from './lineage.js';
91
- import { createHistoryService } from './history.js';
92
- import { createHistoryRestoreService } from './history-restore.js';
93
- import {
94
- createLegacyRecycleService,
95
- createLegacyRecycleStore,
96
- createRecycleHub,
97
- createUnifiedTrashStore,
98
- } from './legacy-recycle.js';
99
91
  import { createWorkspaceBulkArchiveService } from './workspace-bulk-archive.js';
100
92
  import { resolvePersistenceCompat } from './persistence-compat.js';
101
93
  import { atomicWriteFile } from './durable.js';
@@ -820,7 +812,7 @@ async function deleteSession(ctx, registry, persistence, id, titleCache, statsSe
820
812
  //#endregion
821
813
 
822
814
  //#region routes
823
- function registerRoutes(ctx, webServer, registry, persistence, titleCache, metadataStore, statsService, pendingStore, trashStore, snapshotStore, retentionStore, legacyRecycleStore, lifecycle, importTokens, restoreAdapter) {
815
+ function registerRoutes(ctx, webServer, registry, persistence, titleCache, metadataStore, statsService, pendingStore, trashStore, snapshotStore, retentionStore, lifecycle, importTokens, restoreAdapter) {
824
816
  const projectedMessages = createProjectedMessageCache((id) => persistence.inspect(id));
825
817
  const listInsightSessions = async () => {
826
818
  const pending = await pendingStore.load();
@@ -849,15 +841,6 @@ function registerRoutes(ctx, webServer, registry, persistence, titleCache, metad
849
841
  snapshotStore,
850
842
  listSessions: listInsightSessions,
851
843
  });
852
- const historyService = createHistoryService({
853
- registry,
854
- persistence,
855
- sessions: ctx.get('sessions'),
856
- metadataStore,
857
- trashStore,
858
- snapshotStore,
859
- lifecycle,
860
- });
861
844
  let workspaceBulkArchiveService = null;
862
845
  let workspaceArchiveUnavailableLogged = false;
863
846
  const workspaceArchiveSecret = randomUUID();
@@ -899,9 +882,8 @@ function registerRoutes(ctx, webServer, registry, persistence, titleCache, metad
899
882
  statsService.invalidate(ids);
900
883
  projectedMessages.invalidate(ids);
901
884
  insightsService.invalidate();
902
- historyService.invalidate();
903
885
  };
904
- const regularRecycleService = createRecycleService({
886
+ const recycleService = createRecycleService({
905
887
  registry,
906
888
  persistence,
907
889
  attachments: ctx.get('attachments'),
@@ -935,50 +917,15 @@ function registerRoutes(ctx, webServer, registry, persistence, titleCache, metad
935
917
  invalidate: invalidateRecycleCaches,
936
918
  logger: ctx.logger,
937
919
  });
938
- const historyRestoreService = createHistoryRestoreService({
939
- snapshotStore,
940
- persistence,
941
- attachments: ctx.get('attachments'),
942
- registry,
943
- metadataStore,
944
- lifecycle,
945
- invalidate: (restoredId, sourceId) => {
946
- titleCache.delete(restoredId);
947
- statsService.invalidate([restoredId]);
948
- projectedMessages.invalidate([restoredId, sourceId]);
949
- insightsService.invalidate();
950
- historyService.invalidate();
951
- },
952
- logger: ctx.logger,
953
- });
954
- const legacyRecycleService = createLegacyRecycleService({
955
- store: legacyRecycleStore,
956
- historyService,
957
- historyRestoreService,
958
- snapshotStore,
959
- trashStore,
960
- lifecycle,
961
- logger: ctx.logger,
962
- });
963
- const recycleService = createRecycleHub({
964
- recycleService: regularRecycleService,
965
- legacyRecycleService,
966
- });
967
- const unifiedTrashStore = createUnifiedTrashStore({ trashStore, legacyRecycleService });
968
920
  const retentionService = createRetentionService({
969
921
  insightsService,
970
922
  retentionStore,
971
- trashStore: unifiedTrashStore,
923
+ trashStore,
972
924
  snapshotStore,
973
925
  recycleService,
974
926
  lifecycle,
975
927
  });
976
928
 
977
- const historyError = (res, error, fallback) => {
978
- const status = error?.status ?? (error instanceof SyntaxError || error instanceof TypeError ? 400 : 500);
979
- send(res, status, { ok: false, error: error?.code ?? fallback });
980
- };
981
-
982
929
  const workspaceArchiveError = (res, error, fallback) => {
983
930
  const status = error?.status ?? (error instanceof SyntaxError || error instanceof TypeError ? 400 : 500);
984
931
  send(res, status, { ok: false, error: error?.code ?? fallback });
@@ -1036,130 +983,6 @@ function registerRoutes(ctx, webServer, registry, persistence, titleCache, metad
1036
983
  },
1037
984
  }), 'archived-chats: workspace archive apply route');
1038
985
 
1039
- ctx.effect(() => webServer.register({
1040
- kind: 'exact',
1041
- path: `${ROUTE_PREFIX}/history/capture`,
1042
- handler: async (req, res) => {
1043
- if (!guard(req, res)) return;
1044
- send(res, 410, { ok: false, error: 'history-capture-retired' });
1045
- },
1046
- }), 'archived-chats: history capture route');
1047
-
1048
- ctx.effect(() => webServer.register({
1049
- kind: 'exact',
1050
- path: `${ROUTE_PREFIX}/history`,
1051
- handler: async (req, res) => {
1052
- if (req.method !== 'GET') { send(res, 405, { ok: false, error: 'method-not-allowed' }); return; }
1053
- try { send(res, 200, { ok: true, ...(await historyService.list()) }); }
1054
- catch (error) { historyError(res, error, 'history-list-failed'); }
1055
- },
1056
- }), 'archived-chats: history route');
1057
-
1058
- ctx.effect(() => webServer.register({
1059
- kind: 'exact',
1060
- path: `${ROUTE_PREFIX}/history/delete`,
1061
- handler: async (req, res) => {
1062
- if (!guard(req, res)) return;
1063
- try {
1064
- const body = await readBody(req, 64 * 1024);
1065
- if (!exactBody(body, ['snapshotId']) || typeof body.snapshotId !== 'string' || body.snapshotId === '') {
1066
- send(res, 400, { ok: false, error: 'history-delete-invalid' });
1067
- return;
1068
- }
1069
- const result = await historyService.deleteVersion(body.snapshotId);
1070
- insightsService.invalidate();
1071
- send(res, 200, { ok: true, ...result });
1072
- } catch (error) { historyError(res, error, 'history-delete-failed'); }
1073
- },
1074
- }), 'archived-chats: history delete route');
1075
-
1076
- ctx.effect(() => webServer.register({
1077
- kind: 'exact',
1078
- path: `${ROUTE_PREFIX}/history/delete-all`,
1079
- handler: async (req, res) => {
1080
- if (!guard(req, res)) return;
1081
- try {
1082
- const body = await readBody(req, 64 * 1024);
1083
- if (!exactBody(body, [])) {
1084
- send(res, 400, { ok: false, error: 'history-delete-all-invalid' });
1085
- return;
1086
- }
1087
- const result = await historyService.clear();
1088
- if (result.deleted.length > 0) insightsService.invalidate();
1089
- const status = result.failed.length > 0 && result.deleted.length === 0 ? 409 : 200;
1090
- send(res, status, { ok: result.failed.length === 0, ...result });
1091
- } catch (error) { historyError(res, error, 'history-delete-all-failed'); }
1092
- },
1093
- }), 'archived-chats: history delete all route');
1094
-
1095
- ctx.effect(() => webServer.register({
1096
- kind: 'exact',
1097
- path: `${ROUTE_PREFIX}/history/preview`,
1098
- handler: async (req, res) => {
1099
- if (!guard(req, res)) return;
1100
- try {
1101
- const body = await readBody(req, 64 * 1024);
1102
- if (!exactBody(body, ['snapshotId', 'offset', 'limit']) || typeof body.snapshotId !== 'string') {
1103
- send(res, 400, { ok: false, error: 'history-preview-invalid' });
1104
- return;
1105
- }
1106
- send(res, 200, { ok: true, ...(await historyService.preview(body.snapshotId, { offset: body.offset, limit: body.limit })) });
1107
- } catch (error) { historyError(res, error, 'history-preview-failed'); }
1108
- },
1109
- }), 'archived-chats: history preview route');
1110
-
1111
- ctx.effect(() => webServer.register({
1112
- kind: 'exact',
1113
- path: `${ROUTE_PREFIX}/history/preview/image`,
1114
- handler: async (req, res) => {
1115
- if (!guard(req, res)) return;
1116
- const request = requestAbort(req);
1117
- try {
1118
- const body = await readBody(req, 64 * 1024);
1119
- if (!exactBody(body, ['snapshotId', 'attachment']) || typeof body.snapshotId !== 'string'
1120
- || body.attachment === null || typeof body.attachment !== 'object' || Array.isArray(body.attachment)) {
1121
- send(res, 400, { ok: false, error: 'history-preview-image-invalid' });
1122
- return;
1123
- }
1124
- const image = await historyService.readImage(body.snapshotId, body.attachment, request.signal);
1125
- sendImage(res, { data: image.data, ref: { mediaType: image.mediaType } });
1126
- } catch (error) {
1127
- if (!request.signal.aborted) historyError(res, error, 'history-preview-image-failed');
1128
- } finally { request.dispose(); }
1129
- },
1130
- }), 'archived-chats: history preview image route');
1131
-
1132
- ctx.effect(() => webServer.register({
1133
- kind: 'exact',
1134
- path: `${ROUTE_PREFIX}/history/restore/preview`,
1135
- handler: async (req, res) => {
1136
- if (!guard(req, res)) return;
1137
- try {
1138
- const body = await readBody(req, 64 * 1024);
1139
- if (!exactBody(body, ['snapshotId']) || typeof body.snapshotId !== 'string' || body.snapshotId === '') {
1140
- send(res, 400, { ok: false, error: 'history-restore-preview-invalid' });
1141
- return;
1142
- }
1143
- send(res, 200, { ok: true, ...(await historyRestoreService.prepare(body.snapshotId)) });
1144
- } catch (error) { historyError(res, error, 'history-restore-preview-failed'); }
1145
- },
1146
- }), 'archived-chats: history restore preview route');
1147
-
1148
- ctx.effect(() => webServer.register({
1149
- kind: 'exact',
1150
- path: `${ROUTE_PREFIX}/history/restore`,
1151
- handler: async (req, res) => {
1152
- if (!guard(req, res)) return;
1153
- try {
1154
- const body = await readBody(req, 64 * 1024);
1155
- if (!exactBody(body, ['token', 'nonce']) || typeof body.token !== 'string' || typeof body.nonce !== 'string') {
1156
- send(res, 400, { ok: false, error: 'history-restore-confirmation-invalid' });
1157
- return;
1158
- }
1159
- send(res, 200, { ok: true, ...(await historyRestoreService.restore(body.token, body.nonce)) });
1160
- } catch (error) { historyError(res, error, 'history-restore-failed'); }
1161
- },
1162
- }), 'archived-chats: history restore route');
1163
986
  ctx.effect(() => webServer.register({
1164
987
  kind: 'exact',
1165
988
  path: `${ROUTE_PREFIX}/state`,
@@ -1805,7 +1628,6 @@ export function apply(ctx) {
1805
1628
  const pendingStore = createPendingStore();
1806
1629
  const trashStore = createTrashStore({ path: join(pluginDataRoot, 'trash.json') });
1807
1630
  const retentionStore = createRetentionStore({ path: join(pluginDataRoot, 'retention.json') });
1808
- const legacyRecycleStore = createLegacyRecycleStore({ path: join(pluginDataRoot, 'legacy-recycle.json') });
1809
1631
  const importTokens = createImportTokenStore();
1810
1632
  const lifecycle = createLifecycleQueue();
1811
1633
  let statsService;
@@ -1830,7 +1652,7 @@ export function apply(ctx) {
1830
1652
  metadataStore,
1831
1653
  tempRoot: join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'plugin-data', 'archived-chats', 'imports'),
1832
1654
  });
1833
- const { recycleService, retentionService } = registerRoutes(ctx, webServer, registry, persistence, titleCache, metadataStore, statsService, pendingStore, trashStore, snapshotStore, retentionStore, legacyRecycleStore, lifecycle, importTokens, restoreAdapter);
1655
+ const { recycleService, retentionService } = registerRoutes(ctx, webServer, registry, persistence, titleCache, metadataStore, statsService, pendingStore, trashStore, snapshotStore, retentionStore, lifecycle, importTokens, restoreAdapter);
1834
1656
  ctx.effect(() => startRetentionScheduler({
1835
1657
  recover: () => recycleService.recoverStartup({ legacyPendingPath: pendingFilePath() }),
1836
1658
  run: (options) => retentionService.runAutomatic(options),
package/lib/insights.js CHANGED
@@ -102,7 +102,9 @@ export function createInsightsService({
102
102
  const snapshots = [];
103
103
  for (const item of inventory.valid) {
104
104
  if (item === null || typeof item !== 'object'
105
- || typeof item.snapshotId !== 'string' || item.snapshotId === ''
105
+ || typeof item.snapshotId !== 'string' || item.snapshotId === '') throw authorityUnavailable();
106
+ if (!activeSnapshotIds.has(item.snapshotId)) continue;
107
+ if (item === null || typeof item !== 'object'
106
108
  || typeof item.sessionId !== 'string' || item.sessionId === ''
107
109
  || typeof item.createdAt !== 'string'
108
110
  || !Number.isSafeInteger(item.totalBytes) || item.totalBytes < 0
@@ -125,18 +127,19 @@ export function createInsightsService({
125
127
  sessionBytes: item.sessionBytes,
126
128
  attachmentCount: item.attachmentCount,
127
129
  status: 'ready',
128
- active: activeSnapshotIds.has(item.snapshotId),
130
+ active: true,
129
131
  });
130
132
  }
131
133
  for (const item of inventory.degraded) {
132
134
  if (item === null || typeof item !== 'object'
133
- || typeof item.snapshotId !== 'string' || item.snapshotId === ''
134
- || typeof item.code !== 'string' || item.code === '') throw authorityUnavailable();
135
+ || typeof item.snapshotId !== 'string' || item.snapshotId === '') throw authorityUnavailable();
136
+ if (!activeSnapshotIds.has(item.snapshotId)) continue;
137
+ if (typeof item.code !== 'string' || item.code === '') throw authorityUnavailable();
135
138
  snapshots.push({
136
139
  snapshotId: item.snapshotId,
137
140
  status: 'degraded',
138
141
  code: item.code,
139
- active: activeSnapshotIds.has(item.snapshotId),
142
+ active: true,
140
143
  });
141
144
  }
142
145
 
@@ -152,7 +155,7 @@ export function createInsightsService({
152
155
  totalMeasuredBytes: sessionBytes + snapshotBytes,
153
156
  duplicateSnapshotBytes,
154
157
  sessionUnavailableCount: sessions.filter((row) => row.status === 'unavailable').length,
155
- degradedSnapshotCount: inventory.degraded.length,
158
+ degradedSnapshotCount: snapshots.filter((row) => row.status === 'degraded').length,
156
159
  },
157
160
  sessions,
158
161
  snapshots,
package/lib/recycle.js CHANGED
@@ -544,6 +544,32 @@ export function createRecycleService({
544
544
  }
545
545
  }
546
546
  }
547
+
548
+ // Historical versions could leave published snapshots that were never
549
+ // referenced by the durable recycle catalog. Re-read both authorities
550
+ // after pending migration because migration may create a protection
551
+ // snapshot which must survive this startup pass.
552
+ if (typeof snapshotStore.inventory === 'function') {
553
+ await lifecycle.run(async () => {
554
+ const currentRecords = await loadedTrash();
555
+ const protectedIds = new Set(
556
+ [...currentRecords.values()]
557
+ .map((record) => record?.snapshotId)
558
+ .filter((snapshotId) => typeof snapshotId === 'string' && snapshotId !== ''),
559
+ );
560
+ const inventory = await snapshotStore.inventory();
561
+ const candidates = [...(inventory?.valid ?? []), ...(inventory?.degraded ?? [])]
562
+ .map((item) => item?.snapshotId)
563
+ .filter((snapshotId) => typeof snapshotId === 'string' && snapshotId !== '' && !protectedIds.has(snapshotId));
564
+ for (const snapshotId of new Set(candidates)) {
565
+ try {
566
+ await snapshotStore.remove(snapshotId);
567
+ } catch (cause) {
568
+ logger?.warn?.('archived-chats: legacy snapshot cleanup failed: ' + stableCode(cause, 'snapshot-cleanup-failed'));
569
+ }
570
+ }
571
+ });
572
+ }
547
573
  return { status: 'ready' };
548
574
  }
549
575
 
@@ -3,10 +3,9 @@
3
3
  * chooser and one-confirmation bulk archive flow. The flow stays inside the
4
4
  * plugin-owned Settings surface and requires no workspace-row extension slot.
5
5
  * The searchable manager includes Archived, Recycle Bin, Storage & Retention,
6
- * and Origins & Branches views. Existing legacy snapshots appear in the
7
- * Recycle Bin and restore only as new archived copies. Removing an archived
8
- * chat moves it to recoverable trash and exposes immediate Undo. The recycle
9
- * view provides scoped read-only previews, original/snapshot restore, guarded
6
+ * and Origins & Branches views. Removing an archived chat moves it to
7
+ * recoverable trash and exposes immediate Undo. The recycle view provides
8
+ * scoped read-only previews, original/snapshot restore, guarded
10
9
  * permanent purge and empty operations, degraded-state warnings, responsive
11
10
  * rows, and accessible confirmation dialogs, all localized in English and 中文.
12
11
  */
@@ -15,10 +14,6 @@ export type RecycleLiveDisposition = 'cold' | 'disposed' | 'parked';
15
14
 
16
15
  export interface RecycleSessionRow {
17
16
  sessionId: string;
18
- sourceKind?: 'legacy-snapshot';
19
- legacySnapshotId?: string;
20
- sourceSessionId?: string | null;
21
- restorable?: boolean;
22
17
  state: RecycleRecordState;
23
18
  trashedAt: string;
24
19
  purgeRequestedAt: string | null;
@@ -52,45 +47,6 @@ export interface RetentionPolicy {
52
47
  recycleAutoDelete: boolean;
53
48
  }
54
49
 
55
- export type HistoryScope = 'archived' | 'recycled' | 'history-only';
56
- export type HistoryVersionState = 'history' | 'recycle-protection';
57
-
58
- export interface HistoryVersion {
59
- snapshotId: string;
60
- createdAt: string;
61
- totalBytes: number;
62
- attachmentCount: number;
63
- state: HistoryVersionState;
64
- }
65
-
66
- export interface HistorySession {
67
- sessionId: string;
68
- title: string | null;
69
- workspace: { id: string | null; title: string | null } | null;
70
- scope: HistoryScope;
71
- versions: HistoryVersion[];
72
- }
73
-
74
- export interface HistoryResponse {
75
- generatedAt: string;
76
- sessions: HistorySession[];
77
- degraded: Array<{ snapshotId: string; code: string }>;
78
- }
79
-
80
- export interface HistoryRestoreResult {
81
- restored: string[];
82
- sourceSessionId: string;
83
- snapshotId: string;
84
- warnings: Array<{ id: string; reason: string }>;
85
- }
86
-
87
- export interface HistoryDeleteResult {
88
- deleted: string[];
89
- freedBytes: number;
90
- skipped?: Array<{ snapshotId: string; reason: string }>;
91
- failed?: Array<{ snapshotId: string; reason: string }>;
92
- }
93
-
94
50
  export interface StorageInsightsSummary {
95
51
  sessionBytes: number;
96
52
  snapshotBytes: number;
@@ -140,15 +96,6 @@ export interface StorageInsights {
140
96
  }
141
97
 
142
98
  export type RetentionCandidate =
143
- | {
144
- key: string;
145
- action: 'delete-snapshot';
146
- reason: 'history-count' | 'snapshot-age' | 'snapshot-quota';
147
- snapshotId: string;
148
- sessionId: string;
149
- createdAt: string;
150
- bytes: number;
151
- }
152
99
  | {
153
100
  key: string;
154
101
  action: 'purge-trash';
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Host loader entry — registers the `/plugins/dsh-archived-chats/*` routes
3
3
  * (state, stats, insights, retention/policy, retention/preview, retention/apply,
4
- * lineage, history, history/capture, history/preview, history/preview/image,
5
- * history/restore/preview, history/restore, history/delete, history/delete-all,
4
+ * lineage,
6
5
  * workspace-archive/workspaces, workspace-archive/preview,
7
6
  * workspace-archive/apply,
8
7
  * preview, preview/image, search,
@@ -38,10 +37,6 @@ export type RecycleLiveDisposition = 'cold' | 'disposed' | 'parked';
38
37
 
39
38
  export interface RecycleSessionRow {
40
39
  sessionId: string;
41
- sourceKind?: 'legacy-snapshot';
42
- legacySnapshotId?: string;
43
- sourceSessionId?: string | null;
44
- restorable?: boolean;
45
40
  state: RecycleRecordState;
46
41
  trashedAt: string;
47
42
  purgeRequestedAt: string | null;
@@ -75,46 +70,6 @@ export interface RetentionPolicy {
75
70
  recycleAutoDelete: boolean;
76
71
  }
77
72
 
78
- export type HistoryScope = 'archived' | 'recycled' | 'history-only';
79
- export type HistoryVersionState = 'history' | 'recycle-protection';
80
-
81
- export interface HistoryVersion {
82
- snapshotId: string;
83
- createdAt: string;
84
- totalBytes: number;
85
- attachmentCount: number;
86
- state: HistoryVersionState;
87
- }
88
-
89
- export interface HistorySession {
90
- sessionId: string;
91
- title: string | null;
92
- workspace: { id: string | null; title: string | null } | null;
93
- scope: HistoryScope;
94
- versions: HistoryVersion[];
95
- }
96
-
97
- export interface HistoryResponse {
98
- generatedAt: string;
99
- sessions: HistorySession[];
100
- degraded: Array<{ snapshotId: string; code: string }>;
101
- }
102
-
103
- export interface HistoryRestoreResult {
104
- restored: string[];
105
- sourceSessionId: string;
106
- snapshotId: string;
107
- warnings: Array<{ id: string; reason: string }>;
108
- }
109
-
110
- /** A degraded version carries no readable bytes but can still be reclaimed. */
111
- export interface HistoryDeleteResult {
112
- deleted: string[];
113
- freedBytes: number;
114
- skipped?: Array<{ snapshotId: string; reason: string }>;
115
- failed?: Array<{ snapshotId: string; reason: string }>;
116
- }
117
-
118
73
  export interface StorageInsightsSummary {
119
74
  sessionBytes: number;
120
75
  snapshotBytes: number;
@@ -164,15 +119,6 @@ export interface StorageInsights {
164
119
  }
165
120
 
166
121
  export type RetentionCandidate =
167
- | {
168
- key: string;
169
- action: 'delete-snapshot';
170
- reason: 'history-count' | 'snapshot-age' | 'snapshot-quota';
171
- snapshotId: string;
172
- sessionId: string;
173
- createdAt: string;
174
- bytes: number;
175
- }
176
122
  | {
177
123
  key: string;
178
124
  action: 'purge-trash';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-archived-chats",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "DeepSeek Harness 会话档案:从设置中安全归档工作区会话,按工作区浏览和全文搜索归档聊天,原生只读预览对话、工具活动和已存储图片,管理标签备注与 ZIP 备份恢复;提供统一回收站、可选自动清理、空间分账和来源与分支,已有快照直接进入回收站。所有数据留在本机。 Session Archive for DeepSeek Harness: safely archive workspace chats from Settings; browse and full-text search archived chats; preview conversations, tool activity, and stored images read-only; manage tags, notes, and ZIP backup restore; provide a unified Recycle Bin, optional automatic cleanup, storage accounting, and Origins & Branches, with existing snapshots shown directly in the Recycle Bin. All data stays local.",
5
5
  "license": "MIT",
6
6
  "author": "Ultronen",
@@ -63,9 +63,6 @@
63
63
  "lib/auto-retention.js",
64
64
  "lib/retention-service.js",
65
65
  "lib/lineage.js",
66
- "lib/history.js",
67
- "lib/history-restore.js",
68
- "lib/legacy-recycle.js",
69
66
  "lib/workspace-bulk-archive.js",
70
67
  "lib/persistence-compat.js",
71
68
  "lib/search.js",