@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.
Files changed (120) hide show
  1. package/README.md +1 -1
  2. package/lib/acp-policy.mjs +99 -12
  3. package/lib/acp-policy.test.mjs +56 -3
  4. package/lib/acp-shell.mjs +38 -8
  5. package/lib/acp-shell.test.mjs +32 -1
  6. package/lib/agent-login.mjs +105 -105
  7. package/lib/check-report.mjs +1 -0
  8. package/lib/check-report.test.mjs +1 -0
  9. package/lib/extract-cache.test.mjs +162 -162
  10. package/lib/model-label.mjs +263 -263
  11. package/lib/model-label.test.mjs +77 -77
  12. package/lib/models-cache.mjs +75 -75
  13. package/lib/models-cache.test.mjs +50 -50
  14. package/lib/review-prep.mjs +63 -63
  15. package/package.json +1 -1
  16. package/web/build/client/_app/immutable/assets/{0.CLQiq3Ed.css → 0.BKRG1f36.css} +1 -1
  17. package/web/build/client/_app/immutable/assets/0.BKRG1f36.css.br +0 -0
  18. package/web/build/client/_app/immutable/assets/{0.CLQiq3Ed.css.gz → 0.BKRG1f36.css.gz} +0 -0
  19. package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css +1 -0
  20. package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css.br +0 -0
  21. package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css.gz +0 -0
  22. package/web/build/client/_app/immutable/assets/3.BT54aVKb.css +1 -0
  23. package/web/build/client/_app/immutable/assets/3.BT54aVKb.css.br +0 -0
  24. package/web/build/client/_app/immutable/assets/3.BT54aVKb.css.gz +0 -0
  25. package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css +1 -0
  26. package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css.br +0 -0
  27. package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css.gz +0 -0
  28. package/web/build/client/_app/immutable/chunks/BXUWMim4.js +213 -0
  29. package/web/build/client/_app/immutable/chunks/BXUWMim4.js.br +0 -0
  30. package/web/build/client/_app/immutable/chunks/BXUWMim4.js.gz +0 -0
  31. package/web/build/client/_app/immutable/chunks/{CPyWH418.js → Bu1mm6Oz.js} +1 -1
  32. package/web/build/client/_app/immutable/chunks/Bu1mm6Oz.js.br +0 -0
  33. package/web/build/client/_app/immutable/chunks/Bu1mm6Oz.js.gz +0 -0
  34. package/web/build/client/_app/immutable/chunks/{B5ByWcPE.js → DPfXzQnm.js} +2 -2
  35. package/web/build/client/_app/immutable/chunks/DPfXzQnm.js.br +0 -0
  36. package/web/build/client/_app/immutable/chunks/DPfXzQnm.js.gz +0 -0
  37. package/web/build/client/_app/immutable/entry/{app.BiBohpyO.js → app.CTgiuiU1.js} +2 -2
  38. package/web/build/client/_app/immutable/entry/app.CTgiuiU1.js.br +0 -0
  39. package/web/build/client/_app/immutable/entry/app.CTgiuiU1.js.gz +0 -0
  40. package/web/build/client/_app/immutable/entry/start.CFSl0kht.js +1 -0
  41. package/web/build/client/_app/immutable/entry/start.CFSl0kht.js.br +0 -0
  42. package/web/build/client/_app/immutable/entry/start.CFSl0kht.js.gz +0 -0
  43. package/web/build/client/_app/immutable/nodes/{1.BzPXaJJj.js → 1.0PQZpSbJ.js} +1 -1
  44. package/web/build/client/_app/immutable/nodes/1.0PQZpSbJ.js.br +2 -0
  45. package/web/build/client/_app/immutable/nodes/1.0PQZpSbJ.js.gz +0 -0
  46. package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js +10 -0
  47. package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js.br +0 -0
  48. package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js.gz +0 -0
  49. package/web/build/client/_app/immutable/nodes/3.AciugOtL.js +171 -0
  50. package/web/build/client/_app/immutable/nodes/3.AciugOtL.js.br +0 -0
  51. package/web/build/client/_app/immutable/nodes/3.AciugOtL.js.gz +0 -0
  52. package/web/build/client/_app/version.json +1 -1
  53. package/web/build/client/_app/version.json.br +0 -0
  54. package/web/build/client/_app/version.json.gz +0 -0
  55. package/web/build/handler.js +3 -3
  56. package/web/build/index.js +3 -3
  57. package/web/build/server/chunks/{0-BYok4D0n.js → 0-DUStDOsr.js} +3 -3
  58. package/web/build/server/chunks/{0-BYok4D0n.js.map → 0-DUStDOsr.js.map} +1 -1
  59. package/web/build/server/chunks/1-C2qlInYk.js +7 -0
  60. package/web/build/server/chunks/{1-C7zcB0q0.js.map → 1-C2qlInYk.js.map} +1 -1
  61. package/web/build/server/chunks/2-DyE177MK.js +7 -0
  62. package/web/build/server/chunks/2-DyE177MK.js.map +1 -0
  63. package/web/build/server/chunks/3-SO3atuWO.js +7 -0
  64. package/web/build/server/chunks/{3-DAAmG6VX.js.map → 3-SO3atuWO.js.map} +1 -1
  65. package/web/build/server/chunks/{_server.ts-qYVrMYPB.js → _server.ts-CRNhzL2a.js} +3 -3
  66. package/web/build/server/chunks/{_server.ts-qYVrMYPB.js.map → _server.ts-CRNhzL2a.js.map} +1 -1
  67. package/web/build/server/chunks/{agent-sessions-DSqGavSn.js → agent-sessions-kcUaLhK5.js} +171 -40
  68. package/web/build/server/chunks/agent-sessions-kcUaLhK5.js.map +1 -0
  69. package/web/build/server/chunks/{git-review-CpO_G8z8.js → git-review-CXKcjYgZ.js} +2 -2
  70. package/web/build/server/chunks/{git-review-CpO_G8z8.js.map → git-review-CXKcjYgZ.js.map} +1 -1
  71. package/web/build/server/chunks/{handler-Di1wJQuU.js → handler-_E0NucKN.js} +3 -3
  72. package/web/build/server/chunks/{handler-Di1wJQuU.js.map → handler-_E0NucKN.js.map} +1 -1
  73. package/web/build/server/chunks/{hooks.server-BLOHobEK.js → hooks.server-D7yPODoc.js} +2 -2
  74. package/web/build/server/chunks/{hooks.server-BLOHobEK.js.map → hooks.server-D7yPODoc.js.map} +1 -1
  75. package/web/build/server/chunks/{index.js-yLYmrAWy.js → index.js-lMtDM8ZQ.js} +3 -3
  76. package/web/build/server/chunks/{index.js-yLYmrAWy.js.map → index.js-lMtDM8ZQ.js.map} +1 -1
  77. package/web/build/server/chunks/{manifest.js-CXj8IIo3.js → manifest.js-BIm6jot5.js} +9 -9
  78. package/web/build/server/chunks/{manifest.js-CXj8IIo3.js.map → manifest.js-BIm6jot5.js.map} +1 -1
  79. package/web/build/server/chunks/{remote-1g4ayag-BiJeU0Pk.js → remote-1g4ayag-DmqxwUIz.js} +3 -3
  80. package/web/build/server/chunks/{remote-1g4ayag-BiJeU0Pk.js.map → remote-1g4ayag-DmqxwUIz.js.map} +1 -1
  81. package/web/build/server/chunks/{remote-wh6t6j-CHanXurm.js → remote-wh6t6j-DZk0W9Pp.js} +4 -4
  82. package/web/build/server/chunks/{remote-wh6t6j-CHanXurm.js.map → remote-wh6t6j-DZk0W9Pp.js.map} +1 -1
  83. package/web/build/client/_app/immutable/assets/0.CLQiq3Ed.css.br +0 -0
  84. package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css +0 -1
  85. package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css.br +0 -0
  86. package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css.gz +0 -0
  87. package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css +0 -1
  88. package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css.br +0 -0
  89. package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css.gz +0 -0
  90. package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css +0 -1
  91. package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css.br +0 -0
  92. package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css.gz +0 -0
  93. package/web/build/client/_app/immutable/chunks/B5ByWcPE.js.br +0 -0
  94. package/web/build/client/_app/immutable/chunks/B5ByWcPE.js.gz +0 -0
  95. package/web/build/client/_app/immutable/chunks/CPyWH418.js.br +0 -0
  96. package/web/build/client/_app/immutable/chunks/CPyWH418.js.gz +0 -0
  97. package/web/build/client/_app/immutable/chunks/NwkMsx0h.js +0 -210
  98. package/web/build/client/_app/immutable/chunks/NwkMsx0h.js.br +0 -0
  99. package/web/build/client/_app/immutable/chunks/NwkMsx0h.js.gz +0 -0
  100. package/web/build/client/_app/immutable/entry/app.BiBohpyO.js.br +0 -0
  101. package/web/build/client/_app/immutable/entry/app.BiBohpyO.js.gz +0 -0
  102. package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js +0 -1
  103. package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js.br +0 -0
  104. package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js.gz +0 -0
  105. package/web/build/client/_app/immutable/nodes/1.BzPXaJJj.js.br +0 -2
  106. package/web/build/client/_app/immutable/nodes/1.BzPXaJJj.js.gz +0 -0
  107. package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js +0 -10
  108. package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js.br +0 -0
  109. package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js.gz +0 -0
  110. package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js +0 -171
  111. package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js.br +0 -0
  112. package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js.gz +0 -0
  113. package/web/build/server/chunks/1-C7zcB0q0.js +0 -7
  114. package/web/build/server/chunks/2-v6ejI_0-.js +0 -7
  115. package/web/build/server/chunks/2-v6ejI_0-.js.map +0 -1
  116. package/web/build/server/chunks/3-DAAmG6VX.js +0 -7
  117. package/web/build/server/chunks/agent-sessions-DSqGavSn.js.map +0 -1
  118. /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js → 0.Dj97JW46.js} +0 -0
  119. /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js.br → 0.Dj97JW46.js.br} +0 -0
  120. /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
+ });