fix(git): attribute inferred branches to the captured span - #3084
devin-ai-integration[bot] wants to merge 4 commits into
Conversation
Reflog backfill no longer writes a second span beside the ingest capture span of the same session window. The inferred branch is folded onto the captured span with BranchProvenance::Inferred, so readers see one span, the captured branch stays null (#2980), and replace_backfill_session clears only the inference on revisit (#3024). Refs #3052 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
Fixed in e6650ab. |
|
Fixed in e6650ab. An inference-tagged span is now bounded by its evidence: a branchless observation merges only when it lands inside |
|
Fixed in e6650ab. Revisit now splits |
|
Also addressed in e6650ab: the review's flag on |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
Resolved in ee6caa8 — merge_span now unions capture_window. |
Summary
BranchProvenance::Inferred, instead of being written as a parallelsource=backfillspan.GitEvidenceWriter::replace_backfill_sessionretracts inference independently: it deletes inferred-only spans and clears an inferred branch from a captured span (back tobranch=None, Captured). Relations derived from either are deleted too.GIT_CORRELATION_SCHEMA_VERSION7 → 8 (span record shape changed; older stores get the existing typed reset, same as the 6 → 7 bump in 505f1a1).e6650abaddresses the Devin Review findings: a conflicting captured branch keeps the inferred span standalone, inference-tagged spans are bounded by their evidence window, revisit preserves captured commit evidence, and folding spans absorb the segment window/event count so inference coverage survives in time-filtered queries.Closes #3052. Related: #2980, #3024.
Motivation / design decision
Verified on master
7aa78775ab: ingest capture writestranscript:spans withsource=ingest, branch=None. Backfill writesbackfill:spans for the same window withbranch=Some("main")from the reflog.merge_spanrequires equalsourceandbranch, so the two never merge. Every reader then has to reconcile two rows (span_hitgroups them,span_count=2).Options considered:
branchfield. fix(sessions): order git catch-up by change sequence #2980 rejected this: inference would become indistinguishable from capture and could not be retracted.SessionGitSpangainsbranch_provenance: Captured | Inferred.branchkeeps one meaning: the effective branch that readers and indexes use, so the SQLbranchcolumn,span_matches_ref,scan_targetsand commit attribution are unchanged.SessionGitSpan::captured_branch()returns only what the host observed.Why each constraint still holds:
infer_captured_branchonly fills a captured span whosebranchisNone. It never overwrites an explicit captured branch. Capture matching (transcript_spans_from_observations) compares oncaptured_branch(), andmerge_spanalso requires equal provenance. So a later explicit observation can't merge into, or be hidden by, an inferred attribution. The regression test assertscaptured_branch() == Nonewhile the reader-visible branch ismain.replace_backfill_sessionstill runs before every re-derivation. Each inference it removes is either a whole inferred span or theInferredtag on a captured span. The captured span stays.in_place_history_rewrites_revisit_and_retract_old_inferencepasses unchanged. The revisit marker is still thegit_history_session_changejournal.backfill:span. Nothing is dropped.Hits keep reporting
"backfill"insourceswhen the branch was inferred, so callers can still tell where the branch came from. The only reader-visible change is thatspan_countdrops from 2 to 1.Changes
crates/tracedecay-sessions/src/runtime/git_correlation.rs:BranchProvenance,SessionGitSpan::branch_provenance,captured_branch(),span_hitsources, schema version 8..../git_correlation/attribution.rs:infer_captured_branch(fold absorbs the segment window and refuses on any differently-named branch); capture matching oncaptured_branch()plus evidence-bounded merging for inference-tagged spans;merge_spanrequires equal provenance..../git_correlation/rows.rs:applyfolds incoming backfill spans first.replace_backfill_sessionclears inferred attribution and deletes only inference-derived relations on surviving captured spans. The sharedupsert_spanhelper replaces the inline insert.tracedecay-dashboard-api/src/loom_api.rs.Test plan
runtime::git_correlation::backfill::bounded::tests::reflog_inference_attributes_the_captured_span_and_retracts_alone. On master it fails withcapture and inference must share one span: left: 2, right: 1; it passes with this change. It checks that one row is stored,sessions_for(branch=main)returnsspan_count=1andsources=["backfill","ingest"],captured_branch()isNone, and after a revisit that moves the session out of the worktree the captured span survives with no branch and no relations derived from the inferred branch.conflicting_captured_branch_keeps_the_inferred_span,folded_inference_absorbs_the_segment_window,branchless_capture_beyond_an_inferred_window_opens_its_own_span,revisit_keeps_captured_commit_evidence_on_the_surviving_span(run viascripts/require-exact-test.sh).cargo test -p tracedecay-sessions --lib: 554 passedcargo test -p tracedecay-global-db -p tracedecay-dashboard-api,tracedecay-session-runtime --test session_store_read_costtracedecaysuites (--features test-helpers,test-transport):runtime_acceptance_suite canonical_git,session_suite git,transcript_ingest_suite sessions_for,mcp_suite git_correlation/workflow_query,dashboard_api_test loom/deliverycargo fmt --all -- --check,cargo clippy -p tracedecay-sessions -p tracedecay-dashboard-api --all-targets -- -D warnings,python3 scripts/linux-test-partitions.py check,node scripts/lint-commit-range.mjs --repository . origin/master HEADcargo nextest run --workspace: left to CIChecklist
CHANGELOG.mdupdated: not edited by hand; release tooling generates it from commits.envfiles includedLink to Devin session: https://app.devin.ai/sessions/1f0d1bf1427c4efcabbcdbd01e63cebc
Open in Devin Desktop: https://app.devin.ai/desktop/session/1f0d1bf1427c4efcabbcdbd01e63cebc?variant=devin
Requested by: @ScriptedAlchemy