@remnic/core 9.66.5 → 9.66.6
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 +2 -2
- package/src/activity/timeline/analysis-batch-empty.test.ts +25 -0
- package/src/activity/timeline/analysis-batch-empty.ts +17 -0
- package/src/activity/vault-body-trim.test.ts +16 -0
- package/src/activity/vault-body-trim.ts +14 -0
- package/src/dedup/merge-unique.test.ts +18 -0
- package/src/dedup/merge-unique.ts +13 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.66.
|
|
3
|
+
"version": "9.66.6",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3217,7 +3217,7 @@
|
|
|
3217
3217
|
"core"
|
|
3218
3218
|
],
|
|
3219
3219
|
"peerDependencies": {
|
|
3220
|
-
"@remnic/coding-graph": "^9.66.
|
|
3220
|
+
"@remnic/coding-graph": "^9.66.6"
|
|
3221
3221
|
},
|
|
3222
3222
|
"peerDependenciesMeta": {
|
|
3223
3223
|
"@remnic/coding-graph": {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { isEmptyAnalysisBatches } from "./analysis-batch-empty.js";
|
|
5
|
+
|
|
6
|
+
test("null, undefined, and empty list are empty", () => {
|
|
7
|
+
assert.equal(isEmptyAnalysisBatches(null), true);
|
|
8
|
+
assert.equal(isEmptyAnalysisBatches(undefined), true);
|
|
9
|
+
assert.equal(isEmptyAnalysisBatches([]), true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("only empty inner batches are empty", () => {
|
|
13
|
+
assert.equal(isEmptyAnalysisBatches([[], []]), true);
|
|
14
|
+
assert.equal(isEmptyAnalysisBatches([null]), true);
|
|
15
|
+
assert.equal(isEmptyAnalysisBatches([undefined]), true);
|
|
16
|
+
assert.equal(isEmptyAnalysisBatches([null, []]), true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("a non-empty inner batch is not empty", () => {
|
|
20
|
+
assert.equal(isEmptyAnalysisBatches([[], [{ id: 1, capturedAtUtc: "2026-08-19T00:00:00.000Z" }]]), false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("non-array throws", () => {
|
|
24
|
+
assert.throws(() => isEmptyAnalysisBatches("batches"), /array/);
|
|
25
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Empty-batch guard for timeline analysis windows (issue #2050 leftover).
|
|
3
|
+
*
|
|
4
|
+
* null, undefined, and [] are empty. A non-array throws.
|
|
5
|
+
* A batch list containing only empty inner arrays is empty.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function isEmptyAnalysisBatches(batches: unknown): boolean {
|
|
9
|
+
if (batches == null) return true;
|
|
10
|
+
if (!Array.isArray(batches)) {
|
|
11
|
+
throw new TypeError("batches must be an array");
|
|
12
|
+
}
|
|
13
|
+
if (batches.length === 0) return true;
|
|
14
|
+
return batches.every(
|
|
15
|
+
(batch) => batch == null || (Array.isArray(batch) && batch.length === 0),
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { trimVaultRegionBody } from "./vault-body-trim.js";
|
|
5
|
+
|
|
6
|
+
test("trims leading and trailing blank lines", () => {
|
|
7
|
+
assert.equal(trimVaultRegionBody("\n\nhello\n\n"), "hello");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("preserves internal blank lines", () => {
|
|
11
|
+
assert.equal(trimVaultRegionBody("line one\n\nline two\n"), "line one\n\nline two");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("all blank becomes empty", () => {
|
|
15
|
+
assert.equal(trimVaultRegionBody("\n\n"), "");
|
|
16
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trim managed-region body text before vault publish (issue #1985 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Removes leading and trailing blank lines. Internal content is preserved.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export function trimVaultRegionBody(body: string): string {
|
|
8
|
+
const lines = body.split("\n");
|
|
9
|
+
let start = 0;
|
|
10
|
+
let end = lines.length;
|
|
11
|
+
while (start < end && lines[start]!.trim() === "") start++;
|
|
12
|
+
while (end > start && lines[end - 1]!.trim() === "") end--;
|
|
13
|
+
return lines.slice(start, end).join("\n");
|
|
14
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { uniqueMergeIds } from "./merge-unique.js";
|
|
5
|
+
|
|
6
|
+
test("empty list returns []", () => {
|
|
7
|
+
assert.deepEqual(uniqueMergeIds([]), []);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("drops empty strings and dedupes", () => {
|
|
11
|
+
assert.deepEqual(uniqueMergeIds(["beta", "", "alpha", "beta", ""]), ["alpha", "beta"]);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("does not mutate input", () => {
|
|
15
|
+
const ids = ["zeta", "", "alpha", "zeta"];
|
|
16
|
+
assert.deepEqual(uniqueMergeIds(ids), ["alpha", "zeta"]);
|
|
17
|
+
assert.deepEqual(ids, ["zeta", "", "alpha", "zeta"]);
|
|
18
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unique merge-id list (issue #2330 leftover).
|
|
3
|
+
*
|
|
4
|
+
* Drops empty strings, dedupes, sorts with localeCompare. Does not mutate input.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export function uniqueMergeIds(ids: readonly string[]): string[] {
|
|
8
|
+
const unique = new Set<string>();
|
|
9
|
+
for (const id of ids) {
|
|
10
|
+
if (id !== "") unique.add(id);
|
|
11
|
+
}
|
|
12
|
+
return [...unique].sort((a, b) => a.localeCompare(b));
|
|
13
|
+
}
|