@remnic/core 9.34.0 → 9.35.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.
- package/dist/access-admin-ops-surface.js +10 -10
- package/dist/access-authorization-probe.js +11 -11
- package/dist/access-boundary.js +10 -10
- package/dist/access-cli.js +26 -26
- package/dist/access-extraction-force-flush.js +10 -10
- package/dist/access-http.js +17 -17
- package/dist/access-identity-continuity-surface.js +10 -10
- package/dist/access-lcm-surface.js +10 -10
- package/dist/access-mcp.js +15 -15
- package/dist/access-namespace-preflight.js +10 -10
- package/dist/access-observe-write-surface.js +10 -10
- package/dist/access-operations-batch.js +12 -12
- package/dist/access-operations.js +14 -14
- package/dist/access-recall-concurrency.js +10 -10
- package/dist/access-recall-response.js +10 -10
- package/dist/access-recall-surface.js +10 -10
- package/dist/access-schema.js +3 -3
- package/dist/access-service.js +10 -10
- package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-RSFWAI4D.js → chunk-2NUC473W.js} +8 -8
- package/dist/{chunk-KJT3PZAR.js → chunk-2SHIWGY7.js} +2 -2
- package/dist/{chunk-FYO2GAZJ.js → chunk-3F2LKUMU.js} +2 -2
- package/dist/{chunk-FL3AM5KE.js → chunk-5FHE4JI7.js} +3 -3
- package/dist/{chunk-DG2R7M7K.js → chunk-5HTAJCTO.js} +5 -5
- package/dist/{chunk-7CCVK67W.js → chunk-65ZPVYTA.js} +5 -5
- package/dist/{chunk-HULSU7PS.js → chunk-AHZYNPLX.js} +2 -2
- package/dist/{chunk-6HXQ2YO5.js → chunk-EH5U2YCX.js} +2 -2
- package/dist/{chunk-QEPNZBBC.js → chunk-GHR7WHZX.js} +3 -3
- package/dist/{chunk-LRYAQGDR.js → chunk-HEVWWPTL.js} +18 -18
- package/dist/{chunk-SUZI6BHQ.js → chunk-IOQFPVGY.js} +2 -2
- package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-PYHOAXTI.js → chunk-LRGSLV7M.js} +4 -4
- package/dist/{chunk-WFYWGDM6.js → chunk-SA3WJJF2.js} +2 -2
- package/dist/{chunk-RLOVRJZN.js → chunk-SLPLPGJQ.js} +6 -6
- package/dist/{chunk-OXBPHIKH.js → chunk-T4HH5Q3U.js} +5 -5
- package/dist/{chunk-RQBF54FC.js → chunk-TJLLYV2X.js} +3 -3
- package/dist/{chunk-Y6XRTQMV.js → chunk-UZQCNOPS.js} +4 -4
- package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/cli.js +25 -25
- package/dist/contradiction/index.js +4 -4
- package/dist/corpus-watermark.js +6 -6
- package/dist/index.js +31 -31
- package/dist/namespaces/migrate.js +5 -5
- package/dist/namespaces/search.js +4 -4
- package/dist/operator-doctor-corpus.js +7 -7
- package/dist/operator-toolkit.js +8 -8
- package/dist/orchestrator.js +26 -26
- package/dist/reconcile/plan.d.ts +175 -0
- package/dist/reconcile/plan.js +420 -0
- package/dist/reconcile/plan.js.map +1 -0
- package/dist/search/factory.js +3 -3
- package/dist/search/index.js +7 -7
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/package.json +12 -2
- package/src/reconcile/plan.test.ts +1013 -0
- package/src/reconcile/plan.ts +813 -0
- /package/dist/{capsule-crypto-GWVG7LGC.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-RSFWAI4D.js.map → chunk-2NUC473W.js.map} +0 -0
- /package/dist/{chunk-KJT3PZAR.js.map → chunk-2SHIWGY7.js.map} +0 -0
- /package/dist/{chunk-FYO2GAZJ.js.map → chunk-3F2LKUMU.js.map} +0 -0
- /package/dist/{chunk-FL3AM5KE.js.map → chunk-5FHE4JI7.js.map} +0 -0
- /package/dist/{chunk-DG2R7M7K.js.map → chunk-5HTAJCTO.js.map} +0 -0
- /package/dist/{chunk-7CCVK67W.js.map → chunk-65ZPVYTA.js.map} +0 -0
- /package/dist/{chunk-HULSU7PS.js.map → chunk-AHZYNPLX.js.map} +0 -0
- /package/dist/{chunk-6HXQ2YO5.js.map → chunk-EH5U2YCX.js.map} +0 -0
- /package/dist/{chunk-QEPNZBBC.js.map → chunk-GHR7WHZX.js.map} +0 -0
- /package/dist/{chunk-LRYAQGDR.js.map → chunk-HEVWWPTL.js.map} +0 -0
- /package/dist/{chunk-SUZI6BHQ.js.map → chunk-IOQFPVGY.js.map} +0 -0
- /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-PYHOAXTI.js.map → chunk-LRGSLV7M.js.map} +0 -0
- /package/dist/{chunk-WFYWGDM6.js.map → chunk-SA3WJJF2.js.map} +0 -0
- /package/dist/{chunk-RLOVRJZN.js.map → chunk-SLPLPGJQ.js.map} +0 -0
- /package/dist/{chunk-OXBPHIKH.js.map → chunk-T4HH5Q3U.js.map} +0 -0
- /package/dist/{chunk-RQBF54FC.js.map → chunk-TJLLYV2X.js.map} +0 -0
- /package/dist/{chunk-Y6XRTQMV.js.map → chunk-UZQCNOPS.js.map} +0 -0
- /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
|
@@ -2,16 +2,16 @@ import {
|
|
|
2
2
|
NamespaceSearchRouter,
|
|
3
3
|
namespaceCollectionName,
|
|
4
4
|
normalizeQmdResultPath
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-IOQFPVGY.js";
|
|
6
|
+
import "../chunk-UZQCNOPS.js";
|
|
7
|
+
import "../chunk-ES36HTSC.js";
|
|
7
8
|
import "../chunk-3Y224NYC.js";
|
|
8
9
|
import "../chunk-H24WNPA2.js";
|
|
9
10
|
import "../chunk-BLAKS3CP.js";
|
|
10
11
|
import "../chunk-S2BBISHU.js";
|
|
11
|
-
import "../chunk-CYEPCZN5.js";
|
|
12
|
-
import "../chunk-ES36HTSC.js";
|
|
13
12
|
import "../chunk-W7IGLX4G.js";
|
|
14
13
|
import "../chunk-CINZGPSJ.js";
|
|
14
|
+
import "../chunk-CYEPCZN5.js";
|
|
15
15
|
import "../chunk-LEPOP46W.js";
|
|
16
16
|
import "../chunk-72A4L5JJ.js";
|
|
17
17
|
import "../chunk-A7Q43EUZ.js";
|
|
@@ -2,21 +2,21 @@ import {
|
|
|
2
2
|
corpusWatermarksFromCheck,
|
|
3
3
|
summarizeCorpusAndReplica,
|
|
4
4
|
summarizeCorpusWatermark
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AHZYNPLX.js";
|
|
6
6
|
import "./chunk-WDISJRMG.js";
|
|
7
7
|
import "./chunk-XOQSEF7X.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-SA3WJJF2.js";
|
|
9
|
+
import "./chunk-2SHIWGY7.js";
|
|
10
|
+
import "./chunk-IOQFPVGY.js";
|
|
11
|
+
import "./chunk-UZQCNOPS.js";
|
|
12
|
+
import "./chunk-ES36HTSC.js";
|
|
12
13
|
import "./chunk-3Y224NYC.js";
|
|
13
14
|
import "./chunk-H24WNPA2.js";
|
|
14
15
|
import "./chunk-BLAKS3CP.js";
|
|
15
16
|
import "./chunk-S2BBISHU.js";
|
|
16
|
-
import "./chunk-CYEPCZN5.js";
|
|
17
|
-
import "./chunk-ES36HTSC.js";
|
|
18
17
|
import "./chunk-W7IGLX4G.js";
|
|
19
18
|
import "./chunk-CINZGPSJ.js";
|
|
19
|
+
import "./chunk-CYEPCZN5.js";
|
|
20
20
|
import "./chunk-Y2ZD2RVG.js";
|
|
21
21
|
import "./chunk-LEPOP46W.js";
|
|
22
22
|
import "./chunk-72A4L5JJ.js";
|
package/dist/operator-toolkit.js
CHANGED
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
summarizeProvenanceCoverage,
|
|
15
15
|
summarizeTierDistribution,
|
|
16
16
|
summarizeTombstoneStatus
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TJLLYV2X.js";
|
|
18
18
|
import "./chunk-TCIWHK3N.js";
|
|
19
19
|
import "./chunk-KFY3SGN7.js";
|
|
20
20
|
import "./chunk-CMTINOFS.js";
|
|
21
|
-
import "./chunk-
|
|
21
|
+
import "./chunk-AHZYNPLX.js";
|
|
22
22
|
import "./chunk-WDISJRMG.js";
|
|
23
23
|
import "./chunk-OZKOPQCM.js";
|
|
24
24
|
import "./chunk-2DQ2XREU.js";
|
|
@@ -37,18 +37,18 @@ import "./chunk-KFZY2OFH.js";
|
|
|
37
37
|
import "./chunk-J6SLNQRO.js";
|
|
38
38
|
import "./chunk-ULARSG5Z.js";
|
|
39
39
|
import "./chunk-XOQSEF7X.js";
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
42
|
-
import "./chunk-
|
|
43
|
-
import "./chunk-
|
|
40
|
+
import "./chunk-SA3WJJF2.js";
|
|
41
|
+
import "./chunk-2SHIWGY7.js";
|
|
42
|
+
import "./chunk-IOQFPVGY.js";
|
|
43
|
+
import "./chunk-UZQCNOPS.js";
|
|
44
|
+
import "./chunk-ES36HTSC.js";
|
|
44
45
|
import "./chunk-3Y224NYC.js";
|
|
45
46
|
import "./chunk-H24WNPA2.js";
|
|
46
47
|
import "./chunk-BLAKS3CP.js";
|
|
47
48
|
import "./chunk-S2BBISHU.js";
|
|
48
|
-
import "./chunk-CYEPCZN5.js";
|
|
49
|
-
import "./chunk-ES36HTSC.js";
|
|
50
49
|
import "./chunk-W7IGLX4G.js";
|
|
51
50
|
import "./chunk-CINZGPSJ.js";
|
|
51
|
+
import "./chunk-CYEPCZN5.js";
|
|
52
52
|
import "./chunk-Y2ZD2RVG.js";
|
|
53
53
|
import "./chunk-LEPOP46W.js";
|
|
54
54
|
import "./chunk-72A4L5JJ.js";
|
package/dist/orchestrator.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
filterRecallCandidates,
|
|
5
5
|
graphPathRelativeToStorage,
|
|
6
6
|
mergeGraphExpandedResults
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2NUC473W.js";
|
|
8
8
|
import "./chunk-UV72DEZD.js";
|
|
9
9
|
import "./chunk-I74SUMNI.js";
|
|
10
10
|
import "./chunk-ILNPU5W5.js";
|
|
@@ -95,21 +95,21 @@ import "./chunk-VEWZZM3H.js";
|
|
|
95
95
|
import "./chunk-Q6IP2ARR.js";
|
|
96
96
|
import "./chunk-6HEM6HTQ.js";
|
|
97
97
|
import "./chunk-3I4FUAVJ.js";
|
|
98
|
-
import "./chunk-
|
|
98
|
+
import "./chunk-HEVWWPTL.js";
|
|
99
99
|
import "./chunk-MMACM5G2.js";
|
|
100
100
|
import "./chunk-54BGIBCR.js";
|
|
101
101
|
import "./chunk-H4CKS5B2.js";
|
|
102
102
|
import "./chunk-FXZTL7F7.js";
|
|
103
103
|
import "./chunk-HDDRVXX4.js";
|
|
104
|
-
import "./chunk-
|
|
105
|
-
import "./chunk-OWHERGF2.js";
|
|
106
|
-
import "./chunk-UP6MOYCB.js";
|
|
107
|
-
import "./chunk-BV2TIZ4F.js";
|
|
108
|
-
import "./chunk-Z734BLO3.js";
|
|
104
|
+
import "./chunk-LRGSLV7M.js";
|
|
109
105
|
import "./chunk-OZKVVUJB.js";
|
|
110
106
|
import "./chunk-2DL3OFLD.js";
|
|
111
107
|
import "./chunk-G4IAEX6D.js";
|
|
108
|
+
import "./chunk-2NLLXCJG.js";
|
|
109
|
+
import "./chunk-UP6MOYCB.js";
|
|
112
110
|
import "./chunk-765K3SAT.js";
|
|
111
|
+
import "./chunk-BV2TIZ4F.js";
|
|
112
|
+
import "./chunk-Z734BLO3.js";
|
|
113
113
|
import "./chunk-FGDKJJZS.js";
|
|
114
114
|
import "./chunk-AJVLDJU6.js";
|
|
115
115
|
import "./chunk-XL24QQ63.js";
|
|
@@ -136,12 +136,12 @@ import "./chunk-ZRWB5D4H.js";
|
|
|
136
136
|
import "./chunk-HYQJQGD3.js";
|
|
137
137
|
import "./chunk-DMT2RGAZ.js";
|
|
138
138
|
import "./chunk-33JBK2XP.js";
|
|
139
|
-
import "./chunk-
|
|
139
|
+
import "./chunk-TJLLYV2X.js";
|
|
140
140
|
import "./chunk-TCIWHK3N.js";
|
|
141
141
|
import "./chunk-KFY3SGN7.js";
|
|
142
142
|
import "./chunk-3T74IZB3.js";
|
|
143
143
|
import "./chunk-CMTINOFS.js";
|
|
144
|
-
import "./chunk-
|
|
144
|
+
import "./chunk-AHZYNPLX.js";
|
|
145
145
|
import "./chunk-WDISJRMG.js";
|
|
146
146
|
import "./chunk-UR6PBX2J.js";
|
|
147
147
|
import "./chunk-6GUG4YNM.js";
|
|
@@ -183,7 +183,7 @@ import "./chunk-OO42R444.js";
|
|
|
183
183
|
import "./chunk-PIG4WJFQ.js";
|
|
184
184
|
import "./chunk-KFZY2OFH.js";
|
|
185
185
|
import "./chunk-LBJBNWS2.js";
|
|
186
|
-
import "./chunk-
|
|
186
|
+
import "./chunk-SLPLPGJQ.js";
|
|
187
187
|
import "./chunk-V7IZKJI3.js";
|
|
188
188
|
import "./chunk-SEDEKFYQ.js";
|
|
189
189
|
import "./chunk-RKNJBZ55.js";
|
|
@@ -193,32 +193,32 @@ import "./chunk-42NQ7AVG.js";
|
|
|
193
193
|
import "./chunk-TMSXWOBZ.js";
|
|
194
194
|
import "./chunk-7RXCMVFQ.js";
|
|
195
195
|
import "./chunk-MKQBXQKU.js";
|
|
196
|
-
import "./chunk-
|
|
196
|
+
import "./chunk-5FHE4JI7.js";
|
|
197
197
|
import "./chunk-57QKLRBV.js";
|
|
198
198
|
import "./chunk-D24OXEPB.js";
|
|
199
|
-
import "./chunk-
|
|
200
|
-
import "./chunk-
|
|
199
|
+
import "./chunk-GHR7WHZX.js";
|
|
200
|
+
import "./chunk-T4HH5Q3U.js";
|
|
201
201
|
import "./chunk-HNZKVLAN.js";
|
|
202
202
|
import "./chunk-EQWEIIKQ.js";
|
|
203
|
-
import "./chunk-WG5HSQ4P.js";
|
|
204
203
|
import "./chunk-UTRO5UJU.js";
|
|
204
|
+
import "./chunk-WG5HSQ4P.js";
|
|
205
205
|
import "./chunk-35NN3ZFA.js";
|
|
206
206
|
import "./chunk-CEN6DW6X.js";
|
|
207
207
|
import "./chunk-T4WDJPEZ.js";
|
|
208
|
-
import "./chunk-
|
|
208
|
+
import "./chunk-3F2LKUMU.js";
|
|
209
209
|
import "./chunk-56BSXSHC.js";
|
|
210
210
|
import "./chunk-WWUVONGW.js";
|
|
211
211
|
import "./chunk-5IVLTFOV.js";
|
|
212
212
|
import "./chunk-VCD4PSK2.js";
|
|
213
213
|
import "./chunk-OADWQ5CR.js";
|
|
214
|
-
import "./chunk-
|
|
214
|
+
import "./chunk-EH5U2YCX.js";
|
|
215
215
|
import {
|
|
216
216
|
hasIdentityRecoveryIntent,
|
|
217
217
|
resolveEffectiveIdentityInjectionMode
|
|
218
|
-
} from "./chunk-
|
|
218
|
+
} from "./chunk-5HTAJCTO.js";
|
|
219
219
|
import "./chunk-GDASG7NC.js";
|
|
220
220
|
import "./chunk-GDB4J2H3.js";
|
|
221
|
-
import "./chunk-
|
|
221
|
+
import "./chunk-65ZPVYTA.js";
|
|
222
222
|
import "./chunk-VQ7B2Q6M.js";
|
|
223
223
|
import "./chunk-PJSK6OJM.js";
|
|
224
224
|
import "./chunk-GNVZQ5JN.js";
|
|
@@ -250,18 +250,18 @@ import "./chunk-NLE6TSLG.js";
|
|
|
250
250
|
import "./chunk-QDW3E4RD.js";
|
|
251
251
|
import "./chunk-PH3ZWL3W.js";
|
|
252
252
|
import "./chunk-C37ZRXX7.js";
|
|
253
|
-
import "./chunk-
|
|
254
|
-
import "./chunk-
|
|
255
|
-
import "./chunk-
|
|
256
|
-
import "./chunk-
|
|
253
|
+
import "./chunk-SA3WJJF2.js";
|
|
254
|
+
import "./chunk-2SHIWGY7.js";
|
|
255
|
+
import "./chunk-IOQFPVGY.js";
|
|
256
|
+
import "./chunk-UZQCNOPS.js";
|
|
257
|
+
import "./chunk-ES36HTSC.js";
|
|
257
258
|
import "./chunk-3Y224NYC.js";
|
|
258
259
|
import "./chunk-H24WNPA2.js";
|
|
259
260
|
import "./chunk-BLAKS3CP.js";
|
|
260
261
|
import "./chunk-S2BBISHU.js";
|
|
261
|
-
import "./chunk-CYEPCZN5.js";
|
|
262
|
-
import "./chunk-ES36HTSC.js";
|
|
263
262
|
import "./chunk-W7IGLX4G.js";
|
|
264
263
|
import "./chunk-CINZGPSJ.js";
|
|
264
|
+
import "./chunk-CYEPCZN5.js";
|
|
265
265
|
import "./chunk-Y2ZD2RVG.js";
|
|
266
266
|
import "./chunk-LEPOP46W.js";
|
|
267
267
|
import "./chunk-72A4L5JJ.js";
|
|
@@ -381,9 +381,9 @@ import "./chunk-6MKAMLQL.js";
|
|
|
381
381
|
import "./chunk-JAKIDQB2.js";
|
|
382
382
|
import "./chunk-TBBDFYXW.js";
|
|
383
383
|
import "./chunk-ZBJMUXZH.js";
|
|
384
|
-
import "./chunk-
|
|
385
|
-
import "./chunk-UVYI6VIX.js";
|
|
384
|
+
import "./chunk-KQAFEZQX.js";
|
|
386
385
|
import "./chunk-WEHSQBFR.js";
|
|
386
|
+
import "./chunk-X7Y7WX73.js";
|
|
387
387
|
import "./chunk-J4EB7DNW.js";
|
|
388
388
|
import "./chunk-BJMBJZ2Y.js";
|
|
389
389
|
import "./chunk-UKJAGEXH.js";
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { OfflineSyncFileState } from '../offline-sync.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bootstrap reconciliation planner for two peer daemons whose corpora have
|
|
5
|
+
* already diverged (issue #2150).
|
|
6
|
+
*
|
|
7
|
+
* The offline-sync protocol assumes a satellite that shares a common base with
|
|
8
|
+
* one daemon: every path it does not know about is a pull, and a conflict is
|
|
9
|
+
* rare. Two long-lived daemons are the opposite case — each side holds months
|
|
10
|
+
* of history the other never saw, both sides are authoritative, and there is
|
|
11
|
+
* NO common base on the first run. That is a different decision problem, so it
|
|
12
|
+
* gets its own planner rather than another mode flag inside `applyOfflineSync*`.
|
|
13
|
+
*
|
|
14
|
+
* This module is deliberately pure: it takes two file censuses and returns what
|
|
15
|
+
* to do. No I/O, no transport, no clock. Everything that makes reconciliation
|
|
16
|
+
* risky — which side wins, what counts as converged, what is reported — is
|
|
17
|
+
* decided here where it can be exhaustively tested, and the transport layer is
|
|
18
|
+
* left to carry out an already-settled plan.
|
|
19
|
+
*/
|
|
20
|
+
/** Which way a path must move for the two corpora to agree. */
|
|
21
|
+
type ReconcileAction = "pull" | "push" | "identical" | "conflict" | "suppress";
|
|
22
|
+
/**
|
|
23
|
+
* How a path present on BOTH sides with different content is settled.
|
|
24
|
+
*
|
|
25
|
+
* `manual` is the safe default: on a bootstrap merge the two sides are equally
|
|
26
|
+
* authoritative, so silently picking one is data loss with extra steps. An
|
|
27
|
+
* operator opts into an automatic rule once they know the shape of their split.
|
|
28
|
+
*/
|
|
29
|
+
type ReconcileConflictPolicy = "manual" | "newest-wins" | "keep-both";
|
|
30
|
+
/**
|
|
31
|
+
* What the planner decided for a conflicting path.
|
|
32
|
+
*
|
|
33
|
+
* `keep-both` never overwrites: the older side is retained and linked as
|
|
34
|
+
* superseded by the newer one, which is the only resolution that cannot lose a
|
|
35
|
+
* fact neither corpus has seen.
|
|
36
|
+
*/
|
|
37
|
+
type ReconcileResolution = "local-wins" | "peer-wins" | "supersede-link" | "unresolved";
|
|
38
|
+
interface ReconcilePlanEntry {
|
|
39
|
+
path: string;
|
|
40
|
+
namespace: string;
|
|
41
|
+
action: ReconcileAction;
|
|
42
|
+
/** Stable machine-readable cause, safe to assert on and to aggregate. */
|
|
43
|
+
reason: ReconcileReason;
|
|
44
|
+
localSha256?: string;
|
|
45
|
+
peerSha256?: string;
|
|
46
|
+
/** Present only when a prior converged run left a cursor covering this path. */
|
|
47
|
+
baseSha256?: string;
|
|
48
|
+
/** Set only when `action` is `conflict`. */
|
|
49
|
+
resolution?: ReconcileResolution;
|
|
50
|
+
/**
|
|
51
|
+
* Which side holds the retracted revision. Set only when `action` is
|
|
52
|
+
* `suppress`: with different digests on each side and only one retracted,
|
|
53
|
+
* the entry would otherwise be identical either way and transport could
|
|
54
|
+
* delete the live copy instead of the retracted one.
|
|
55
|
+
*/
|
|
56
|
+
suppressSide?: "local" | "peer" | "both";
|
|
57
|
+
/**
|
|
58
|
+
* Which revision is newer, set only for a `supersede-link` resolution.
|
|
59
|
+
*
|
|
60
|
+
* The contract is that the older revision is linked as superseded by the
|
|
61
|
+
* newer one, so transport needs the direction. Absent when the timestamps
|
|
62
|
+
* cannot order the two - which is exactly when `newest-wins` degrades to
|
|
63
|
+
* `supersede-link` - and the link direction is then an operator decision.
|
|
64
|
+
*/
|
|
65
|
+
newerSide?: "local" | "peer";
|
|
66
|
+
}
|
|
67
|
+
type ReconcileReason = "peer_only" | "local_only"
|
|
68
|
+
/** Cursor showed only that side moved since agreement; both still hold the path. */
|
|
69
|
+
| "peer_changed" | "local_changed" | "same_content" | "both_modified" | "peer_deleted" | "local_deleted"
|
|
70
|
+
/** Peer deleted it while this side edited it — the offline-sync delete/modify pair. */
|
|
71
|
+
| "local_modified_peer_deleted" | "local_deleted_peer_modified" | "tombstoned";
|
|
72
|
+
interface ReconcileNamespaceReport {
|
|
73
|
+
namespace: string;
|
|
74
|
+
pull: number;
|
|
75
|
+
push: number;
|
|
76
|
+
identical: number;
|
|
77
|
+
conflict: number;
|
|
78
|
+
/** Local retractions the peer must be told about before the pair agrees. */
|
|
79
|
+
suppress: number;
|
|
80
|
+
/**
|
|
81
|
+
* Conflicts still needing an operator: those the policy declined to settle,
|
|
82
|
+
* plus supersede links whose direction could not be determined.
|
|
83
|
+
*/
|
|
84
|
+
unresolved: number;
|
|
85
|
+
}
|
|
86
|
+
interface ReconcilePlan {
|
|
87
|
+
entries: ReconcilePlanEntry[];
|
|
88
|
+
byNamespace: ReconcileNamespaceReport[];
|
|
89
|
+
/**
|
|
90
|
+
* True when the two corpora already agree — every shared path matches and
|
|
91
|
+
* neither side holds a path the other lacks.
|
|
92
|
+
*
|
|
93
|
+
* This is the idempotency contract from #2150: running reconciliation against
|
|
94
|
+
* an already-converged peer must be a no-op, and a caller can skip the whole
|
|
95
|
+
* transfer phase on this flag alone.
|
|
96
|
+
*/
|
|
97
|
+
converged: boolean;
|
|
98
|
+
}
|
|
99
|
+
/** Minimal shape the planner needs; `OfflineSyncFileState` satisfies it. */
|
|
100
|
+
type ReconcileFileState = Pick<OfflineSyncFileState, "path" | "sha256"> & Partial<Pick<OfflineSyncFileState, "mtimeMs" | "bytes">>;
|
|
101
|
+
interface ReconcileNamespaceInput {
|
|
102
|
+
namespace: string;
|
|
103
|
+
local: Iterable<ReconcileFileState>;
|
|
104
|
+
peer: Iterable<ReconcileFileState>;
|
|
105
|
+
/**
|
|
106
|
+
* File states agreed at the end of the last converged run with THIS peer.
|
|
107
|
+
* Absent on a bootstrap merge, which is why a path missing from one side is
|
|
108
|
+
* read as "never seen" rather than "deleted".
|
|
109
|
+
*/
|
|
110
|
+
base?: Iterable<ReconcileFileState>;
|
|
111
|
+
/**
|
|
112
|
+
* Digests of FILES this side has retracted, in the same form as
|
|
113
|
+
* `ReconcileFileState.sha256` — a hash of the serialized file.
|
|
114
|
+
*
|
|
115
|
+
* Deliberately NOT `TombstoneEntry.contentHash`, which hashes the canonical
|
|
116
|
+
* raw fact text and therefore never equals a file digest (§13: one content
|
|
117
|
+
* form, everywhere). Mapping retracted fact hashes onto the file digests that
|
|
118
|
+
* carry them is the caller's job, because only the caller can read its own
|
|
119
|
+
* corpus; handing this the wrong form would silently plan `pull` and
|
|
120
|
+
* resurrect every retracted fact, so the parameter name states the form.
|
|
121
|
+
*/
|
|
122
|
+
tombstonedFileSha256?: Iterable<string>;
|
|
123
|
+
/**
|
|
124
|
+
* Digests the PEER has retracted, same form.
|
|
125
|
+
*
|
|
126
|
+
* Without this a bootstrap merge cannot tell "the peer never had it" from
|
|
127
|
+
* "the peer deliberately retracted it": the peer census simply omits both,
|
|
128
|
+
* so a file we still hold is planned `push` and the peer's retraction is
|
|
129
|
+
* undone. Reconciliation is symmetric, so retraction has to be too.
|
|
130
|
+
*
|
|
131
|
+
* SCOPE: these sets decide what happens to files that still EXIST on one
|
|
132
|
+
* side. Sharing the retraction records themselves is not modelled here -
|
|
133
|
+
* tombstones are corpus files (`state/tombstones.jsonl`), so they reconcile
|
|
134
|
+
* as ordinary paths through this same plan. A digest both censuses have
|
|
135
|
+
* already dropped therefore produces no entry, by design: there is no file
|
|
136
|
+
* left to act on, and synthesizing a path-less entry would hand transport
|
|
137
|
+
* something it cannot apply.
|
|
138
|
+
*/
|
|
139
|
+
peerTombstonedFileSha256?: Iterable<string>;
|
|
140
|
+
}
|
|
141
|
+
interface ReconcileOptions {
|
|
142
|
+
conflictPolicy?: ReconcileConflictPolicy;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* A census the planner refuses to reason about.
|
|
146
|
+
*
|
|
147
|
+
* Dropping a malformed or contradictory record would let the planner return
|
|
148
|
+
* `converged: true` for a corpus it could not actually read, and transport is
|
|
149
|
+
* invited to skip everything on that flag — so bad input fails loudly instead
|
|
150
|
+
* (§1/§39).
|
|
151
|
+
*/
|
|
152
|
+
declare class ReconcilePlanInputError extends Error {
|
|
153
|
+
constructor(message: string);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Plan one namespace. Exposed for callers that stream namespaces one at a time.
|
|
157
|
+
*
|
|
158
|
+
* Residency is one peer index + a set of local paths + the entry list. The
|
|
159
|
+
* local census is consumed as a stream and never materialized, so a 100k-file
|
|
160
|
+
* corpus does not hold two full censuses at once — but this is NOT constant
|
|
161
|
+
* memory, and a caller holding its own census arrays adds to that.
|
|
162
|
+
*/
|
|
163
|
+
declare function planNamespaceReconciliation(input: ReconcileNamespaceInput, options?: ReconcileOptions): ReconcilePlanEntry[];
|
|
164
|
+
/** Aggregate entries into the per-namespace convergence report (#2150). */
|
|
165
|
+
declare function summarizeReconcilePlan(entries: readonly ReconcilePlanEntry[]): ReconcileNamespaceReport[];
|
|
166
|
+
/**
|
|
167
|
+
* Plan a full reconciliation across namespaces.
|
|
168
|
+
*
|
|
169
|
+
* `converged` is an affirmative claim that nothing needs to move, so it is
|
|
170
|
+
* derived from the entries rather than tracked alongside them: any action other
|
|
171
|
+
* than `identical` disproves it.
|
|
172
|
+
*/
|
|
173
|
+
declare function planReconciliation(namespaces: readonly ReconcileNamespaceInput[], options?: ReconcileOptions): ReconcilePlan;
|
|
174
|
+
|
|
175
|
+
export { type ReconcileAction, type ReconcileConflictPolicy, type ReconcileFileState, type ReconcileNamespaceInput, type ReconcileNamespaceReport, type ReconcileOptions, type ReconcilePlan, type ReconcilePlanEntry, ReconcilePlanInputError, type ReconcileReason, type ReconcileResolution, planNamespaceReconciliation, planReconciliation, summarizeReconcilePlan };
|