@jpkme/diff-review 0.1.12 → 0.1.13
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/README.md +1 -1
- package/lib/acp-policy.mjs +99 -12
- package/lib/acp-policy.test.mjs +56 -3
- package/lib/acp-shell.mjs +38 -8
- package/lib/acp-shell.test.mjs +32 -1
- package/lib/agent-login.mjs +105 -105
- package/lib/check-report.mjs +1 -0
- package/lib/check-report.test.mjs +1 -0
- package/lib/extract-cache.test.mjs +162 -162
- package/lib/model-label.mjs +263 -263
- package/lib/model-label.test.mjs +77 -77
- package/lib/models-cache.mjs +75 -75
- package/lib/models-cache.test.mjs +50 -50
- package/lib/review-prep.mjs +63 -63
- package/package.json +1 -1
- package/web/build/client/_app/immutable/assets/{0.CLQiq3Ed.css → 0.BKRG1f36.css} +1 -1
- package/web/build/client/_app/immutable/assets/0.BKRG1f36.css.br +0 -0
- package/web/build/client/_app/immutable/assets/{0.CLQiq3Ed.css.gz → 0.BKRG1f36.css.gz} +0 -0
- package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css +1 -0
- package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css.br +0 -0
- package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/3.BT54aVKb.css +1 -0
- package/web/build/client/_app/immutable/assets/3.BT54aVKb.css.br +0 -0
- package/web/build/client/_app/immutable/assets/3.BT54aVKb.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css +1 -0
- package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css.br +0 -0
- package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css.gz +0 -0
- package/web/build/client/_app/immutable/chunks/BXUWMim4.js +213 -0
- package/web/build/client/_app/immutable/chunks/BXUWMim4.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/BXUWMim4.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/{CPyWH418.js → Bu1mm6Oz.js} +1 -1
- package/web/build/client/_app/immutable/chunks/Bu1mm6Oz.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/Bu1mm6Oz.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/{B5ByWcPE.js → DPfXzQnm.js} +2 -2
- package/web/build/client/_app/immutable/chunks/DPfXzQnm.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/DPfXzQnm.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/{app.BiBohpyO.js → app.CTgiuiU1.js} +2 -2
- package/web/build/client/_app/immutable/entry/app.CTgiuiU1.js.br +0 -0
- package/web/build/client/_app/immutable/entry/app.CTgiuiU1.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/start.CFSl0kht.js +1 -0
- package/web/build/client/_app/immutable/entry/start.CFSl0kht.js.br +0 -0
- package/web/build/client/_app/immutable/entry/start.CFSl0kht.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/{1.BzPXaJJj.js → 1.0PQZpSbJ.js} +1 -1
- package/web/build/client/_app/immutable/nodes/1.0PQZpSbJ.js.br +2 -0
- package/web/build/client/_app/immutable/nodes/1.0PQZpSbJ.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js +10 -0
- package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/3.AciugOtL.js +171 -0
- package/web/build/client/_app/immutable/nodes/3.AciugOtL.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/3.AciugOtL.js.gz +0 -0
- package/web/build/client/_app/version.json +1 -1
- package/web/build/client/_app/version.json.br +0 -0
- package/web/build/client/_app/version.json.gz +0 -0
- package/web/build/handler.js +3 -3
- package/web/build/index.js +3 -3
- package/web/build/server/chunks/{0-BYok4D0n.js → 0-DUStDOsr.js} +3 -3
- package/web/build/server/chunks/{0-BYok4D0n.js.map → 0-DUStDOsr.js.map} +1 -1
- package/web/build/server/chunks/1-C2qlInYk.js +7 -0
- package/web/build/server/chunks/{1-C7zcB0q0.js.map → 1-C2qlInYk.js.map} +1 -1
- package/web/build/server/chunks/2-DyE177MK.js +7 -0
- package/web/build/server/chunks/2-DyE177MK.js.map +1 -0
- package/web/build/server/chunks/3-SO3atuWO.js +7 -0
- package/web/build/server/chunks/{3-DAAmG6VX.js.map → 3-SO3atuWO.js.map} +1 -1
- package/web/build/server/chunks/{_server.ts-qYVrMYPB.js → _server.ts-CRNhzL2a.js} +3 -3
- package/web/build/server/chunks/{_server.ts-qYVrMYPB.js.map → _server.ts-CRNhzL2a.js.map} +1 -1
- package/web/build/server/chunks/{agent-sessions-DSqGavSn.js → agent-sessions-kcUaLhK5.js} +171 -40
- package/web/build/server/chunks/agent-sessions-kcUaLhK5.js.map +1 -0
- package/web/build/server/chunks/{git-review-CpO_G8z8.js → git-review-CXKcjYgZ.js} +2 -2
- package/web/build/server/chunks/{git-review-CpO_G8z8.js.map → git-review-CXKcjYgZ.js.map} +1 -1
- package/web/build/server/chunks/{handler-Di1wJQuU.js → handler-_E0NucKN.js} +3 -3
- package/web/build/server/chunks/{handler-Di1wJQuU.js.map → handler-_E0NucKN.js.map} +1 -1
- package/web/build/server/chunks/{hooks.server-BLOHobEK.js → hooks.server-D7yPODoc.js} +2 -2
- package/web/build/server/chunks/{hooks.server-BLOHobEK.js.map → hooks.server-D7yPODoc.js.map} +1 -1
- package/web/build/server/chunks/{index.js-yLYmrAWy.js → index.js-lMtDM8ZQ.js} +3 -3
- package/web/build/server/chunks/{index.js-yLYmrAWy.js.map → index.js-lMtDM8ZQ.js.map} +1 -1
- package/web/build/server/chunks/{manifest.js-CXj8IIo3.js → manifest.js-BIm6jot5.js} +9 -9
- package/web/build/server/chunks/{manifest.js-CXj8IIo3.js.map → manifest.js-BIm6jot5.js.map} +1 -1
- package/web/build/server/chunks/{remote-1g4ayag-BiJeU0Pk.js → remote-1g4ayag-DmqxwUIz.js} +3 -3
- package/web/build/server/chunks/{remote-1g4ayag-BiJeU0Pk.js.map → remote-1g4ayag-DmqxwUIz.js.map} +1 -1
- package/web/build/server/chunks/{remote-wh6t6j-CHanXurm.js → remote-wh6t6j-DZk0W9Pp.js} +4 -4
- package/web/build/server/chunks/{remote-wh6t6j-CHanXurm.js.map → remote-wh6t6j-DZk0W9Pp.js.map} +1 -1
- package/web/build/client/_app/immutable/assets/0.CLQiq3Ed.css.br +0 -0
- package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css +0 -1
- package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css.br +0 -0
- package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css +0 -1
- package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css.br +0 -0
- package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css +0 -1
- package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css.br +0 -0
- package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css.gz +0 -0
- package/web/build/client/_app/immutable/chunks/B5ByWcPE.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/B5ByWcPE.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/CPyWH418.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/CPyWH418.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/NwkMsx0h.js +0 -210
- package/web/build/client/_app/immutable/chunks/NwkMsx0h.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/NwkMsx0h.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/app.BiBohpyO.js.br +0 -0
- package/web/build/client/_app/immutable/entry/app.BiBohpyO.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js +0 -1
- package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js.br +0 -0
- package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/1.BzPXaJJj.js.br +0 -2
- package/web/build/client/_app/immutable/nodes/1.BzPXaJJj.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js +0 -10
- package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js +0 -171
- package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js.gz +0 -0
- package/web/build/server/chunks/1-C7zcB0q0.js +0 -7
- package/web/build/server/chunks/2-v6ejI_0-.js +0 -7
- package/web/build/server/chunks/2-v6ejI_0-.js.map +0 -1
- package/web/build/server/chunks/3-DAAmG6VX.js +0 -7
- package/web/build/server/chunks/agent-sessions-DSqGavSn.js.map +0 -1
- /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js → 0.Dj97JW46.js} +0 -0
- /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js.br → 0.Dj97JW46.js.br} +0 -0
- /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js.gz → 0.Dj97JW46.js.gz} +0 -0
|
@@ -1,162 +1,162 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { afterEach, test } from "node:test";
|
|
6
|
-
import { extractBranchDiff, parseGitDiffFiles } from "./extract.mjs";
|
|
7
|
-
import { OUTPUT_DIR } from "./output-name.mjs";
|
|
8
|
-
import { companionPaths, ensureReviewDir, writeDiffText } from "./review-dir.mjs";
|
|
9
|
-
import { checkReportFile } from "./check-report.mjs";
|
|
10
|
-
|
|
11
|
-
const sample = [
|
|
12
|
-
"diff --git a/src/a.ts b/src/a.ts",
|
|
13
|
-
"index 111..222 100644",
|
|
14
|
-
"--- a/src/a.ts",
|
|
15
|
-
"+++ b/src/a.ts",
|
|
16
|
-
"@@ -1,2 +1,3 @@",
|
|
17
|
-
" keep",
|
|
18
|
-
"-old",
|
|
19
|
-
"+new",
|
|
20
|
-
"+extra",
|
|
21
|
-
"diff --git a/package-lock.json b/package-lock.json",
|
|
22
|
-
"index 1..2 100644",
|
|
23
|
-
"--- a/package-lock.json",
|
|
24
|
-
"+++ b/package-lock.json",
|
|
25
|
-
"@@ -1 +1 @@",
|
|
26
|
-
"-{}",
|
|
27
|
-
"+{ }",
|
|
28
|
-
"diff --git a/old.ts b/new.ts",
|
|
29
|
-
"similarity index 90%",
|
|
30
|
-
"rename from old.ts",
|
|
31
|
-
"rename to new.ts",
|
|
32
|
-
"index 1..2 100644",
|
|
33
|
-
"--- a/old.ts",
|
|
34
|
-
"+++ b/new.ts",
|
|
35
|
-
"@@ -1 +1 @@",
|
|
36
|
-
"-x",
|
|
37
|
-
"+y",
|
|
38
|
-
].join("\n");
|
|
39
|
-
|
|
40
|
-
const dirs = [];
|
|
41
|
-
afterEach(() => {
|
|
42
|
-
for (const d of dirs.splice(0)) {
|
|
43
|
-
try {
|
|
44
|
-
rmSync(d, { recursive: true, force: true });
|
|
45
|
-
} catch {
|
|
46
|
-
/* ignore */
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("parseGitDiffFiles splits paths and change types", () => {
|
|
52
|
-
const files = parseGitDiffFiles(sample);
|
|
53
|
-
assert.equal(files.length, 3);
|
|
54
|
-
assert.equal(files[0].path, "src/a.ts");
|
|
55
|
-
assert.equal(files[0].changeType, "modified");
|
|
56
|
-
assert.match(files[0].hunkDiff, /^@@/);
|
|
57
|
-
assert.equal(files[1].path, "package-lock.json");
|
|
58
|
-
assert.equal(files[2].changeType, "renamed");
|
|
59
|
-
assert.equal(files[2].path, "new.ts");
|
|
60
|
-
assert.equal(files[2].oldPath, "old.ts");
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("extractBranchDiff with cachedDiff applies DEFAULT_IGNORE", () => {
|
|
64
|
-
const repo = mkdtempSync(join(tmpdir(), "diff-review-cache-"));
|
|
65
|
-
dirs.push(repo);
|
|
66
|
-
mkdirSync(join(repo, "src"), { recursive: true });
|
|
67
|
-
// repo path only used for config/guidelines; no git needed when cachedDiff is set
|
|
68
|
-
const skeleton = extractBranchDiff({
|
|
69
|
-
repo,
|
|
70
|
-
branch: "feature",
|
|
71
|
-
base: "develop",
|
|
72
|
-
cachedDiff: sample,
|
|
73
|
-
});
|
|
74
|
-
assert.deepEqual(
|
|
75
|
-
skeleton.files.map((f) => f.path).sort(),
|
|
76
|
-
["new.ts", "src/a.ts"]
|
|
77
|
-
);
|
|
78
|
-
assert.ok(skeleton.context.ignored.includes("package-lock.json"));
|
|
79
|
-
assert.match(skeleton.files.find((f) => f.path === "src/a.ts").diff, /^@@/);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test("checkReportFile reuses companion .diff paths without inventing coverage", () => {
|
|
83
|
-
const repo = mkdtempSync(join(tmpdir(), "diff-review-check-"));
|
|
84
|
-
dirs.push(repo);
|
|
85
|
-
ensureReviewDir(repo);
|
|
86
|
-
const filename = "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json";
|
|
87
|
-
writeDiffText(repo, filename, sample);
|
|
88
|
-
const payload = {
|
|
89
|
-
meta: {
|
|
90
|
-
agent: "Cursor",
|
|
91
|
-
model: "composer",
|
|
92
|
-
repo,
|
|
93
|
-
branch: "feature",
|
|
94
|
-
base: "develop",
|
|
95
|
-
},
|
|
96
|
-
intent: "Cambia src/a.ts y renombra old.ts para dejar el módulo listo en la rama.",
|
|
97
|
-
groups: [{ id: "g1", kind: "feat", title: "Ajuste", intent: "base" }],
|
|
98
|
-
blocks: [
|
|
99
|
-
{
|
|
100
|
-
id: "b1",
|
|
101
|
-
group: "g1",
|
|
102
|
-
file: "src/a.ts",
|
|
103
|
-
lines: "L1-3",
|
|
104
|
-
op: "mod",
|
|
105
|
-
what: "cambia la lógica",
|
|
106
|
-
why: "hace falta",
|
|
107
|
-
source: "code",
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
id: "b2",
|
|
111
|
-
group: "g1",
|
|
112
|
-
file: "new.ts",
|
|
113
|
-
lines: "L1",
|
|
114
|
-
op: "rename",
|
|
115
|
-
what: "renombra el módulo",
|
|
116
|
-
why: "nombre más claro",
|
|
117
|
-
source: "code",
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
findings: [],
|
|
121
|
-
skipped: [{ file: "package-lock.json", reason: "lockfile" }],
|
|
122
|
-
};
|
|
123
|
-
const jsonPath = companionPaths(repo, filename).json;
|
|
124
|
-
writeFileSync(jsonPath, JSON.stringify(payload));
|
|
125
|
-
// Sin git: loadBranchDiff lee el .diff y aplica ignore (lockfile fuera de paths).
|
|
126
|
-
const result = checkReportFile(jsonPath, { repo, branch: "feature", base: "develop" });
|
|
127
|
-
assert.equal(result.ok, true, result.errors.join("; "));
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
test("buildPrompt with precomputed context skips merge-base rediscovery", async () => {
|
|
131
|
-
const { buildPrompt } = await import("./prompt.mjs");
|
|
132
|
-
const text = buildPrompt(
|
|
133
|
-
{ source: "local", repo: "/tmp/r", branch: "feat", base: "develop" },
|
|
134
|
-
{
|
|
135
|
-
outputFilename: "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json",
|
|
136
|
-
diffRelPath: ".diff-review/diff-rev_aaaaaaaaaa_bbbbbbbbbb.diff",
|
|
137
|
-
mergeBase: "abc123",
|
|
138
|
-
branchSha: "def456",
|
|
139
|
-
baseSha: "789abc",
|
|
140
|
-
files: [{ path: "src/a.ts", changeType: "modified" }],
|
|
141
|
-
ignored: ["package-lock.json"],
|
|
142
|
-
ignoreGlobs: ["**/package-lock.json"],
|
|
143
|
-
}
|
|
144
|
-
);
|
|
145
|
-
assert.match(text, /Precomputed git context/);
|
|
146
|
-
assert.match(text, /diff-rev_aaaaaaaaaa_bbbbbbbbbb\.diff/);
|
|
147
|
-
assert.match(text, /Merge-base SHA: `abc123`/);
|
|
148
|
-
assert.match(text, /modified: src\/a\.ts/);
|
|
149
|
-
assert.doesNotMatch(text, /Resolve the merge-base/);
|
|
150
|
-
assert.doesNotMatch(text, /Run exactly: `git diff/);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("buildPrompt acp omits validate CLI", async () => {
|
|
154
|
-
const { buildPrompt, validateCliCommand } = await import("./prompt.mjs");
|
|
155
|
-
const filename = "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json";
|
|
156
|
-
const text = buildPrompt(
|
|
157
|
-
{ source: "local", repo: "/tmp/r", branch: "feat", base: "develop" },
|
|
158
|
-
{ outputFilename: filename, acp: true, diffRelPath: `.${OUTPUT_DIR}/${filename.replace(/\.json$/, ".diff")}` }
|
|
159
|
-
);
|
|
160
|
-
assert.doesNotMatch(text, new RegExp(validateCliCommand(filename).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
|
161
|
-
assert.match(text, /host validates/i);
|
|
162
|
-
});
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { afterEach, test } from "node:test";
|
|
6
|
+
import { extractBranchDiff, parseGitDiffFiles } from "./extract.mjs";
|
|
7
|
+
import { OUTPUT_DIR } from "./output-name.mjs";
|
|
8
|
+
import { companionPaths, ensureReviewDir, writeDiffText } from "./review-dir.mjs";
|
|
9
|
+
import { checkReportFile } from "./check-report.mjs";
|
|
10
|
+
|
|
11
|
+
const sample = [
|
|
12
|
+
"diff --git a/src/a.ts b/src/a.ts",
|
|
13
|
+
"index 111..222 100644",
|
|
14
|
+
"--- a/src/a.ts",
|
|
15
|
+
"+++ b/src/a.ts",
|
|
16
|
+
"@@ -1,2 +1,3 @@",
|
|
17
|
+
" keep",
|
|
18
|
+
"-old",
|
|
19
|
+
"+new",
|
|
20
|
+
"+extra",
|
|
21
|
+
"diff --git a/package-lock.json b/package-lock.json",
|
|
22
|
+
"index 1..2 100644",
|
|
23
|
+
"--- a/package-lock.json",
|
|
24
|
+
"+++ b/package-lock.json",
|
|
25
|
+
"@@ -1 +1 @@",
|
|
26
|
+
"-{}",
|
|
27
|
+
"+{ }",
|
|
28
|
+
"diff --git a/old.ts b/new.ts",
|
|
29
|
+
"similarity index 90%",
|
|
30
|
+
"rename from old.ts",
|
|
31
|
+
"rename to new.ts",
|
|
32
|
+
"index 1..2 100644",
|
|
33
|
+
"--- a/old.ts",
|
|
34
|
+
"+++ b/new.ts",
|
|
35
|
+
"@@ -1 +1 @@",
|
|
36
|
+
"-x",
|
|
37
|
+
"+y",
|
|
38
|
+
].join("\n");
|
|
39
|
+
|
|
40
|
+
const dirs = [];
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
for (const d of dirs.splice(0)) {
|
|
43
|
+
try {
|
|
44
|
+
rmSync(d, { recursive: true, force: true });
|
|
45
|
+
} catch {
|
|
46
|
+
/* ignore */
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("parseGitDiffFiles splits paths and change types", () => {
|
|
52
|
+
const files = parseGitDiffFiles(sample);
|
|
53
|
+
assert.equal(files.length, 3);
|
|
54
|
+
assert.equal(files[0].path, "src/a.ts");
|
|
55
|
+
assert.equal(files[0].changeType, "modified");
|
|
56
|
+
assert.match(files[0].hunkDiff, /^@@/);
|
|
57
|
+
assert.equal(files[1].path, "package-lock.json");
|
|
58
|
+
assert.equal(files[2].changeType, "renamed");
|
|
59
|
+
assert.equal(files[2].path, "new.ts");
|
|
60
|
+
assert.equal(files[2].oldPath, "old.ts");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("extractBranchDiff with cachedDiff applies DEFAULT_IGNORE", () => {
|
|
64
|
+
const repo = mkdtempSync(join(tmpdir(), "diff-review-cache-"));
|
|
65
|
+
dirs.push(repo);
|
|
66
|
+
mkdirSync(join(repo, "src"), { recursive: true });
|
|
67
|
+
// repo path only used for config/guidelines; no git needed when cachedDiff is set
|
|
68
|
+
const skeleton = extractBranchDiff({
|
|
69
|
+
repo,
|
|
70
|
+
branch: "feature",
|
|
71
|
+
base: "develop",
|
|
72
|
+
cachedDiff: sample,
|
|
73
|
+
});
|
|
74
|
+
assert.deepEqual(
|
|
75
|
+
skeleton.files.map((f) => f.path).sort(),
|
|
76
|
+
["new.ts", "src/a.ts"]
|
|
77
|
+
);
|
|
78
|
+
assert.ok(skeleton.context.ignored.includes("package-lock.json"));
|
|
79
|
+
assert.match(skeleton.files.find((f) => f.path === "src/a.ts").diff, /^@@/);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("checkReportFile reuses companion .diff paths without inventing coverage", () => {
|
|
83
|
+
const repo = mkdtempSync(join(tmpdir(), "diff-review-check-"));
|
|
84
|
+
dirs.push(repo);
|
|
85
|
+
ensureReviewDir(repo);
|
|
86
|
+
const filename = "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json";
|
|
87
|
+
writeDiffText(repo, filename, sample);
|
|
88
|
+
const payload = {
|
|
89
|
+
meta: {
|
|
90
|
+
agent: "Cursor",
|
|
91
|
+
model: "composer",
|
|
92
|
+
repo,
|
|
93
|
+
branch: "feature",
|
|
94
|
+
base: "develop",
|
|
95
|
+
},
|
|
96
|
+
intent: "Cambia src/a.ts y renombra old.ts para dejar el módulo listo en la rama.",
|
|
97
|
+
groups: [{ id: "g1", kind: "feat", title: "Ajuste", intent: "base" }],
|
|
98
|
+
blocks: [
|
|
99
|
+
{
|
|
100
|
+
id: "b1",
|
|
101
|
+
group: "g1",
|
|
102
|
+
file: "src/a.ts",
|
|
103
|
+
lines: "L1-3",
|
|
104
|
+
op: "mod",
|
|
105
|
+
what: "cambia la lógica",
|
|
106
|
+
why: "hace falta",
|
|
107
|
+
source: "code",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "b2",
|
|
111
|
+
group: "g1",
|
|
112
|
+
file: "new.ts",
|
|
113
|
+
lines: "L1",
|
|
114
|
+
op: "rename",
|
|
115
|
+
what: "renombra el módulo",
|
|
116
|
+
why: "nombre más claro",
|
|
117
|
+
source: "code",
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
findings: [],
|
|
121
|
+
skipped: [{ file: "package-lock.json", reason: "lockfile" }],
|
|
122
|
+
};
|
|
123
|
+
const jsonPath = companionPaths(repo, filename).json;
|
|
124
|
+
writeFileSync(jsonPath, JSON.stringify(payload));
|
|
125
|
+
// Sin git: loadBranchDiff lee el .diff y aplica ignore (lockfile fuera de paths).
|
|
126
|
+
const result = checkReportFile(jsonPath, { repo, branch: "feature", base: "develop" });
|
|
127
|
+
assert.equal(result.ok, true, result.errors.join("; "));
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("buildPrompt with precomputed context skips merge-base rediscovery", async () => {
|
|
131
|
+
const { buildPrompt } = await import("./prompt.mjs");
|
|
132
|
+
const text = buildPrompt(
|
|
133
|
+
{ source: "local", repo: "/tmp/r", branch: "feat", base: "develop" },
|
|
134
|
+
{
|
|
135
|
+
outputFilename: "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json",
|
|
136
|
+
diffRelPath: ".diff-review/diff-rev_aaaaaaaaaa_bbbbbbbbbb.diff",
|
|
137
|
+
mergeBase: "abc123",
|
|
138
|
+
branchSha: "def456",
|
|
139
|
+
baseSha: "789abc",
|
|
140
|
+
files: [{ path: "src/a.ts", changeType: "modified" }],
|
|
141
|
+
ignored: ["package-lock.json"],
|
|
142
|
+
ignoreGlobs: ["**/package-lock.json"],
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
assert.match(text, /Precomputed git context/);
|
|
146
|
+
assert.match(text, /diff-rev_aaaaaaaaaa_bbbbbbbbbb\.diff/);
|
|
147
|
+
assert.match(text, /Merge-base SHA: `abc123`/);
|
|
148
|
+
assert.match(text, /modified: src\/a\.ts/);
|
|
149
|
+
assert.doesNotMatch(text, /Resolve the merge-base/);
|
|
150
|
+
assert.doesNotMatch(text, /Run exactly: `git diff/);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("buildPrompt acp omits validate CLI", async () => {
|
|
154
|
+
const { buildPrompt, validateCliCommand } = await import("./prompt.mjs");
|
|
155
|
+
const filename = "diff-rev_aaaaaaaaaa_bbbbbbbbbb.json";
|
|
156
|
+
const text = buildPrompt(
|
|
157
|
+
{ source: "local", repo: "/tmp/r", branch: "feat", base: "develop" },
|
|
158
|
+
{ outputFilename: filename, acp: true, diffRelPath: `.${OUTPUT_DIR}/${filename.replace(/\.json$/, ".diff")}` }
|
|
159
|
+
);
|
|
160
|
+
assert.doesNotMatch(text, new RegExp(validateCliCommand(filename).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
|
161
|
+
assert.match(text, /host validates/i);
|
|
162
|
+
});
|