MCPcopy Create free account
hub / github.com/ReviewStage/stage-cli / validateHunkCoverage

Function validateHunkCoverage

packages/cli/src/show.ts:122–190  ·  view source on GitHub ↗
(
	filteredFiles: { path: string; hunks: { oldStart: number }[] }[],
	chapters: Chapter[],
)

Source from the content-addressed store, hash-verified

120}
121
122function validateHunkCoverage(
123 filteredFiles: { path: string; hunks: { oldStart: number }[] }[],
124 chapters: Chapter[],
125): void {
126 const expected = new Map<string, Set<number>>();
127 for (const file of filteredFiles) {
128 const starts = new Set<number>();
129 for (const hunk of file.hunks) {
130 starts.add(hunk.oldStart);
131 }
132 if (starts.size > 0) {
133 expected.set(file.path, starts);
134 }
135 }
136
137 const actual = new Map<string, Map<number, number>>();
138 const duplicates: string[] = [];
139 for (const chapter of chapters) {
140 for (const ref of chapter.hunkRefs) {
141 let starts = actual.get(ref.filePath);
142 if (!starts) {
143 starts = new Map();
144 actual.set(ref.filePath, starts);
145 }
146 const count = starts.get(ref.oldStart) ?? 0;
147 if (count > 0) {
148 duplicates.push(` filePath: "${ref.filePath}", oldStart: ${ref.oldStart}`);
149 }
150 starts.set(ref.oldStart, count + 1);
151 }
152 }
153
154 const missing: string[] = [];
155 for (const [filePath, starts] of expected) {
156 const actualStarts = actual.get(filePath);
157 for (const oldStart of starts) {
158 if (!actualStarts?.has(oldStart)) {
159 missing.push(` filePath: "${filePath}", oldStart: ${oldStart}`);
160 }
161 }
162 }
163
164 const extra: string[] = [];
165 for (const [filePath, starts] of actual) {
166 const expectedStarts = expected.get(filePath);
167 for (const oldStart of starts.keys()) {
168 if (!expectedStarts?.has(oldStart)) {
169 extra.push(` filePath: "${filePath}", oldStart: ${oldStart}`);
170 }
171 }
172 }
173
174 if (missing.length === 0 && extra.length === 0 && duplicates.length === 0) return;
175
176 const lines = ["Hunk coverage validation failed."];
177 if (missing.length > 0) {
178 lines.push(`Missing hunks (${missing.length}) — not assigned to any chapter:`);
179 lines.push(...missing);

Callers 1

assembleChaptersFileFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected