Skip to content

Add contamination file-path identification (SWE-Bench Illusion methodology)#738

Open
Groenbech96 wants to merge 15 commits into
mainfrom
contamination-filepath-probe
Open

Add contamination file-path identification (SWE-Bench Illusion methodology)#738
Groenbech96 wants to merge 15 commits into
mainfrom
contamination-filepath-probe

Conversation

@Groenbech96

Copy link
Copy Markdown
Collaborator

What

Adds a file-path identification contamination probe — a black-box memorization detector that requires no access to model training data.

Motivated by the discussion on work item 632829 (dataset refresh / contamination). Per the SWE-Bench Illusion methodology Haoran cited, contamination detection (not exact quantification) is feasible black-box: give the model only the bug report — no repository, no code — and ask which file(s) contain the bug. A model that localizes bugs it can't see is exhibiting memorization.

How it maps onto BC-Bench

  • Ground truth: files the gold fix patch touches (reuses extract_file_paths_from_patch).
  • Context-free input: entry.get_task() (the problem statement) only.
  • Execution: single-shot Copilot CLI in an isolated empty temp dir, so the repo is withheld.
  • Scoring: exact-path and basename hit/recall. Basename (the AL object file name) is the real memorization signal.

⚠️ AL-specific caveat (built into the report)

AL has rigid naming conventions (<ObjectName>.<ObjectType>.al), so a model can often guess SalesHeader.Table.al from a description without contamination. A raw accuracy number is therefore convention-inflated. The probe reports the pre-cutoff (suspect) vs on/after-cutoff (control) delta as the actual contamination signal — run summarize --cutoff YYYY-MM-DD. The dataset-refresh work provides the fresh control set for free.

Changes

  • src/bcbench/contamination/ — pure core (filepath_probe.py) + runner (runner.py).
  • bcbench contamination filepath-probe <id> and bcbench contamination summarize --cutoff CLI commands.
  • .github/workflows/contamination-probe.ymlworkflow_dispatch + weekly schedule, runs on ubuntu-latest (no BC container/build), matrixed, then summarizes to the step summary.
  • tests/test_filepath_probe.py — 25 unit tests for the pure core.

Testing

  • pytest tests/test_filepath_probe.py → 25 passed; broader CLI/type tests green (57 total).
  • ruff check clean; workflow YAML validated.
  • Summarize path smoke-tested end-to-end with synthetic results (delta report correct).
  • Note: no live model run in this environment (no Copilot auth); the invocation path mirrors the existing code-review judge.

Implements the SWE-Bench Illusion (arXiv:2506.12286) context-free bug
localization probe as a black-box memorization detector that needs no access
to model training data.

The model is given ONLY the bug report (no repository, no code) and asked which
file(s) contain the bug; predictions are scored against the files the gold fix
patch touches. Because AL has rigid file-naming conventions, absolute accuracy
is convention-inflated, so the probe reports the pre-cutoff vs control delta as
the actual contamination signal.

- Pure, tested core: prompt builder, gold-file extraction, prediction parsing,
  exact/basename scoring, aggregation, and temporal cutoff split.
- Runner: single-shot Copilot CLI in an isolated empty dir (repo withheld).
- CLI: `bcbench contamination filepath-probe` and `... summarize --cutoff`.
- Workflow: contamination-probe.yml (dispatch + weekly), no BC container/build.
- 25 unit tests for the pure core.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/bcbench/commands/contamination.py Fixed
Comment thread src/bcbench/commands/contamination.py Fixed
Review fixes for the file-path identification probe:

- Isolation (Important): restrict the Copilot CLI to the `write` tool only
  (--silent --available-tools=write), removing shell/read/fetch so the model
  cannot reach the checked-out repo or the gold patch. Parse the answer from
  stdout instead of a written file. Verified live end-to-end.
- Scheduled cutoff (Important): weekly runs fall back to the CONTAMINATION_CUTOFF
  repo variable so the pre-vs-control delta is still reported.
- Timeout (Important): add PROBE_TIMEOUT_SECONDS (15m) below the 20m workflow
  step timeout so a hung probe records an error result before the step is killed.
