@modusensus/dsh-mneme 0.6.7 → 0.6.9
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/.github/workflows/test.yml +32 -0
- package/.release-notes-v0.6.9.md +13 -0
- package/CHANGELOG.md +89 -0
- package/LICENSE +21 -21
- package/README.md +219 -463
- package/SECURITY.md +544 -0
- package/docs/devlog/2026-08-14-dsh-mneme-dev-log.md +247 -0
- package/docs/devlog/2026-08-15-dsh-mneme-audit-stress-dev-log.md +145 -0
- package/docs/devlog/2026-08-15-dsh-mneme-pipeline-dev-log.md +56 -0
- package/docs/devlog/2026-08-15-dsh-mneme-reflection-dev-log.md +77 -0
- package/docs/devlog/2026-08-15-dsh-mneme-review-fixes-dev-log.md +64 -0
- package/docs/devlog/2026-08-15-dsh-mneme-semantic-dev-log.md +90 -0
- package/dsh-mneme/CHANGELOG.md +248 -0
- package/dsh-mneme/LICENSE +21 -0
- package/dsh-mneme/README.md +465 -0
- package/{cordis.patch.yml → dsh-mneme/cordis.patch.yml} +15 -15
- package/dsh-mneme/docs/AGENT_MEMORY_RESEARCH.md +183 -0
- package/dsh-mneme/docs/ENTITIES.md +245 -0
- package/dsh-mneme/docs/LOCAL_MODEL.md +141 -0
- package/dsh-mneme/docs/MIGRATION.md +127 -0
- package/dsh-mneme/docs/SEMANTIC.md +256 -0
- package/dsh-mneme/docs/SLEEP.md +163 -0
- package/{lib → dsh-mneme/lib}/api.js +783 -783
- package/{lib → dsh-mneme/lib}/client.js +1757 -1757
- package/{src → dsh-mneme/lib}/commands.js +64 -64
- package/{lib → dsh-mneme/lib}/config.js +298 -288
- package/{lib → dsh-mneme/lib}/dream/clustering.js +118 -118
- package/{src → dsh-mneme/lib}/dream/decisions.js +488 -439
- package/{lib → dsh-mneme/lib}/dream/sleep.js +561 -554
- package/{src → dsh-mneme/lib}/dream/tag-extractor.js +156 -156
- package/{lib → dsh-mneme/lib}/dream.js +958 -929
- package/{src → dsh-mneme/lib}/embedding.js +154 -154
- package/{src → dsh-mneme/lib}/entities/extractor.js +242 -242
- package/{src → dsh-mneme/lib}/hot-memory.js +53 -53
- package/{lib → dsh-mneme/lib}/index.js +361 -361
- package/{src → dsh-mneme/lib}/inject.js +208 -208
- package/{lib → dsh-mneme/lib}/local-embedder.js +282 -282
- package/{lib → dsh-mneme/lib}/mirror.js +170 -170
- package/{lib → dsh-mneme/lib}/parser/tag.js +59 -59
- package/{lib → dsh-mneme/lib}/parser/wiki-link.js +38 -38
- package/{src → dsh-mneme/lib}/quality-filter.js +123 -123
- package/{lib → dsh-mneme/lib}/reranker.js +218 -218
- package/{lib → dsh-mneme/lib}/search/adaptive.js +22 -22
- package/{lib → dsh-mneme/lib}/search/bm25.js +96 -96
- package/{src → dsh-mneme/lib}/search/tag-boost.js +61 -61
- package/{src → dsh-mneme/lib}/service.js +1726 -1726
- package/{lib → dsh-mneme/lib}/settings.js +172 -172
- package/{lib → dsh-mneme/lib}/store.js +2238 -2238
- package/{lib → dsh-mneme/lib}/summarize.js +236 -236
- package/{lib → dsh-mneme/lib}/tools.js +290 -290
- package/{lib → dsh-mneme/lib}/vector-index.js +116 -116
- package/dsh-mneme/package-lock.json +1936 -0
- package/dsh-mneme/package.json +80 -0
- package/{scripts → dsh-mneme/scripts}/benchmark-embed.js +201 -201
- package/{scripts → dsh-mneme/scripts}/benchmark-recall.js +133 -133
- package/{scripts → dsh-mneme/scripts}/benchmark-rerank.js +166 -166
- package/{scripts → dsh-mneme/scripts}/e2e-dsh.js +218 -218
- package/{scripts → dsh-mneme/scripts}/stress-dsh.js +255 -255
- package/{scripts → dsh-mneme/scripts}/sync-lib.js +52 -52
- package/{src → dsh-mneme/src}/api.js +783 -783
- package/{lib → dsh-mneme/src}/commands.js +64 -64
- package/{src → dsh-mneme/src}/config.js +298 -288
- package/{src → dsh-mneme/src}/dream/clustering.js +118 -118
- package/{lib → dsh-mneme/src}/dream/decisions.js +488 -439
- package/{src → dsh-mneme/src}/dream/sleep.js +561 -554
- package/{lib → dsh-mneme/src}/dream/tag-extractor.js +156 -156
- package/{src → dsh-mneme/src}/dream.js +958 -929
- package/{lib → dsh-mneme/src}/embedding.js +154 -154
- package/{lib → dsh-mneme/src}/entities/extractor.js +242 -242
- package/{lib → dsh-mneme/src}/hot-memory.js +53 -53
- package/{src → dsh-mneme/src}/index.js +361 -361
- package/{lib → dsh-mneme/src}/inject.js +208 -208
- package/{src → dsh-mneme/src}/local-embedder.js +282 -282
- package/{src → dsh-mneme/src}/mirror.js +170 -170
- package/{src → dsh-mneme/src}/parser/tag.js +59 -59
- package/{src → dsh-mneme/src}/parser/wiki-link.js +38 -38
- package/{lib → dsh-mneme/src}/quality-filter.js +123 -123
- package/{src → dsh-mneme/src}/reranker.js +218 -218
- package/{src → dsh-mneme/src}/search/adaptive.js +22 -22
- package/{src → dsh-mneme/src}/search/bm25.js +96 -96
- package/{lib → dsh-mneme/src}/search/tag-boost.js +61 -61
- package/{lib → dsh-mneme/src}/service.js +1726 -1726
- package/{src → dsh-mneme/src}/settings.js +172 -172
- package/{src → dsh-mneme/src}/store.js +2238 -2238
- package/{src → dsh-mneme/src}/summarize.js +236 -236
- package/{src → dsh-mneme/src}/tools.js +290 -290
- package/{src → dsh-mneme/src}/vector-index.js +116 -116
- package/{test → dsh-mneme/test}/api.test.js +594 -594
- package/{test → dsh-mneme/test}/audit.test.js +448 -448
- package/{test → dsh-mneme/test}/benchmark.test.js +35 -35
- package/{test → dsh-mneme/test}/boundary-v0625.test.js +82 -82
- package/{test → dsh-mneme/test}/client.test.js +368 -368
- package/{test → dsh-mneme/test}/clustering.test.js +100 -100
- package/{test → dsh-mneme/test}/commands.test.js +69 -69
- package/{test → dsh-mneme/test}/config.test.js +50 -50
- package/{test → dsh-mneme/test}/conflict-freeze.test.js +290 -290
- package/{test → dsh-mneme/test}/directory.test.js +134 -134
- package/{test → dsh-mneme/test}/dream.test.js +1060 -901
- package/{test → dsh-mneme/test}/entities.test.js +522 -522
- package/{test → dsh-mneme/test}/epistemic.test.js +298 -298
- package/{test → dsh-mneme/test}/fnew-0112.test.js +311 -311
- package/{test → dsh-mneme/test}/fnew-03.test.js +422 -422
- package/{test → dsh-mneme/test}/graph-api.test.js +175 -175
- package/{test → dsh-mneme/test}/helpers/dream-mock.js +82 -82
- package/{test → dsh-mneme/test}/hot-memory.test.js +174 -174
- package/{test → dsh-mneme/test}/inject.test.js +103 -103
- package/{test → dsh-mneme/test}/llm-audit.test.js +279 -279
- package/{test → dsh-mneme/test}/local-embedder.test.js +227 -227
- package/{test → dsh-mneme/test}/mirror-dirty.test.js +424 -424
- package/{test → dsh-mneme/test}/mirror-edit-digest.test.js +187 -187
- package/{test → dsh-mneme/test}/mirror-generation.test.js +499 -499
- package/{test → dsh-mneme/test}/mirror.test.js +249 -249
- package/{test → dsh-mneme/test}/normalize-decisions.test.js +120 -120
- package/{test → dsh-mneme/test}/peer-blockers.test.js +190 -190
- package/{test → dsh-mneme/test}/policy-epoch.test.js +259 -259
- package/{test → dsh-mneme/test}/provenance.test.js +103 -103
- package/{test → dsh-mneme/test}/quality-filter.test.js +118 -118
- package/{test → dsh-mneme/test}/reasoning-effort.test.js +199 -199
- package/{test → dsh-mneme/test}/recall-evals.test.js +235 -235
- package/{test → dsh-mneme/test}/recall-layer.test.js +315 -315
- package/{test → dsh-mneme/test}/receipt-chain.test.js +451 -451
- package/{test → dsh-mneme/test}/reflection.test.js +226 -226
- package/{test → dsh-mneme/test}/reranker.test.js +240 -240
- package/{test → dsh-mneme/test}/search-fusion.test.js +90 -90
- package/{test → dsh-mneme/test}/semantic.test.js +124 -124
- package/{test → dsh-mneme/test}/service-search.test.js +199 -199
- package/{test → dsh-mneme/test}/service.test.js +435 -435
- package/{test → dsh-mneme/test}/settings.test.js +118 -118
- package/{test → dsh-mneme/test}/sleep.test.js +365 -365
- package/{test → dsh-mneme/test}/store.test.js +436 -436
- package/{test → dsh-mneme/test}/stress.test.js +209 -209
- package/{test → dsh-mneme/test}/summarize.test.js +191 -191
- package/{test → dsh-mneme/test}/tag-boost.test.js +125 -125
- package/{test → dsh-mneme/test}/tag.test.js +312 -312
- package/{test → dsh-mneme/test}/tools.test.js +285 -285
- package/{test → dsh-mneme/test}/vector-index.test.js +221 -221
- package/{test → dsh-mneme/test}/wiki-link.test.js +332 -332
- package/package.json +18 -40
- package//346/250/252/345/271/205.png +0 -0
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createStore } from "../src/store.js";
|
|
4
|
-
import { createSettings } from "../src/settings.js";
|
|
5
|
-
|
|
6
|
-
function setup() {
|
|
7
|
-
const store = createStore(":memory:");
|
|
8
|
-
const settings = createSettings(store.db);
|
|
9
|
-
return { store, settings };
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
test("profile defaults to empty and round-trips", () => {
|
|
13
|
-
const { store, settings } = setup();
|
|
14
|
-
assert.equal(settings.getProfile(), "");
|
|
15
|
-
settings.setProfile("我是后端工程师,偏好简洁代码");
|
|
16
|
-
assert.equal(settings.getProfile(), "我是后端工程师,偏好简洁代码");
|
|
17
|
-
settings.setProfile("");
|
|
18
|
-
assert.equal(settings.getProfile(), "");
|
|
19
|
-
store.close();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test("rules default to empty list and round-trip", () => {
|
|
23
|
-
const { store, settings } = setup();
|
|
24
|
-
assert.deepEqual(settings.getRules(), []);
|
|
25
|
-
settings.setRules(["规则一", "规则二"]);
|
|
26
|
-
assert.deepEqual(settings.getRules(), ["规则一", "规则二"]);
|
|
27
|
-
settings.setRules([]);
|
|
28
|
-
assert.deepEqual(settings.getRules(), []);
|
|
29
|
-
store.close();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("rules filters non-string entries", () => {
|
|
33
|
-
const { store, settings } = setup();
|
|
34
|
-
settings.setRules(["ok", 42, null, "also-ok"]);
|
|
35
|
-
assert.deepEqual(settings.getRules(), ["ok", "also-ok"]);
|
|
36
|
-
store.close();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("addCommand stores and lists sorted by name", () => {
|
|
40
|
-
const { store, settings } = setup();
|
|
41
|
-
settings.addCommand({ name: "banner", description: "b", instruction: "打印横幅" });
|
|
42
|
-
settings.addCommand({ name: "agenda", instruction: "列出今日议程" });
|
|
43
|
-
const list = settings.listCommands();
|
|
44
|
-
assert.equal(list.length, 2);
|
|
45
|
-
assert.deepEqual(list.map((c) => c.name), ["agenda", "banner"]);
|
|
46
|
-
assert.ok(list[1].id, "has id");
|
|
47
|
-
store.close();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("addCommand replaces existing name", () => {
|
|
51
|
-
const { store, settings } = setup();
|
|
52
|
-
settings.addCommand({ name: "fmt", instruction: "旧指令" });
|
|
53
|
-
const updated = settings.addCommand({ name: "fmt", instruction: "新指令" });
|
|
54
|
-
assert.equal(updated.instruction, "新指令");
|
|
55
|
-
assert.equal(settings.listCommands().length, 1);
|
|
56
|
-
store.close();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("addCommand rejects invalid names and empty instructions", () => {
|
|
60
|
-
const { store, settings } = setup();
|
|
61
|
-
assert.throws(() => settings.addCommand({ name: "Bad Name", instruction: "x" }), /command name/);
|
|
62
|
-
assert.throws(() => settings.addCommand({ name: "123abc", instruction: "x" }), /command name/);
|
|
63
|
-
assert.throws(() => settings.addCommand({ name: "ok", instruction: " " }), /instruction/);
|
|
64
|
-
assert.equal(settings.listCommands().length, 0);
|
|
65
|
-
store.close();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("removeCommand removes by id and returns false for missing", () => {
|
|
69
|
-
const { store, settings } = setup();
|
|
70
|
-
const { id } = settings.addCommand({ name: "tmp", instruction: "x" });
|
|
71
|
-
assert.equal(settings.removeCommand(id), true);
|
|
72
|
-
assert.equal(settings.removeCommand(id), false);
|
|
73
|
-
assert.equal(settings.listCommands().length, 0);
|
|
74
|
-
store.close();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("vector config defaults to undefined and round-trips", () => {
|
|
78
|
-
const { store, settings } = setup();
|
|
79
|
-
assert.equal(settings.getVectorConfig(), undefined);
|
|
80
|
-
const saved = settings.setVectorConfig({
|
|
81
|
-
enabled: true,
|
|
82
|
-
baseUrl: " https://api.openai.com/v1/ ",
|
|
83
|
-
apiKey: " sk-123 ",
|
|
84
|
-
model: "text-embedding-3-small"
|
|
85
|
-
});
|
|
86
|
-
assert.equal(saved.enabled, true);
|
|
87
|
-
assert.equal(saved.baseUrl, "https://api.openai.com/v1", "trims baseUrl");
|
|
88
|
-
assert.equal(saved.apiKey, "sk-123", "trims apiKey");
|
|
89
|
-
assert.equal(saved.model, "text-embedding-3-small");
|
|
90
|
-
const read = settings.getVectorConfig();
|
|
91
|
-
assert.equal(read.enabled, true);
|
|
92
|
-
assert.equal(read.model, "text-embedding-3-small");
|
|
93
|
-
store.close();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("vector config disabled value is stored as false", () => {
|
|
97
|
-
const { store, settings } = setup();
|
|
98
|
-
settings.setVectorConfig({ enabled: false, baseUrl: "x", apiKey: "k", model: "m" });
|
|
99
|
-
assert.equal(settings.getVectorConfig().enabled, false);
|
|
100
|
-
store.close();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test("autoTag config defaults to disabled and round-trips", () => {
|
|
104
|
-
const { store, settings } = setup();
|
|
105
|
-
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: false, manualTagEnabled: false });
|
|
106
|
-
settings.setAutoTagConfig({ autoTagEnabled: true, manualTagEnabled: true });
|
|
107
|
-
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: true, manualTagEnabled: true });
|
|
108
|
-
settings.setAutoTagConfig({ autoTagEnabled: false });
|
|
109
|
-
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: false, manualTagEnabled: true });
|
|
110
|
-
store.close();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("autoTag config coerces non-boolean to false", () => {
|
|
114
|
-
const { store, settings } = setup();
|
|
115
|
-
settings.setAutoTagConfig({ autoTagEnabled: "yes", manualTagEnabled: 1 });
|
|
116
|
-
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: false, manualTagEnabled: false });
|
|
117
|
-
store.close();
|
|
118
|
-
});
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { createStore } from "../src/store.js";
|
|
4
|
+
import { createSettings } from "../src/settings.js";
|
|
5
|
+
|
|
6
|
+
function setup() {
|
|
7
|
+
const store = createStore(":memory:");
|
|
8
|
+
const settings = createSettings(store.db);
|
|
9
|
+
return { store, settings };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
test("profile defaults to empty and round-trips", () => {
|
|
13
|
+
const { store, settings } = setup();
|
|
14
|
+
assert.equal(settings.getProfile(), "");
|
|
15
|
+
settings.setProfile("我是后端工程师,偏好简洁代码");
|
|
16
|
+
assert.equal(settings.getProfile(), "我是后端工程师,偏好简洁代码");
|
|
17
|
+
settings.setProfile("");
|
|
18
|
+
assert.equal(settings.getProfile(), "");
|
|
19
|
+
store.close();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("rules default to empty list and round-trip", () => {
|
|
23
|
+
const { store, settings } = setup();
|
|
24
|
+
assert.deepEqual(settings.getRules(), []);
|
|
25
|
+
settings.setRules(["规则一", "规则二"]);
|
|
26
|
+
assert.deepEqual(settings.getRules(), ["规则一", "规则二"]);
|
|
27
|
+
settings.setRules([]);
|
|
28
|
+
assert.deepEqual(settings.getRules(), []);
|
|
29
|
+
store.close();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("rules filters non-string entries", () => {
|
|
33
|
+
const { store, settings } = setup();
|
|
34
|
+
settings.setRules(["ok", 42, null, "also-ok"]);
|
|
35
|
+
assert.deepEqual(settings.getRules(), ["ok", "also-ok"]);
|
|
36
|
+
store.close();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("addCommand stores and lists sorted by name", () => {
|
|
40
|
+
const { store, settings } = setup();
|
|
41
|
+
settings.addCommand({ name: "banner", description: "b", instruction: "打印横幅" });
|
|
42
|
+
settings.addCommand({ name: "agenda", instruction: "列出今日议程" });
|
|
43
|
+
const list = settings.listCommands();
|
|
44
|
+
assert.equal(list.length, 2);
|
|
45
|
+
assert.deepEqual(list.map((c) => c.name), ["agenda", "banner"]);
|
|
46
|
+
assert.ok(list[1].id, "has id");
|
|
47
|
+
store.close();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("addCommand replaces existing name", () => {
|
|
51
|
+
const { store, settings } = setup();
|
|
52
|
+
settings.addCommand({ name: "fmt", instruction: "旧指令" });
|
|
53
|
+
const updated = settings.addCommand({ name: "fmt", instruction: "新指令" });
|
|
54
|
+
assert.equal(updated.instruction, "新指令");
|
|
55
|
+
assert.equal(settings.listCommands().length, 1);
|
|
56
|
+
store.close();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("addCommand rejects invalid names and empty instructions", () => {
|
|
60
|
+
const { store, settings } = setup();
|
|
61
|
+
assert.throws(() => settings.addCommand({ name: "Bad Name", instruction: "x" }), /command name/);
|
|
62
|
+
assert.throws(() => settings.addCommand({ name: "123abc", instruction: "x" }), /command name/);
|
|
63
|
+
assert.throws(() => settings.addCommand({ name: "ok", instruction: " " }), /instruction/);
|
|
64
|
+
assert.equal(settings.listCommands().length, 0);
|
|
65
|
+
store.close();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("removeCommand removes by id and returns false for missing", () => {
|
|
69
|
+
const { store, settings } = setup();
|
|
70
|
+
const { id } = settings.addCommand({ name: "tmp", instruction: "x" });
|
|
71
|
+
assert.equal(settings.removeCommand(id), true);
|
|
72
|
+
assert.equal(settings.removeCommand(id), false);
|
|
73
|
+
assert.equal(settings.listCommands().length, 0);
|
|
74
|
+
store.close();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("vector config defaults to undefined and round-trips", () => {
|
|
78
|
+
const { store, settings } = setup();
|
|
79
|
+
assert.equal(settings.getVectorConfig(), undefined);
|
|
80
|
+
const saved = settings.setVectorConfig({
|
|
81
|
+
enabled: true,
|
|
82
|
+
baseUrl: " https://api.openai.com/v1/ ",
|
|
83
|
+
apiKey: " sk-123 ",
|
|
84
|
+
model: "text-embedding-3-small"
|
|
85
|
+
});
|
|
86
|
+
assert.equal(saved.enabled, true);
|
|
87
|
+
assert.equal(saved.baseUrl, "https://api.openai.com/v1", "trims baseUrl");
|
|
88
|
+
assert.equal(saved.apiKey, "sk-123", "trims apiKey");
|
|
89
|
+
assert.equal(saved.model, "text-embedding-3-small");
|
|
90
|
+
const read = settings.getVectorConfig();
|
|
91
|
+
assert.equal(read.enabled, true);
|
|
92
|
+
assert.equal(read.model, "text-embedding-3-small");
|
|
93
|
+
store.close();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("vector config disabled value is stored as false", () => {
|
|
97
|
+
const { store, settings } = setup();
|
|
98
|
+
settings.setVectorConfig({ enabled: false, baseUrl: "x", apiKey: "k", model: "m" });
|
|
99
|
+
assert.equal(settings.getVectorConfig().enabled, false);
|
|
100
|
+
store.close();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("autoTag config defaults to disabled and round-trips", () => {
|
|
104
|
+
const { store, settings } = setup();
|
|
105
|
+
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: false, manualTagEnabled: false });
|
|
106
|
+
settings.setAutoTagConfig({ autoTagEnabled: true, manualTagEnabled: true });
|
|
107
|
+
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: true, manualTagEnabled: true });
|
|
108
|
+
settings.setAutoTagConfig({ autoTagEnabled: false });
|
|
109
|
+
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: false, manualTagEnabled: true });
|
|
110
|
+
store.close();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("autoTag config coerces non-boolean to false", () => {
|
|
114
|
+
const { store, settings } = setup();
|
|
115
|
+
settings.setAutoTagConfig({ autoTagEnabled: "yes", manualTagEnabled: 1 });
|
|
116
|
+
assert.deepEqual(settings.getAutoTagConfig(), { autoTagEnabled: false, manualTagEnabled: false });
|
|
117
|
+
store.close();
|
|
118
|
+
});
|