@remit/mailbox-service 0.0.36 → 0.0.37
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/package.json +1 -1
- package/src/filters/match.test.ts +24 -4
- package/src/filters/match.ts +10 -6
package/package.json
CHANGED
|
@@ -228,14 +228,17 @@ describe("cosineSimilarity", () => {
|
|
|
228
228
|
});
|
|
229
229
|
|
|
230
230
|
describe("selectMoveWinner", () => {
|
|
231
|
-
const filter = (
|
|
232
|
-
|
|
231
|
+
const filter = (
|
|
232
|
+
filterId: string,
|
|
233
|
+
actionChangedAt: number,
|
|
234
|
+
ruleChangedAt = actionChangedAt,
|
|
235
|
+
): FilterItem => ({ filterId, actionChangedAt, ruleChangedAt }) as FilterItem;
|
|
233
236
|
|
|
234
237
|
it("returns undefined with no candidates", () => {
|
|
235
238
|
assert.equal(selectMoveWinner([]), undefined);
|
|
236
239
|
});
|
|
237
240
|
|
|
238
|
-
it("picks the most-recently-changed filter", () => {
|
|
241
|
+
it("picks the most-recently action-changed filter", () => {
|
|
239
242
|
const winner = selectMoveWinner([
|
|
240
243
|
filter("a", 100),
|
|
241
244
|
filter("b", 300),
|
|
@@ -244,7 +247,7 @@ describe("selectMoveWinner", () => {
|
|
|
244
247
|
assert.equal(winner?.filterId, "b");
|
|
245
248
|
});
|
|
246
249
|
|
|
247
|
-
it("tie-breaks on filterId when
|
|
250
|
+
it("tie-breaks on filterId when actionChangedAt is identical", () => {
|
|
248
251
|
const winner = selectMoveWinner([
|
|
249
252
|
filter("a", 100),
|
|
250
253
|
filter("c", 100),
|
|
@@ -252,6 +255,23 @@ describe("selectMoveWinner", () => {
|
|
|
252
255
|
]);
|
|
253
256
|
assert.equal(winner?.filterId, "c");
|
|
254
257
|
});
|
|
258
|
+
|
|
259
|
+
it("ignores a ruleChangedAt-only bump — extending scope/expiry alone must not promote a filter to move-winner (reader #384)", () => {
|
|
260
|
+
// filter A's predicate/action last changed at 10:00 (actionChangedAt).
|
|
261
|
+
// filter B was created at 09:00 and never had its predicate/action
|
|
262
|
+
// touched since, but a user extended its expiry at 11:00 — bumping only
|
|
263
|
+
// its ruleChangedAt (RFC 034 Decision 3.2 / #294), not what it matches or
|
|
264
|
+
// does. B must not out-rank A.
|
|
265
|
+
const filterA = filter("filter-a", 10_00);
|
|
266
|
+
const filterB = filter("filter-b", 9_00, 11_00);
|
|
267
|
+
|
|
268
|
+
const winner = selectMoveWinner([filterA, filterB]);
|
|
269
|
+
assert.equal(
|
|
270
|
+
winner?.filterId,
|
|
271
|
+
"filter-a",
|
|
272
|
+
"A still wins: its actionChangedAt (10:00) beats B's (09:00), even though B's ruleChangedAt (11:00) is later",
|
|
273
|
+
);
|
|
274
|
+
});
|
|
255
275
|
});
|
|
256
276
|
|
|
257
277
|
describe("buildMatchText", () => {
|
package/src/filters/match.ts
CHANGED
|
@@ -134,10 +134,14 @@ export const cosineSimilarity = (
|
|
|
134
134
|
};
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
* The move a message ends in when several filters matched: the
|
|
138
|
-
* *changed*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
137
|
+
* The move a message ends in when several filters matched: the filter whose
|
|
138
|
+
* predicate or action was most recently *changed* wins (RFC 034 Decision 3.2),
|
|
139
|
+
* tie-broken on `filterId` for the unreachable identical-timestamp case.
|
|
140
|
+
* `actionChangedAt` — not `ruleChangedAt` — is the signal: `ruleChangedAt` also
|
|
141
|
+
* bumps on a scope/expiry-only edit (reader #266), which changes a filter's
|
|
142
|
+
* lifecycle, not what it matches or does, and must not reorder exclusive-move
|
|
143
|
+
* precedence (reader #384). Nor is it `updatedAt`, so a cosmetic rename never
|
|
144
|
+
* flips an exclusive move either.
|
|
141
145
|
*/
|
|
142
146
|
export const selectMoveWinner = (
|
|
143
147
|
candidates: readonly FilterItem[],
|
|
@@ -148,12 +152,12 @@ export const selectMoveWinner = (
|
|
|
148
152
|
winner = candidate;
|
|
149
153
|
continue;
|
|
150
154
|
}
|
|
151
|
-
if (candidate.
|
|
155
|
+
if (candidate.actionChangedAt > winner.actionChangedAt) {
|
|
152
156
|
winner = candidate;
|
|
153
157
|
continue;
|
|
154
158
|
}
|
|
155
159
|
if (
|
|
156
|
-
candidate.
|
|
160
|
+
candidate.actionChangedAt === winner.actionChangedAt &&
|
|
157
161
|
candidate.filterId > winner.filterId
|
|
158
162
|
) {
|
|
159
163
|
winner = candidate;
|