Skip to content

Commit ba20696

Browse files
committed
fix(overeng): BM25 divergence, dead env vars, memory_pipeline postpass
1 parent 2159387 commit ba20696

12 files changed

Lines changed: 43 additions & 113 deletions

File tree

benchmarks/adapters/runner.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,18 @@ def _run_parallel( # noqa: C901 — pool-shape branching + multi-failure-mode d
213213
)
214214

215215
def _drain(active_pool: ProcessPoolExecutor) -> None:
216+
from concurrent.futures import CancelledError
216217
from concurrent.futures.process import BrokenProcessPool
217218

218219
futures: dict = {}
219220
submit_failed: list[BenchmarkInstance] = []
221+
pool_broken = False
220222
for inst in pending:
221223
try:
222224
futures[active_pool.submit(eval_fn, inst, params)] = inst
223225
except BrokenProcessPool:
224226
submit_failed.extend([inst, *pending[pending.index(inst) + 1 :]])
227+
pool_broken = True
225228
break
226229
outer_deadline = time.monotonic() + timeout_per_instance * max(1, (len(pending) + workers - 1) // workers)
227230
completed: set[str] = set()
@@ -230,10 +233,11 @@ def _drain(active_pool: ProcessPoolExecutor) -> None:
230233
inst = futures[future]
231234
try:
232235
r = future.result(timeout=0)
233-
except FuturesTimeoutError:
236+
except (FuturesTimeoutError, CancelledError):
234237
r = _failure_result(inst, params, "timeout", f"after {timeout_per_instance}s")
235238
except BrokenProcessPool:
236239
r = _failure_result(inst, params, "error", "BrokenProcessPool: worker died")
240+
pool_broken = True
237241
except Exception as e:
238242
r = _failure_result(inst, params, "error", f"{type(e).__name__}: {e}")
239243
completed.add(inst.instance_id)
@@ -243,12 +247,13 @@ def _drain(active_pool: ProcessPoolExecutor) -> None:
243247
if inst.instance_id not in completed:
244248
record(_failure_result(inst, params, "timeout", "exceeded global deadline"))
245249
except BrokenProcessPool:
250+
pool_broken = True
246251
for inst in futures.values():
247252
if inst.instance_id not in completed:
248253
record(_failure_result(inst, params, "error", "BrokenProcessPool: worker died"))
249254
for inst in submit_failed:
250255
record(_failure_result(inst, params, "error", "BrokenProcessPool: submit failed"))
251-
if submit_failed or any(inst.instance_id not in completed for inst in futures.values()):
256+
if pool_broken:
252257
raise BrokenProcessPool("pool degraded mid-cell")
253258

254259
if pool is not None:

diffctx/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
1111
name = "diffctx"
1212
path = "src/main.rs"
1313

14-
[[bin]]
14+
[[example]]
1515
name = "diffctx-test"
1616
path = "src/test_harness.rs"
1717

diffctx/src/config/bm25.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use once_cell::sync::Lazy;
33
pub struct Bm25Config {
44
pub k1: f64,
55
pub b: f64,
6-
pub doc_len_factor: f64,
76
pub idf_smoothing: f64,
87
pub min_query_token_length: usize,
98
}
@@ -13,7 +12,6 @@ impl Default for Bm25Config {
1312
Self {
1413
k1: 2.5,
1514
b: 0.75,
16-
doc_len_factor: 1.5,
1715
idf_smoothing: 0.5,
1816
min_query_token_length: 3,
1917
}

diffctx/src/config/category_weights.rs

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,11 @@
88
//! (Bayesian opt / grid search) against a labeled corpus, as described in
99
//! paper Section 4.3 (Edge-Type Weight Calibration).
1010
//!
11-
//! Override at runtime via environment variables:
12-
//! DIFFCTX_CATWEIGHT_SEMANTIC=0.65
13-
//! DIFFCTX_CATWEIGHT_STRUCTURAL=0.50
14-
//! DIFFCTX_CATWEIGHT_SIBLING=0.10
15-
//! DIFFCTX_CATWEIGHT_CONFIG=0.40
16-
//! DIFFCTX_CATWEIGHT_CONFIGGENERIC=0.30
17-
//! DIFFCTX_CATWEIGHT_DOCUMENT=0.30
18-
//! DIFFCTX_CATWEIGHT_SIMILARITY=0.20
19-
//! DIFFCTX_CATWEIGHT_HISTORY=0.40
20-
//! DIFFCTX_CATWEIGHT_TESTEDGE=0.60
21-
//! DIFFCTX_CATWEIGHT_GENERIC=0.10
22-
//!
2311
//! Default for every variant is 1.0 (no scaling — the fine-grained
2412
//! prior weights from `weights.rs` apply unchanged).
2513
2614
use once_cell::sync::Lazy;
2715

28-
use crate::config::env_overrides::read_env_f64;
2916
use crate::graph::EdgeCategory;
3017

3118
#[derive(Debug, Clone, Copy)]
@@ -77,18 +64,7 @@ impl CategoryWeights {
7764
}
7865
}
7966

80-
pub static CATEGORY_WEIGHTS: Lazy<CategoryWeights> = Lazy::new(|| CategoryWeights {
81-
semantic: read_env_f64("DIFFCTX_CATWEIGHT_SEMANTIC", 1.0),
82-
structural: read_env_f64("DIFFCTX_CATWEIGHT_STRUCTURAL", 1.0),
83-
sibling: read_env_f64("DIFFCTX_CATWEIGHT_SIBLING", 1.0),
84-
config: read_env_f64("DIFFCTX_CATWEIGHT_CONFIG", 1.0),
85-
config_generic: read_env_f64("DIFFCTX_CATWEIGHT_CONFIGGENERIC", 1.0),
86-
document: read_env_f64("DIFFCTX_CATWEIGHT_DOCUMENT", 1.0),
87-
similarity: read_env_f64("DIFFCTX_CATWEIGHT_SIMILARITY", 1.0),
88-
history: read_env_f64("DIFFCTX_CATWEIGHT_HISTORY", 1.0),
89-
test_edge: read_env_f64("DIFFCTX_CATWEIGHT_TESTEDGE", 1.0),
90-
generic: read_env_f64("DIFFCTX_CATWEIGHT_GENERIC", 1.0),
91-
});
67+
pub static CATEGORY_WEIGHTS: Lazy<CategoryWeights> = Lazy::new(CategoryWeights::default);
9268

9369
#[cfg(test)]
9470
mod tests {

diffctx/src/config/limits.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,18 @@ impl Default for LexicalConfig {
8585
}
8686

8787
pub struct CochangeConfig {
88-
pub weight: f64,
8988
pub min_count: usize,
9089
pub max_files_per_commit: usize,
9190
pub commits_limit: usize,
92-
pub timeout_seconds: u64,
9391
pub log_scale_factor: f64,
9492
}
9593

9694
impl Default for CochangeConfig {
9795
fn default() -> Self {
9896
Self {
99-
weight: 0.40,
10097
min_count: 2,
10198
max_files_per_commit: 30,
10299
commits_limit: 500,
103-
timeout_seconds: 10,
104100
log_scale_factor: 0.1,
105101
}
106102
}

diffctx/src/config/scoring.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
11
use once_cell::sync::Lazy;
22

3-
use crate::config::env_overrides::read_env_f64;
4-
53
pub struct EgoScoringConfig {
64
pub identifier_overlap_epsilon: f64,
75
pub identifier_overlap_cap: usize,
8-
pub per_hop_decay: f64,
96
}
107

118
impl Default for EgoScoringConfig {
129
fn default() -> Self {
1310
Self {
1411
identifier_overlap_epsilon: 0.1,
1512
identifier_overlap_cap: 10,
16-
per_hop_decay: 1.0,
1713
}
1814
}
1915
}
2016

21-
pub static EGO: Lazy<EgoScoringConfig> = Lazy::new(|| EgoScoringConfig {
22-
per_hop_decay: read_env_f64("DIFFCTX_OP_EGO_PER_HOP_DECAY", 1.0),
23-
..EgoScoringConfig::default()
24-
});
17+
pub static EGO: Lazy<EgoScoringConfig> = Lazy::new(EgoScoringConfig::default);

diffctx/src/config/selection.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ use crate::config::env_overrides::{read_env_fraction, read_env_u32};
44
pub struct SelectionConfig {
55
pub core_budget_fraction: f64,
66
pub r_cap_min: f64,
7-
pub stopping_threshold: f64,
87
}
98

109
impl Default for SelectionConfig {
1110
fn default() -> Self {
1211
Self {
1312
core_budget_fraction: 0.70,
1413
r_cap_min: 0.01,
15-
stopping_threshold: 0.08,
1614
}
1715
}
1816
}
@@ -55,7 +53,6 @@ pub fn selection() -> SelectionConfig {
5553
SelectionConfig {
5654
core_budget_fraction: read_env_fraction("DIFFCTX_OP_SELECTION_CORE_BUDGET_FRACTION", 0.70),
5755
r_cap_min: read_env_fraction("DIFFCTX_OP_SELECTION_R_CAP_MIN", 0.01),
58-
stopping_threshold: read_env_fraction("DIFFCTX_OP_SELECTION_STOPPING_THRESHOLD", 0.08),
5956
}
6057
}
6158

diffctx/src/discovery.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl BM25Discovery {
172172
}
173173
let idf_val = idf.get(t).copied().unwrap_or(0.0);
174174
s += idf_val * (freq * BM25.k1)
175-
/ (freq + BM25.doc_len_factor * (1.0 - BM25.b + BM25.b * dl / avgdl));
175+
/ (freq + BM25.k1 * (1.0 - BM25.b + BM25.b * dl / avgdl));
176176
}
177177
s
178178
}

diffctx/src/memory_pipeline.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,38 @@ pub fn build_diff_context_in_memory(
135135
None,
136136
);
137137

138+
let mut selected = selection.selected;
139+
140+
crate::postpass::coherence_post_pass(
141+
&mut selected,
142+
&scoring_result.filtered_fragments,
143+
&scoring_result.graph,
144+
effective_budget,
145+
);
146+
147+
crate::postpass::rescue_nontrivial_context(
148+
&mut selected,
149+
&all_fragments,
150+
&scoring_result.rel_scores,
151+
&core_ids,
152+
effective_budget,
153+
);
154+
155+
let used: u32 = selected.iter().map(|f| f.token_count).sum();
156+
let remaining = effective_budget.saturating_sub(used);
157+
let changed_files: Vec<PathBuf> = changed_paths.iter().map(PathBuf::from).collect();
158+
crate::postpass::ensure_changed_files_represented(
159+
&mut selected,
160+
&all_fragments,
161+
&changed_files,
162+
remaining,
163+
Path::new("."),
164+
&[],
165+
None,
166+
);
167+
138168
let dummy_root = Path::new(".");
139-
build_diff_context_output(dummy_root, &selection.selected, no_content)
169+
build_diff_context_output(dummy_root, &selected, no_content)
140170
}
141171

