fix: ensure truncatedByLimit is only true when content is actually excluded

This commit is contained in:
Hannes Rudolph 2026-01-14 22:38:15 -07:00
parent cb75197502
commit 95a2390744
2 changed files with 85 additions and 8 deletions

View file

@ -0,0 +1,64 @@
import { promises as fs } from "fs"
import path from "path"
import { readIndentationBlock } from "../read-file-content"
describe("readIndentationBlock truncation", () => {
const testDir = __dirname
async function withTempFile(filename: string, content: string, testFn: (filepath: string) => Promise<void>) {
const filepath = path.join(testDir, filename)
await fs.writeFile(filepath, content)
try {
await testFn(filepath)
} finally {
await fs.unlink(filepath)
}
}
it("should NOT be truncated when block size equals limit and no content remains", async () => {
// Use indentation to ensure lines are treated as content block, not siblings
const content = " Line 1\n Line 2\n Line 3"
await withTempFile("truncation-exact-test.txt", content, async (filepath) => {
const result = await readIndentationBlock(filepath, 1, 3)
// Should get all 3 lines
expect(result.lineCount).toBe(3)
expect(result.metadata.truncatedByLimit).toBe(false)
})
})
it("should be truncated when block size exceeds limit", async () => {
// Use indentation to ensure lines are treated as content block, not siblings
const content = " Line 1\n Line 2\n Line 3\n Line 4"
await withTempFile("truncation-exceeds-test.txt", content, async (filepath) => {
const result = await readIndentationBlock(filepath, 1, 3)
// Should get 3 lines
expect(result.lineCount).toBe(3)
expect(result.metadata.truncatedByLimit).toBe(true)
})
})
it("should NOT be truncated when block ends naturally before limit (with maxLevels)", async () => {
// Block: lines 1-2 (indent 8). File has lines 3-4 (indent 0). Limit 10.
// maxLevels: 1 => minIndent = 8 - 4 = 4.
const content = " Line 1\n Line 2\nLine 3\nLine 4"
await withTempFile("truncation-natural-end-levels-test.txt", content, async (filepath) => {
const result = await readIndentationBlock(filepath, 1, 10, {
anchorLine: 1,
maxLevels: 1,
})
// Should get 2 lines (Line 1, Line 2)
expect(result.lineCount).toBe(2)
expect(result.metadata.truncatedByLimit).toBe(false)
})
})
it("should be truncated when block continues but limit reached", async () => {
// Block: lines 1-4. Limit 3.
const content = " Line 1\n Line 2\n Line 3\n Line 4"
await withTempFile("truncation-limit-reached-test.txt", content, async (filepath) => {
const result = await readIndentationBlock(filepath, 1, 3, { anchorLine: 1 })
expect(result.lineCount).toBe(3)
expect(result.metadata.truncatedByLimit).toBe(true)
})
})
})

View file

@ -241,6 +241,11 @@ async function collectFileLines(filePath: string): Promise<LineRecord[]> {
lineNumber++
records.push(createLineRecord(lineNumber, buffer))
}
console.log(
"collectFileLines records:",
records.length,
records.map((r) => r.raw),
)
resolve(records)
})
})
@ -506,8 +511,9 @@ export async function readIndentationBlock(
let j = anchorIndex + 1 // downward cursor
let iMinIndentCount = 0
let jMinIndentCount = 0
let truncatedByLimit = false
while (out.length < finalLimit) {
while (out.length <= finalLimit) {
let progressed = 0
// Expand upward
@ -530,12 +536,15 @@ export async function readIndentationBlock(
}
}
if (i >= 0) {
i--
// Check if we've exceeded the limit
if (out.length > finalLimit) {
truncatedByLimit = true
out.shift()
break
}
if (out.length >= finalLimit) {
break
if (i >= 0) {
i--
}
} else {
i = -1 // Stop upward expansion
@ -558,6 +567,13 @@ export async function readIndentationBlock(
jMinIndentCount++
}
// Check if we've exceeded the limit
if (out.length > finalLimit) {
truncatedByLimit = true
out.pop()
break
}
if (j < records.length) {
j++
}
@ -594,9 +610,6 @@ export async function readIndentationBlock(
const totalLines = records.length
const linesAfterEnd = totalLines - endLine
// Determine if truncated by limit (expansion stopped due to limit, not natural boundaries)
const truncatedByLimit = out.length >= finalLimit
return {
content,
lineCount: linesReturned,