Skip to content

Commit fd925bd

Browse files
committed
feat(api): persist fix-loop telemetry
1 parent e77b5c4 commit fd925bd

10 files changed

Lines changed: 304 additions & 6 deletions

File tree

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ This roadmap is derived from deep research into Greptile's public docs, blog, MC
5353
23. [x] Add a max-iteration policy and loop budget controls for autonomous review convergence.
5454
24. [x] Add "issue replay" prompts that hand unresolved findings back to a coding agent with file-local context.
5555
25. [x] Add a handoff contract from reviewer findings to fix agents with rule IDs, evidence, and suggested diffs.
56-
26. [ ] Persist loop-level telemetry: iterations, fixes attempted, findings cleared, findings reopened.
56+
26. [x] Persist loop-level telemetry: iterations, fixes attempted, findings cleared, findings reopened.
5757
27. [x] Add "challenge the finding" verification loops where a validator tries to falsify a suspected issue before keeping it.
5858
28. [ ] Add caching between iterations so repeated codebase retrieval and verification runs are cheaper.
5959
29. [ ] Allow loop policies to differ by profile: conservative auditor, high-autonomy fixer, or report-only.

src/core/comment.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ use tags::extract_tags;
3636

3737
pub use identity::compute_comment_id;
3838
pub use types::{
39-
Category, CodeSuggestion, Comment, CommentStatus, FixEffort, MergeReadiness, RawComment,
40-
ReviewCompletenessSummary, ReviewSummary, ReviewVerificationState, ReviewVerificationSummary,
41-
Severity,
39+
Category, CodeSuggestion, Comment, CommentStatus, FixEffort, FixLoopTelemetry, MergeReadiness,
40+
RawComment, ReviewCompletenessSummary, ReviewSummary, ReviewVerificationState,
41+
ReviewVerificationSummary, Severity,
4242
};
4343

4444
pub struct CommentSynthesizer;

src/core/comment/summary.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub(super) fn generate_summary(comments: &[Comment]) -> ReviewSummary {
7474
merge_readiness: default_merge_readiness(open_blockers),
7575
verification: ReviewVerificationSummary::default(),
7676
readiness_reasons: Vec::new(),
77+
loop_telemetry: None,
7778
}
7879
}
7980

@@ -83,6 +84,7 @@ pub(super) fn inherit_review_state(
8384
) -> ReviewSummary {
8485
if let Some(previous) = previous {
8586
summary.verification = previous.verification.clone();
87+
summary.loop_telemetry = previous.loop_telemetry.clone();
8688
}
8789
apply_review_runtime_state(summary, false)
8890
}
@@ -211,7 +213,7 @@ mod tests {
211213
use std::path::PathBuf;
212214

213215
use super::*;
214-
use crate::core::comment::{Category, FixEffort};
216+
use crate::core::comment::{Category, FixEffort, FixLoopTelemetry};
215217

216218
fn make_comment(
217219
id: &str,
@@ -409,4 +411,26 @@ mod tests {
409411
assert_eq!(summary.completeness.fixed_findings, 1);
410412
assert_eq!(summary.completeness.stale_findings, 1);
411413
}
414+
415+
#[test]
416+
fn inherit_review_state_preserves_fix_loop_telemetry() {
417+
let previous = ReviewSummary {
418+
loop_telemetry: Some(FixLoopTelemetry {
419+
iterations: 3,
420+
fixes_attempted: 2,
421+
findings_cleared: 4,
422+
findings_reopened: 1,
423+
}),
424+
..generate_summary(&[make_comment(
425+
"open-warning",
426+
Severity::Warning,
427+
Category::Bug,
428+
CommentStatus::Open,
429+
)])
430+
};
431+
432+
let inherited = inherit_review_state(generate_summary(&[]), Some(&previous));
433+
434+
assert_eq!(inherited.loop_telemetry, previous.loop_telemetry);
435+
}
412436
}

src/core/comment/types.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ pub struct ReviewSummary {
6565
pub verification: ReviewVerificationSummary,
6666
#[serde(default, skip_serializing_if = "Vec::is_empty")]
6767
pub readiness_reasons: Vec<String>,
68+
#[serde(default, skip_serializing_if = "Option::is_none")]
69+
pub loop_telemetry: Option<FixLoopTelemetry>,
70+
}
71+
72+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
73+
pub struct FixLoopTelemetry {
74+
#[serde(default)]
75+
pub iterations: usize,
76+
#[serde(default)]
77+
pub fixes_attempted: usize,
78+
#[serde(default)]
79+
pub findings_cleared: usize,
80+
#[serde(default)]
81+
pub findings_reopened: usize,
6882
}
6983

7084
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]

src/output/format.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ mod tests {
943943
merge_readiness: crate::core::comment::MergeReadiness::NeedsAttention,
944944
verification: crate::core::comment::ReviewVerificationSummary::default(),
945945
readiness_reasons: Vec::new(),
946+
loop_telemetry: None,
946947
};
947948
let comments = vec![
948949
build_test_comment(

0 commit comments

Comments
 (0)