142172
fn compute_memory_hunks(

diffctx/src/pybridge.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -183,51 +183,6 @@ impl FragmentIterator {
183183
}
184184
}
185185

186-
#[pyfunction]
187-
#[pyo3(signature = (
188-
root_dir,
189-
diff_range = None,
190-
budget_tokens = None,
191-
alpha = DEFAULT_PPR_ALPHA,
192-
tau = DEFAULT_STOPPING_THRESHOLD,
193-
no_content = false,
194-
full = false,
195-
scoring_mode = "hybrid",
196-
timeout = DEFAULT_PIPELINE_TIMEOUT_SECONDS,
197-
))]
198-
fn build_diff_context_native(
199-
py: Python<'_>,
200-
root_dir: &str,
201-
diff_range: Option<&str>,
202-
budget_tokens: Option<u32>,
203-
alpha: f64,
204-
tau: f64,
205-
no_content: bool,
206-
full: bool,
207-
scoring_mode: &str,
208-
timeout: u64,
209-
) -> PyResult<DiffContextResult> {
210-
let mode =
211-
ScoringMode::from_str(scoring_mode).map_err(pyo3::exceptions::PyValueError::new_err)?;
212-
let path = Path::new(root_dir);
213-
214-
py.allow_threads(|| {
215-
pipeline::build_diff_context(
216-
path,
217-
diff_range,
218-
budget_tokens,
219-
alpha,
220-
tau,
221-
no_content,
222-
full,
223-
mode,
224-
timeout,
225-
)
226-
})
227-
.map(DiffContextResult::from)
228-
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))
229-
}
230-
231186
#[pyfunction]
232187
#[pyo3(signature = (
233188
root_dir,
@@ -598,7 +553,6 @@ fn graph_summary<'py>(
598553
#[pymodule]
599554
pub fn _diffctx(m: &Bound<'_, PyModule>) -> PyResult<()> {
600555
m.add_function(wrap_pyfunction!(build_diff_context, m)?)?;
601-
m.add_function(wrap_pyfunction!(build_diff_context_native, m)?)?;
602556
m.add_function(wrap_pyfunction!(get_language_for_file, m)?)?;
603557
m.add_function(wrap_pyfunction!(count_tokens, m)?)?;
604558
m.add_function(wrap_pyfunction!(build_project_graph, m)?)?;

0 commit comments

Comments
 (0)