import { describe, expect, test } from "bun:test" import path from "node:path" const SOURCE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx"]) function isExempt(file: string) { const norm = file.replaceAll("\\", "/").toLowerCase() return norm.split("/").some((part) => part.includes("kilocode")) } function isSource(file: string) { return SOURCE_EXTS.has(path.extname(file)) } const MARKER_PREFIX = /(?:\/\/|\{?\s*\/\*)\s*kilocode_change\b/ function hasMarker(line: string) { return MARKER_PREFIX.test(line) } function coveredLines(text: string): Set { const lines = text.split(/\r?\n/) const covered = new Set() const first = lines.find((x) => x.trim() !== "") if (first?.match(/(?:\/\/|\{?\s*\/\*)\s*kilocode_change\s*-\s*new\s*file\b/)) { for (let i = 1; i <= lines.length; i++) covered.add(i) return covered } let block = false for (let i = 0; i < lines.length; i++) { const n = i + 1 const line = lines[i] ?? "" if (line.match(/(?:\/\/|\{?\s*\/\*)\s*kilocode_change\s+start\b/)) { block = true covered.add(n) continue } if (line.match(/(?:\/\/|\{?\s*\/\*)\s*kilocode_change\s+end\b/)) { covered.add(n) block = false continue } if (block) { covered.add(n) continue } if (hasMarker(line)) covered.add(n) } return covered } function checkLine(line: string, covered: Set, n: number): boolean { const trim = line.trim() if (!trim) return true if (hasMarker(trim)) return true return covered.has(n) } // ─── hasMarker tests ────────────────────────────────────────────────────────── describe("hasMarker", () => { const cases: Array<[string, boolean]> = [ // JS-style inline ["// kilocode_change", true], [" // kilocode_change", true], ["const x = 1 // kilocode_change", true], ["// kilocode_change start", true], ["// kilocode_change end", true], ["// kilocode_change - new file", true], ["// kilocode_change", true], ["// kilocode_change ", true], // JSX-style inline ["{/* kilocode_change */}", true], [" {/* kilocode_change */}", true], ["{/* kilocode_change start */}", true], ["{/* kilocode_change end */}", true], ["{/* kilocode_change - new file */}", true], ["{/* kilocode_change - KiloNews added */}", true], ["{/* kilocode_change */}", true], ["{/* kilocode_change */}", true], // bare /* */ style ["/* kilocode_change */", true], [" /* kilocode_change */", true], ["/* kilocode_change start */", true], ["/* kilocode_change end */", true], // Non-markers ["const x = 1", false], ["{label}", false], ["// some other comment", false], ["{/* just a comment */}", false], ["/* something else */", false], // typo variants — should NOT match (missing word boundary) ["// kilocode_changes", false], ["// kilocode_changelog", false], ["/* kilocode_change_log */", false], ["{/* kilocode_changes */}", false], ["// kilocode_changeable", false], ["", false], [" ", false], ] test.each(cases)("input %j → %j", (input, expected) => { expect(hasMarker(input)).toBe(expected) }) }) // ─── isExempt tests ─────────────────────────────────────────────────────────── describe("isExempt", () => { const cases: Array<[string, boolean]> = [ // exempt — "kilocode" in path ["packages/opencode/src/kilocode/foo.ts", true], ["packages/opencode/test/kilocode/bar.test.ts", true], ["packages/opencode/src/some/kilocode/deep/path.ts", true], ["packages/opencode/src/kilocode/deep/nested/file.tsx", true], // exempt — "kilocode" in filename ["packages/opencode/src/foo/kilocode.ts", true], ["packages/opencode/src/bar/kilocode.test.ts", true], ["packages/opencode/src/file.kilocode.ts", true], // exempt — case-insensitive ["packages/opencode/src/KiloCode/foo.ts", true], ["packages/opencode/src/KILOCODE/bar.ts", true], // NOT exempt ["packages/opencode/src/index.ts", false], ["packages/opencode/src/cli/cmd/tui/routes/home.tsx", false], ["packages/opencode/src/cli/cmd/tui/routes/session/index.tsx", false], ["packages/opencode/src/tool/registry.ts", false], ["packages/opencode/src/config/config.ts", false], ["packages/opencode/src/indexing/search-service.ts", false], // kilocode_change is not the same as kilocode ["packages/opencode/src/check-opencode-annotations.ts", false], ] test.each(cases)("%j → exempt=%j", (file, expected) => { expect(isExempt(file)).toBe(expected) }) }) // ─── isSource tests ─────────────────────────────────────────────────────────── describe("isSource", () => { const cases: Array<[string, boolean]> = [ ["foo.ts", true], ["foo.tsx", true], ["foo/bar.tsx", true], ["foo.js", true], ["foo.jsx", true], [".json", false], [".md", false], [".txt", false], ["Makefile", false], ["foo.go", false], ["foo.rs", false], ] test.each(cases)("%j → isSource=%j", (file, expected) => { expect(isSource(file)).toBe(expected) }) }) // ─── coveredLines tests ─────────────────────────────────────────────────────── describe("coveredLines", () => { test("empty file", () => { const covered = coveredLines("") expect(covered.size).toBe(0) }) test("file with only whitespace", () => { const covered = coveredLines(" \n\n \n") expect(covered.size).toBe(0) }) test("whole-file JS annotation", () => { const covered = coveredLines("// kilocode_change - new file\nexport const x = 1\nexport const y = 2") expect(covered).toEqual(new Set([1, 2, 3])) }) test("whole-file JSX annotation", () => { const covered = coveredLines("{/* kilocode_change - new file */}\nexport const x = 1\nexport const y = 2") expect(covered).toEqual(new Set([1, 2, 3])) }) test("JS block markers", () => { const text = [ "const a = 1", "// kilocode_change start", "const b = 2", "const c = 3", "// kilocode_change end", "const d = 4", ].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([2, 3, 4, 5])) // block markers + content }) test("JSX block markers", () => { const text = [ "const a = 1", "{/* kilocode_change start */}", "const b = 2", "const c = 3", "{/* kilocode_change end */}", "const d = 4", ].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([2, 3, 4, 5])) }) test("mixed JS and JSX block markers (nested)", () => { const text = [ "// kilocode_change start", "{/* kilocode_change start */}", "const b = 2", "{/* kilocode_change end */}", "// kilocode_change end", ].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([1, 2, 3, 4, 5])) }) test("bare /* */ block markers", () => { const text = ["/* kilocode_change start */", "const b = 2", "/* kilocode_change end */"].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([1, 2, 3])) }) test("inline JS marker covers only that line", () => { const text = ["const a = 1", "const b = 2 // kilocode_change", "const c = 3"].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([2])) }) test("inline JSX marker covers only that line", () => { const text = ["const a = 1", "{/* kilocode_change */}", "const c = 3"].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([2])) }) test("inline JS marker with code on same line", () => { const text = "const url = Flag.KILO_MODELS_URL || 'https://models.dev' // kilocode_change\n" const covered = coveredLines(text) expect(covered).toEqual(new Set([1])) }) test("JSX block marker with descriptive suffix", () => { const text = [ "{/* kilocode_change start - Kilo-specific error display */}", "", "{/* kilocode_change end */}", ].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([1, 2, 3])) }) test("multiple independent blocks", () => { const text = [ "// kilocode_change start", "const a = 1", "// kilocode_change end", "const b = 2", "{/* kilocode_change start */}", "const c = 3", "{/* kilocode_change end */}", "const d = 4", ].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([1, 2, 3, 5, 6, 7])) }) test("marker line with extra text after marker is still covered", () => { const text = [ "const a = 1", "// kilocode_change start - this is kilo specific", "const b = 2", "// kilocode_change end", ].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([2, 3, 4])) }) test("nested block — inner block ends, outer continues", () => { const text = [ "// kilocode_change start", "{/* kilocode_change start */}", "const b = 2", "{/* kilocode_change end */}", "const c = 3", "// kilocode_change end", ].join("\n") const covered = coveredLines(text) // Line 1: start, block=true // Line 2: inner start, block=true (covered by block) // Line 3: covered by block // Line 4: inner end, block=false, covered by end marker // Line 5: NOT covered (block is false, no inline marker) // Line 6: outer end, block already false, covered by end marker expect(covered).toEqual(new Set([1, 2, 3, 4, 6])) }) test("whitespace before marker is handled", () => { const text = [" {/* kilocode_change start */}", " const b = 2", " {/* kilocode_change end */}"].join("\n") const covered = coveredLines(text) expect(covered).toEqual(new Set([1, 2, 3])) }) }) // ─── checkLine integration tests ────────────────────────────────────────────── // Simulates what the main loop does for each added line describe("checkLine (main loop simulation)", () => { function check(text: string, addedLines: number[]): string[] { const covered = coveredLines(text) const lines = text.split(/\r?\n/) const violations: string[] = [] for (const n of addedLines) { const line = lines[n - 1] ?? "" const trim = line.trim() if (!trim) continue if (hasMarker(trim)) continue if (!covered.has(n)) violations.push(`line ${n}: ${trim}`) } return violations } test("covered line reports no violation", () => { const text = ["// kilocode_change start", "const kilo = 1", "// kilocode_change end"].join("\n") expect(check(text, [2])).toEqual([]) }) test("uncovered line reports violation", () => { const text = ["const uncovered = 1", "const also_uncovered = 2"].join("\n") expect(check(text, [1, 2])).toEqual(["line 1: const uncovered = 1", "line 2: const also_uncovered = 2"]) }) test("empty lines are skipped", () => { const text = ["const x = 1", "", " ", "", "const y = 2"].join("\n") expect(check(text, [1, 2, 3, 4, 5])).toEqual(["line 1: const x = 1", "line 5: const y = 2"]) }) test("marker lines are skipped even if uncovered", () => { // This shouldn't normally happen, but the loop should skip it const text = ["{/* kilocode_change */}", "{/* kilocode_change start */}"].join("\n") expect(check(text, [1, 2])).toEqual([]) }) test("real-world TSX home.tsx pattern", () => { const text = [ '', " {/* kilocode_change start */}", " ", " {indexingLabel()}", " ", " {/* kilocode_change end */}", "", ].join("\n") // Only the first and last lines (opening/closing box) should be uncovered expect(check(text, [1, 7])).toEqual([`line 1: `, `line 7: `]) // Middle lines are covered expect(check(text, [2, 3, 4, 5, 6])).toEqual([]) }) test("real-world TSX session index.tsx pattern", () => { const text = [ "const foo = 1", "{/* kilocode_change start */}", '', "", "", "{/* kilocode_change end */}", "const bar = 2", ].join("\n") // Lines 1 and 7 are uncovered (not in any block) expect(check(text, [1, 7])).toEqual(["line 1: const foo = 1", "line 7: const bar = 2"]) // Lines 2-6 are covered expect(check(text, [2, 3, 4, 5, 6])).toEqual([]) }) test("real-world TSX sidebar.tsx pattern", () => { const text = [ "", " {/* kilocode_change start */}", " ", " {/* kilocode_change end */}", "", " {/* kilocode_change start */}", "
other content
", " {/* kilocode_change end */}", ].join("\n") expect(check(text, [1, 5])).toEqual(["line 1: ", "line 5: "]) expect(check(text, [2, 3, 4, 6, 7, 8])).toEqual([]) }) test("real-world TSX permission.tsx inline pattern", () => { const text = [ "{/* kilocode_change */}", "", "{/* kilocode_change */}", "", ].join("\n") expect(check(text, [2, 4])).toEqual(["line 2: ", "line 4: "]) expect(check(text, [1, 3])).toEqual([]) }) test("JS-style session/index.tsx pattern (from existing codebase)", () => { const text = ["const foo = 1", "", "{/* kilocode_change */}", "