Watch
0
0
Fork
You've already forked hyperhive
0

review classifier: commit shas and index lines stay out of the prompt

Every classification's shared context began with the PR's head sha,
headed each commit with its sha, and carried each file's
`index <hash>..<hash>` line in the diff. A push or rebase rewrites all
of those, so the provider's prompt cache missed from the first line of
the user message even when the commit messages and hunks were
unchanged (#5245: "cache hits show as 0.1x").

The header now names only repo#pr, each commit is headed by its
position, and the diff drops `index` lines before lockfiles collapse.
The `diff --git` paths and every hunk stay. The TryOut's head_sha is
untouched: the controller still posts the review against it, and the
journal line still logs it.

On the ACP runtime the cost sink also adds each classification's tokens
to `hyperhive.review_classifier.token.usage`, typed input / output /
cacheRead / cacheCreation like claude's own `claude_code.token.usage`,
so the hit rate is a number in the metrics store on both runtimes.
This commit is contained in:
atlas 2026-10-14 10:43:41 +02:00 • committed by mara
commit 74b63dd031
4 changed files with 190 additions and 35 deletions

View file

@ -30,22 +30,26 @@ Answer with exactly one JSON object and nothing else, no code fence:
/// The shared context: the PR's commits with their full messages, then its
/// diff with lockfiles collapsed. Built once per run.
///
/// No object hash goes in: not the head's, a commit's or a blob's. A rebase
/// rewrites all of them, and the provider's cache only serves a prefix that
/// is byte for byte the same as an earlier one.
#[must_use]
pub fn shared_context(run: &TryOut) -> String {
let mut out = format!(
"# Pull request {}#{} at {}\n\n## Commits, oldest first\n\n",
run.repo, run.pr, run.head_sha
"# Pull request {}#{}\n\n## Commits, oldest first\n\n",
run.repo, run.pr
);
for commit in &run.commits {
for (n, commit) in run.commits.iter().enumerate() {
let _ = write!(
out,
"### {}\n\n{}\n\n",
commit.sha,
"### Commit {}\n\n{}\n\n",
n + 1,
commit.message.trim_end()
);
}
out.push_str("## Diff\n\n```diff\n");
out.push_str(&collapse_lockfiles(&run.diff));
out.push_str(&collapse_lockfiles(&strip_index_lines(&run.diff)));
out.push_str("```\n\n");
out
}
@ -111,6 +115,18 @@ fn collapse_lockfiles(diff: &str) -> String {
out
}
/// `diff` without the `index <hash>..<hash>` line of each file's header.
/// The `diff --git` line, the other header lines and every hunk stay: a hunk
/// line starts with ` `, `+`, `-` or `\`, so none of them is matched.
fn strip_index_lines(diff: &str) -> String {
let mut out = String::with_capacity(diff.len());
for line in diff.lines().filter(|line| !line.starts_with("index ")) {
out.push_str(line);
out.push('\n');
}
out
}
/// One lockfile section being collapsed.
struct Collapsed {
path: String,
@ -264,6 +280,46 @@ diff --git a/src/main.rs b/src/main.rs
assert!(shared.contains("+fn main() { run(); }"), "{shared}");
}
#[test]
fn a_rebase_that_changes_only_hashes_leaves_the_shared_context_unchanged() {
let first = run();
let mut rebased = run();
rebased.head_sha = "def456".to_owned();
rebased.commits[0].sha = "def456".to_owned();
rebased.diff = rebased
.diff
.replace("index 1111..2222", "index 3333..4444")
.replace(
"diff --git a/src/main.rs b/src/main.rs\n",
"diff --git a/src/main.rs b/src/main.rs\nindex 5555..6666 100644\n",
);
assert_eq!(shared_context(&first), shared_context(&rebased));
}
#[test]
fn no_hash_reaches_the_shared_context() {
let mut r = run();
r.diff
.push_str("diff --git a/b.rs b/b.rs\nindex 7777..8888 100644\n--- a/b.rs\n+++ b/b.rs\n@@ -1 +1 @@\n-a\n+b\n");
let shared = shared_context(&r);
assert!(
shared.starts_with("# Pull request hyperhive/hyperhive#7\n\n"),
"{shared}"
);
for hash in ["abc123", "7777", "8888"] {
assert!(!shared.contains(hash), "{hash} in {shared}");
}
assert!(
shared.contains("### Commit 1\n\nnix: add a thing"),
"{shared}"
);
assert!(
shared.contains("diff --git a/b.rs b/b.rs\n--- a/b.rs"),
"{shared}"
);
assert!(shared.contains("-a\n+b\n"), "{shared}");
}
#[test]
fn a_quoted_path_is_read_from_its_b_side() {
assert_eq!(