- Add missing contamination/__init__.py with the package public API.
- Validate top_k >= 1 in the CLI.
- Replace object-typed lambdas + type: ignore with Callable in aggregate_results.
- Add runner unit tests: save/load round-trip and mocked success/error paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread tests/test_filepath_identification.py Fixed
Comment thread src/bcbench/cli.py
Magnus Hartvig Grønbech and others added 4 commits July 8, 2026 13:54
- Collapse implicitly-concatenated multi-line strings in _build_markdown_report
  into single literals (CodeQL: implicit string concatenation in a list).
- Use a single import style for bcbench.contamination.runner in the probe tests
  (CodeQL: module imported with both 'import' and 'import from').

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Cast the JSON dict to dict[str, object] in _candidate_path so ty accepts the
  string key on .get() (narrowed-from-object dict had key type Never).
- Remove a now-unused `# ty: ignore[invalid-argument-type]` in the nl2al
  pipeline test that ty 0.0.33 flags as unused, unblocking the lint check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The SWE-Bench Illusion paper (arXiv:2506.12286) calls these "diagnostic tasks"
and names this specific one "file-path identification"; "probe" was ad-hoc.
Rename throughout to match the paper:

- CLI: `contamination filepath-probe` -> `contamination file-path-identification`
- module filepath_probe.py -> filepath_identification.py
- FilePathProbe* -> FilePathIdentification*, ProbeAggregate -> IdentificationAggregate
- run/save/load/build helpers and PROBE_* constants renamed accordingly
- result suffix *.filepath-probe.jsonl -> *.file-path-identification.jsonl
- workflow renamed to contamination-file-path-identification.yml
- tests renamed to test_filepath_identification.py

No behavioural change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Groenbech96 Groenbech96 force-pushed the contamination-filepath-probe branch from cf37596 to c5cef89 Compare July 9, 2026 07:26
@Groenbech96 Groenbech96 changed the title Add file-path identification contamination probe Add contamination file-path identification (SWE-Bench Illusion methodology) Jul 9, 2026
@Groenbech96 Groenbech96 force-pushed the contamination-filepath-probe branch from 137ea40 to e3452a9 Compare July 9, 2026 07:48
Two gratuitous divergences from house patterns, surfaced in review:

- Move the hardcoded IDENTIFICATION_TIMEOUT_SECONDS into TimeoutConfig
  (`filepath_identification`), where every other timeout lives; the runner now
  reads `_config.timeout.filepath_identification`.
- De-duplicate the triplicated Copilot-CLI lookup into a shared
  `bcbench.copilot_cli.find_copilot`, now used by the identification runner, the
  code-review judge, and the copilot agent (the judge keeps a `_find_copilot`
  alias so existing test patch points still work).

No behavioural change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Groenbech96 Groenbech96 force-pushed the contamination-filepath-probe branch from e3452a9 to a8595e8 Compare July 9, 2026 07:53
Magnus Hartvig Grønbech and others added 8 commits July 9, 2026 10:15
Reverted immediately after the run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…utput

- Add docs/contamination-file-path-identification.md explaining gold-file
  extraction, path/basename normalization, the exact/basename hit & recall
  formulas, aggregation, and the cutoff delta, with direct citations from
  "The SWE-Bench Illusion" (arXiv:2506.12286).
- Link the doc + paper from the summarize step-summary report footer.
- Add a Diagnostics entry on the docs home page.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reverted immediately after the run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…on CLI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…on logs

Reverted immediately after. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Groenbech96 Groenbech96 marked this pull request as ready for review July 9, 2026 09:10

@gggdttt gggdttt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few methodology / design questions from a close read — none blocking. Details inline.

lines.append(_aggregate_row(pre_agg))
lines.append(_aggregate_row(post_agg))

delta = pre_agg.basename_hit_rate - post_agg.basename_hit_rate

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The headline delta uses basename_hit, but the docs argue exact_hit is the stronger (convention-resistant) memorization signal — should we headline the exact-path delta instead of (or alongside) basename?

[
copilot_cmd,
"--silent", # emit only the agent response on stdout
"--available-tools=write", # the model's ONLY tool: no shell/read/fetch to reach the repo or gold patch

@gggdttt gggdttt Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I misunderstand - this task should only need a JSON text answer, allowing the write tool risks the model writing to a file instead of stdout right?

data); on/after-cutoff entries act as the clean control. Entries with an
unparseable date are conservatively grouped with the pre-cutoff set.
"""
boundary = date.fromisoformat(cutoff)

@gggdttt gggdttt Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor : An invalid --cutoff raises a raw ValueError here — could we pre-validate in the summarize command and surface a typer.BadParameter instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants