Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/review/issue-rag-wire.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Issue-centric RAG query composition (#2320). The miner analyze phase has no PR diff yet, so it feeds retrieval

Check notice on line 1 in src/review/issue-rag-wire.ts

View check run for this annotation

Loopover ORB / Gittensory Context

Review queue is busy

This repo has a busy review queue in the local Gittensory cache.
// from the issue's title/body/labels while reusing the existing RAG engine unchanged.

import { MIN_QUERY_CHARS } from "./rag";

const MAX_ISSUE_BODY_CHARS = 4000;
const MAX_ISSUE_LABELS = 20;

export type IssueRagQueryInput = {
title: string;
body?: string | undefined;
labels?: string[] | undefined;
};

function cleanLabels(labels: string[] | undefined): string[] {
if (!labels) return [];
return labels
.map((label) => label.trim())
.filter(Boolean)
.slice(0, MAX_ISSUE_LABELS);
}

export function buildIssueRagQuery(input: IssueRagQueryInput): { queryText: string } {
const sections: string[] = [];
const title = input.title.trim();
if (title) sections.push(title);

const body = (input.body ?? "").trim().slice(0, MAX_ISSUE_BODY_CHARS);
if (body) sections.push(body);

const labels = cleanLabels(input.labels);
if (labels.length > 0) sections.push(`Labels: ${labels.join(", ")}`);

const queryText = sections.join("\n\n").trim();
if (queryText.length < MIN_QUERY_CHARS) return { queryText: "" };
return { queryText };
}
2 changes: 1 addition & 1 deletion src/review/rag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,10 @@
}
}

// ── Retrieval (fail-safe: "" when anything is missing/broken) ────────────────────────────────────

Check notice on line 355 in src/review/rag.ts

View check run for this annotation

Loopover ORB / Gittensory Context

Review queue is busy

This repo has a busy review queue in the local Gittensory cache.
/** Skip retrieval for a trivially-short query (e.g. a one-word scope string): not worth an embed +
* a vector query, and the matches would be noise. (#cloud-opt) */
const MIN_QUERY_CHARS = 40;
export const MIN_QUERY_CHARS = 40;
/** Hard cap on neighbours per query — bounds vector-index cost even if a caller passes a large topK. (#cloud-opt) */
const RAG_MAX_TOPK = 20;
const EMPTY_RAG_RETRIEVAL_METRICS: RagRetrievalMetrics = {
Expand Down
57 changes: 57 additions & 0 deletions test/unit/issue-rag-wire.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { describe, expect, it } from "vitest";

Check notice on line 1 in test/unit/issue-rag-wire.test.ts

View check run for this annotation

Loopover ORB / Gittensory Context

Review queue is busy

This repo has a busy review queue in the local Gittensory cache.
import { buildIssueRagQuery } from "../../src/review/issue-rag-wire";

describe("buildIssueRagQuery (#2320)", () => {
it("uses a sufficiently descriptive title when the issue has an empty body", () => {
expect(
buildIssueRagQuery({
title: "Add observability context for self-hosted review planning failures",
body: "",
}),
).toEqual({
queryText: "Add observability context for self-hosted review planning failures",
});
});

it("prepends the issue title, includes the body, and appends labels as a hint line", () => {
const { queryText } = buildIssueRagQuery({
title: "Improve SQLite backup readiness checks",
body: "Operators need restore guidance tied to the existing self-host backup flow.",
labels: ["gittensor:feature", "selfhost", " "],
});

expect(queryText).toContain("Improve SQLite backup readiness checks");
expect(queryText).toContain("Operators need restore guidance");
expect(queryText).toContain("Labels: gittensor:feature, selfhost");
expect(queryText.indexOf("Improve SQLite")).toBeLessThan(queryText.indexOf("Operators need"));
expect(queryText.indexOf("Operators need")).toBeLessThan(queryText.indexOf("Labels:"));
});

it("bounds long issue bodies without dropping the label hint", () => {
const { queryText } = buildIssueRagQuery({
title: "Investigate flaky queue dispatch telemetry",
body: `${"a".repeat(4100)}SHOULD_NOT_APPEAR`,
labels: ["queue"],
});

expect(queryText).toContain("Investigate flaky queue dispatch telemetry");
expect(queryText).toContain("Labels: queue");
expect(queryText).not.toContain("SHOULD_NOT_APPEAR");
});

it("returns an empty query for a one-line issue below the retrieval floor", () => {
expect(buildIssueRagQuery({ title: "Tiny" })).toEqual({ queryText: "" });
});

it("uses a descriptive body when the title is blank and omits blank labels", () => {
const { queryText } = buildIssueRagQuery({
title: " ",
body: "Document how the miner should build issue context before a pull request exists.",
labels: [" ", ""],
});

expect(queryText).toBe(
"Document how the miner should build issue context before a pull request exists.",
);
});
});
Loading