Skip to content

Commit ab0f161

Browse files
Your Nameclaude
andcommitted
test(pipeline): PR#9 -- churn regression test matching the plan's own DoD exactly
Adds call_site_and_external_proof_survive_an_edit_that_only_shifts_ absolute_position: indexes a real file, hand-inserts an external_proofs row (simulating a real SCIP verification, same INSERT shape as the existing cancelled_identity_baseline_preserves_legacy_graph_and_records_ failure test), inserts a comment line above the enclosing function (shifting the call's absolute byte position but not its position relative to the enclosing symbol), reindexes, and asserts: - the call_sites row keeps its own id - callee_start_rel/callee_end_rel are unchanged (relative identity stable) - callee_start_byte genuinely changed (sanity check the fixture actually exercises a position shift, not a no-op) - the external_proofs row survives byte-for-byte: same id, same call_site_id, still status='fresh' -- before slice D (96ea1a3) this proof would have been CASCADE-deleted on any edit to the file, regardless of identity_version, because call_sites blindly deleted-and- reinserted every row for the path on every reindex This is the direct proof that PR#9 slices A-D together (docs/plans/ 2026-08-19-evidence-architecture-execution-plan.md Part E) actually achieve the plan's own stated DoD ("insert a comment line above a proven call site; reindex; assert the proof row for that call site is unchanged"), not just that the existing suite doesn't regress. Verified: cargo build/clippy -p calm-core --all-targets clean, cargo test -p calm-core 1249 passed/0 failed/12 ignored (1248 baseline + 1 new test) including both golden_equivalence_{continued,incremental}_vs_fresh_across_ mutation_rounds, cargo fmt clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 96ea1a3 commit ab0f161

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

crates/calm-core/src/indexer/pipeline.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4529,6 +4529,137 @@ impl StructB {
45294529
let _ = std::fs::remove_dir_all(&dir);
45304530
}
45314531

4532+
#[test]
4533+
// PR#9 (docs/plans/2026-08-19-evidence-architecture-execution-plan.md
4534+
// Part E): the actual DoD scenario v3 position-independent identity +
4535+
// slice D upsert-by-identity reconciliation exist to fix -- "insert a
4536+
// comment line above a proven call site; reindex; assert the proof row
4537+
// for that call site is unchanged". Verified at the persistence layer
4538+
// directly (a hand-inserted external_proofs row simulating what a real
4539+
// SCIP verification would produce, same INSERT shape as
4540+
// cancelled_identity_baseline_preserves_legacy_graph_and_records_failure
4541+
// above) rather than driving real SCIP machinery, which this test
4542+
// doesn't need to exercise.
4543+
fn call_site_and_external_proof_survive_an_edit_that_only_shifts_absolute_position() {
4544+
let dir =
4545+
std::env::temp_dir().join(format!("ci_idx_v3_churn_regression_{}", std::process::id()));
4546+
let _ = std::fs::remove_dir_all(&dir);
4547+
std::fs::create_dir_all(&dir).unwrap();
4548+
std::fs::write(
4549+
dir.join("main.py"),
4550+
"def caller():\n helper()\n\ndef helper():\n pass\n",
4551+
)
4552+
.unwrap();
4553+
4554+
let mut conn = Connection::open_in_memory().unwrap();
4555+
init_db(&conn).unwrap();
4556+
run_indexing_pipeline(&mut conn, &dir, dummy_phase()).unwrap();
4557+
4558+
let (call_site_id, identity_version, start_rel, end_rel, start_byte): (
4559+
i64,
4560+
i64,
4561+
Option<i64>,
4562+
Option<i64>,
4563+
Option<i64>,
4564+
) = conn
4565+
.query_row(
4566+
"SELECT id, identity_version, callee_start_rel, callee_end_rel, callee_start_byte \
4567+
FROM call_sites WHERE callee_name = 'helper'",
4568+
[],
4569+
|r| Ok((r.get(0)?, r.get(1)?, r.get(2)?, r.get(3)?, r.get(4)?)),
4570+
)
4571+
.unwrap();
4572+
assert_eq!(
4573+
identity_version, 3,
4574+
"caller() is a real enclosing symbol -- this call site must get v3 identity"
4575+
);
4576+
assert!(
4577+
start_rel.is_some() && end_rel.is_some(),
4578+
"v3 identity must carry relative offsets"
4579+
);
4580+
4581+
conn.execute(
4582+
"INSERT INTO external_proofs
4583+
(call_site_id, to_symbol, provider, source_file_hash,
4584+
callee_start_byte, callee_end_byte, provider_fingerprint,
4585+
context_fingerprint, status, observed_at)
4586+
VALUES (?1, 'main.py::helper', 'scip:test', 'irrelevant-hash',
4587+
0, 1, 'test-provider', 'test-context', 'fresh', 0)",
4588+
[call_site_id],
4589+
)
4590+
.unwrap();
4591+
let proof_id: i64 = conn
4592+
.query_row(
4593+
"SELECT id FROM external_proofs WHERE call_site_id = ?1",
4594+
[call_site_id],
4595+
|r| r.get(0),
4596+
)
4597+
.unwrap();
4598+
4599+
// Insert a comment line ABOVE caller() -- shifts every byte offset
4600+
// inside caller() (including the helper() call) by a fixed amount,
4601+
// but the call's position RELATIVE to caller()'s own start is
4602+
// unchanged.
4603+
std::fs::write(
4604+
dir.join("main.py"),
4605+
"# a harmless comment, unrelated to caller/helper\ndef caller():\n helper()\n\ndef helper():\n pass\n",
4606+
)
4607+
.unwrap();
4608+
reindex_paths(&mut conn, &dir, &["main.py".to_string()]).unwrap();
4609+
4610+
let (new_id, new_identity_version, new_start_rel, new_end_rel, new_start_byte): (
4611+
i64,
4612+
i64,
4613+
Option<i64>,
4614+
Option<i64>,
4615+
Option<i64>,
4616+
) = conn
4617+
.query_row(
4618+
"SELECT id, identity_version, callee_start_rel, callee_end_rel, callee_start_byte \
4619+
FROM call_sites WHERE callee_name = 'helper'",
4620+
[],
4621+
|r| Ok((r.get(0)?, r.get(1)?, r.get(2)?, r.get(3)?, r.get(4)?)),
4622+
)
4623+
.unwrap();
4624+
4625+
assert_eq!(
4626+
new_id, call_site_id,
4627+
"the call site's own id must survive an edit that only shifts its absolute \
4628+
position -- this is the entire point of v3 relative identity + upsert-by-identity \
4629+
reconciliation"
4630+
);
4631+
assert_eq!(new_identity_version, 3);
4632+
assert_eq!(
4633+
(new_start_rel, new_end_rel),
4634+
(start_rel, end_rel),
4635+
"relative offsets must be unchanged -- the call's position within caller() didn't move"
4636+
);
4637+
assert_ne!(
4638+
new_start_byte, start_byte,
4639+
"sanity check: the absolute byte position MUST have shifted (a comment line was \
4640+
inserted above caller()) -- if this fails the test fixture itself is wrong, not the \
4641+
code under test"
4642+
);
4643+
4644+
let surviving_proof_count: i64 = conn
4645+
.query_row(
4646+
"SELECT COUNT(*) FROM external_proofs \
4647+
WHERE id = ?1 AND call_site_id = ?2 AND status = 'fresh'",
4648+
rusqlite::params![proof_id, call_site_id],
4649+
|r| r.get(0),
4650+
)
4651+
.unwrap();
4652+
assert_eq!(
4653+
surviving_proof_count, 1,
4654+
"the external_proofs row must survive the reindex byte-for-byte (same id, same \
4655+
call_site_id, still 'fresh') -- before slice D this proof would have been \
4656+
CASCADE-deleted because call_sites blindly deleted-and-reinserted every row for the \
4657+
file on any edit"
4658+
);
4659+
4660+
let _ = std::fs::remove_dir_all(&dir);
4661+
}
4662+
45324663
/// Layer-2 code chunks must track incremental reindex the same way symbols
45334664
/// do: a changed file's stale chunks are replaced (not duplicated
45344665
/// alongside the new ones), and a deleted file's chunks disappear too.

0 commit comments

Comments
 (0)