@rce-mcp/retrieval-core 0.1.2 → 0.1.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.
@@ -70,14 +70,18 @@ describe("runRemoteDeltaSync", () => {
70
70
  expect(Object.keys(result.next_files)).toEqual(["src/keep.ts"]);
71
71
  });
72
72
 
73
- it("maps .mjs and .cjs files to javascript language metadata during scans", async () => {
73
+ it("maps .mjs/.cjs to javascript and .mts/.cts to typescript language metadata during scans", async () => {
74
74
  const root = await createProject();
75
75
  await writeFile(join(root, "src", "runtime.mjs"), "export const runtime = true;\n");
76
76
  await writeFile(join(root, "src", "loader.cjs"), "module.exports = { loader: true };\n");
77
+ await writeFile(join(root, "src", "types.mts"), "export const typed = true as const;\n");
78
+ await writeFile(join(root, "src", "legacy.cts"), "export = { typed: true };\n");
77
79
 
78
80
  const stats = await collectProjectFileStats(root);
79
81
  expect(stats.get("src/runtime.mjs")?.language).toBe("javascript");
80
82
  expect(stats.get("src/loader.cjs")?.language).toBe("javascript");
83
+ expect(stats.get("src/types.mts")?.language).toBe("typescript");
84
+ expect(stats.get("src/legacy.cts")?.language).toBe("typescript");
81
85
  });
82
86
 
83
87
  it("applies add/modify/delete changes incrementally", async () => {
@@ -0,0 +1,86 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ __applySmartCutoffCandidatesForTests,
4
+ mergeRetrievalScoringConfig,
5
+ resolveRetrievalScoringProfile
6
+ } from "../src/index.js";
7
+
8
+ function sampleCandidates(scores: number[]) {
9
+ return scores.map((score, index) => ({
10
+ path: `src/candidate-${index + 1}.ts`,
11
+ start_line: index * 10 + 1,
12
+ end_line: index * 10 + 5,
13
+ snippet: `export const candidate${index + 1} = ${score};`,
14
+ score,
15
+ reason: "semantic match" as const
16
+ }));
17
+ }
18
+
19
+ describe("retrieval smart cutoff", () => {
20
+ it("applies delta and ratio guards after the safe-harbor minimum", () => {
21
+ const baseline = resolveRetrievalScoringProfile("baseline");
22
+ const config = mergeRetrievalScoringConfig(baseline.config, {
23
+ rerank: {
24
+ smart_cutoff_enabled: true,
25
+ smart_cutoff_min_k: 2,
26
+ smart_cutoff_max_k: 8,
27
+ smart_cutoff_min_score: 0.25,
28
+ smart_cutoff_top_ratio: 0.5,
29
+ smart_cutoff_delta_abs: 0.2
30
+ }
31
+ }).rerank;
32
+
33
+ const output = __applySmartCutoffCandidatesForTests({
34
+ config,
35
+ candidates: sampleCandidates([0.92, 0.88, 0.56, 0.55, 0.41])
36
+ });
37
+
38
+ expect(output).toHaveLength(2);
39
+ expect(output[0]?.score).toBe(0.92);
40
+ expect(output[1]?.score).toBe(0.88);
41
+ });
42
+
43
+ it("keeps at least min_k results even when score floors are not met", () => {
44
+ const baseline = resolveRetrievalScoringProfile("baseline");
45
+ const config = mergeRetrievalScoringConfig(baseline.config, {
46
+ rerank: {
47
+ smart_cutoff_enabled: true,
48
+ smart_cutoff_min_k: 2,
49
+ smart_cutoff_max_k: 8,
50
+ smart_cutoff_min_score: 0.8,
51
+ smart_cutoff_top_ratio: 0.95,
52
+ smart_cutoff_delta_abs: 0.01
53
+ }
54
+ }).rerank;
55
+
56
+ const output = __applySmartCutoffCandidatesForTests({
57
+ config,
58
+ candidates: sampleCandidates([0.91, 0.31, 0.3, 0.29])
59
+ });
60
+
61
+ expect(output).toHaveLength(2);
62
+ expect(output[0]?.score).toBe(0.91);
63
+ expect(output[1]?.score).toBe(0.31);
64
+ });
65
+
66
+ it("rejects invalid smart cutoff ranges in scoring config", () => {
67
+ const baseline = resolveRetrievalScoringProfile("baseline");
68
+
69
+ expect(() =>
70
+ mergeRetrievalScoringConfig(baseline.config, {
71
+ rerank: {
72
+ smart_cutoff_min_k: 3,
73
+ smart_cutoff_max_k: 2
74
+ }
75
+ })
76
+ ).toThrow(/smart_cutoff_max_k must be >= smart_cutoff_min_k/);
77
+
78
+ expect(() =>
79
+ mergeRetrievalScoringConfig(baseline.config, {
80
+ rerank: {
81
+ smart_cutoff_top_ratio: 0
82
+ }
83
+ })
84
+ ).toThrow(/smart_cutoff_top_ratio must be in \(0, 1\]/);
85
+ });
86
+ });
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ DEFAULT_RETRIEVAL_SNIPPET_INTEGRITY_CONFIG,
4
+ mergeRetrievalSnippetIntegrityConfig
5
+ } from "../src/index.js";
6
+
7
+ describe("retrieval-core snippet integrity config validation", () => {
8
+ it("uses dark-launch defaults", () => {
9
+ expect(DEFAULT_RETRIEVAL_SNIPPET_INTEGRITY_CONFIG).toMatchObject({
10
+ enabled: false,
11
+ target_languages: ["typescript", "tsx", "javascript", "jsx"],
12
+ max_contiguous_gap_lines: 6,
13
+ marker_template_version: "v1",
14
+ repair_enabled: false,
15
+ repair_max_envelope_lines: 260,
16
+ repair_max_snippet_chars: 3600
17
+ });
18
+ });
19
+
20
+ it("accepts valid overrides and normalizes aliases", () => {
21
+ const merged = mergeRetrievalSnippetIntegrityConfig(DEFAULT_RETRIEVAL_SNIPPET_INTEGRITY_CONFIG, {
22
+ enabled: true,
23
+ target_languages: ["ts", "js", "tsx"],
24
+ max_contiguous_gap_lines: 10,
25
+ repair_enabled: true,
26
+ repair_max_envelope_lines: 400,
27
+ repair_max_snippet_chars: 4200
28
+ });
29
+ expect(merged.enabled).toBe(true);
30
+ expect(merged.target_languages).toEqual(["typescript", "javascript", "tsx"]);
31
+ expect(merged.max_contiguous_gap_lines).toBe(10);
32
+ expect(merged.marker_template_version).toBe("v1");
33
+ expect(merged.repair_enabled).toBe(true);
34
+ expect(merged.repair_max_envelope_lines).toBe(400);
35
+ expect(merged.repair_max_snippet_chars).toBe(4200);
36
+ });
37
+
38
+ it("rejects unsupported target languages", () => {
39
+ expect(() =>
40
+ mergeRetrievalSnippetIntegrityConfig(DEFAULT_RETRIEVAL_SNIPPET_INTEGRITY_CONFIG, {
41
+ target_languages: ["python"]
42
+ })
43
+ ).toThrow(/unsupported target language/);
44
+ });
45
+
46
+ it("rejects invalid repair caps", () => {
47
+ expect(() =>
48
+ mergeRetrievalSnippetIntegrityConfig(DEFAULT_RETRIEVAL_SNIPPET_INTEGRITY_CONFIG, {
49
+ repair_max_envelope_lines: 0
50
+ })
51
+ ).toThrow(/repair_max_envelope_lines must be a positive integer/);
52
+
53
+ expect(() =>
54
+ mergeRetrievalSnippetIntegrityConfig(DEFAULT_RETRIEVAL_SNIPPET_INTEGRITY_CONFIG, {
55
+ repair_max_snippet_chars: -1
56
+ })
57
+ ).toThrow(/repair_max_snippet_chars must be a positive integer/);
58
+ });
59
+ });