Groundtruth checks developer activity against deterministic, checkable rules — no LLM guessing. This is Rule #001 (auto-close-without-fix), run against 30 real, active public repositories, with every candidate match hand-verified against the actual GitHub issue and PR content before being called a finding. It is a candidate-generation heuristic with mandatory human verification, not an auto-blocking enforcement gate — see "What this is / is not" below.
Auto-close-without-fix: a PR references an issue with a GitHub closing keyword (Fixes #N, Closes #N, Resolves #N) while its diff touches only test files. If that PR merges, GitHub silently closes the issue — without the underlying code ever changing.
Every finding below is checkable, not probabilistic: the rule doesn't guess whether a PR "seems" thin, it reads the actual linked issue's labels and text, and the actual list of changed files, and applies one fact-based test.
Is: a candidate-generation heuristic. It flags PRs matching a deterministic pattern, and every flag on this page was then manually checked against the real issue and PR before being called a finding — that manual step is why zero of the true positives below actually caused harm (see "The number that matters most").
Is not: an auto-blocking enforcement gate. It does not merge, close, or fail a check on its own judgment. Recent tooling (CodeRabbit's Agentic Change Management, launched the same week as their $1.5B valuation; GitHub Copilot's coding-agent auto-validation) automates the verification step itself — this rule automates only the flagging, and treats verification as a human's call, on purpose.
Nearest published research: arXiv:2601.04886 scanned 23,247 AI-authored PRs and named "Phantom Changes" — descriptions claiming a change that was never implemented — as 45.4% of message-code inconsistencies found, releasing a 974-PR annotated dataset because no detector existed at the time. Same failure mode this rule targets, at PR-description granularity rather than repo-artifact granularity. Caveat in the same paper: high-inconsistency PRs are only 1.7% of their full corpus — this is a real but narrow-incidence problem, not a majority-case one.
Zero of the 26 verified true positives actually merged. Every one was caught and rejected by a human maintainer, by hand, before it could auto-close a real bug. Groundtruth didn't catch anything a maintainer missed — it demonstrates that the same judgment call, made once per PR by a person, could be made instantly and consistently by a rule instead.
Verifying against real data didn't just validate the rule. It broke it, twice, in ways synthetic test fixtures never would have.
GitHub's default PR template includes example text like <!-- e.g. "fixes #123" -->. The original regex matched that literal example just like a genuine reference — and #123 is a real (usually unrelated) issue in nearly every repo old enough to have one. This alone produced 10 false positives across pydantic/pydantic and vitejs/vite in the first scan pass. Fixed by stripping HTML comments before matching; confirmed by rescan — all 10 disappeared.
Streamlit ships a real product feature — its AppTest testing framework — implemented in a file literally named app_test.py. The filename heuristic can't distinguish that from an actual test file. Left as a documented, tested limitation rather than a repo-specific patch, which would just trade one blind spot for another.
Nothing here is published on the heuristic's word alone.
For every one of the 43 candidates, the real GitHub issue (title, body, labels) and the real PR (body, merge state) were fetched from the live API and read. A true positive requires the linked issue to be a genuine, usually maintainer-labeled (bug, often accepted) product defect — not a request to add test coverage or fix the test suite itself.
In every false positive in this dataset, the linked issue was itself about tests, CI, or a naming collision with real product code — meaning a test-only PR was the correct fix, not a shortcut. That's the exact class the rule's own design doc names as its known limitation.
Ranked by true-positive count. Every PR and issue number links to the live page.
jaythehardcoder) submitting the same test-only-PR pattern repeatedly — this repo's count is one prolific pattern caught every time, not 22 independent incidents.tests/vector_stores/test_faiss.pytests/vector_stores/test_e2e_threshold.pytests/vector_stores/test_score_normalization.pytests/embeddings/test_gemini_embeddings.pytests/embeddings/test_langchain_embeddings.pytests/embeddings/test_gemini_embeddings.pytests/embeddings/test_langchain_embeddings.pymem0-ts/src/oss/tests/helpers/vectorStoreResultContract.tsmem0-ts/src/oss/tests/vector-store-result-contract.test.tstests/test_oss_to_platform_migrate.pymem0-ts/src/oss/tests/entity-extraction.test.tstests/test_issue_6346.pytests/test_issue_6362.pytests/test_issue_6368.pytests/test_issue_6448.pytests/test_issue_6562.pytests/test_issue_6526.pytests/test_issue_6563.pytests/test_issue_6546.pytests/test_issue_6550.pytests/test_issue_6560.pytests/test_issue_6346.pytests/test_issue_6368.pytests/test_issue_6362.pytests/test_issue_6181.pytests/test_issue_6301.pytests/test_issue_6264.pytests/test_issue_6230.pytests/test_issue_6183.pytests/test_issue_6013.pytests/test_issue_6065.pytests/test_issue_6085.pyllama-dev/tests/test/test_test.pyllama-index-core/tests/indices/multi_modal/test_retriever.pyllama-index-integrations/indices/llama-index-indices-managed-lancedb/tests/test_index.pyllama-index-integrations/protocols/llama-index-protocols-ag-ui/tests/test_utils.pyllama-dev/llama_dev/test/__init__.pyllama-dev/tests/test/test_test.pytest/types/logger.tst.tstest/req.is.jstest/req.is.jstests/conftest.pytests/test_cli.pytests/conftest.pytests/test_cli.pytests/conftest.pytests/test_cli.pytests/conftest.pytests/test_cli.pytests/conftest.pytests/test_cli.pylib/streamlit/testing/v1/app_test.pylib/tests/streamlit/testing/app_test_test.pylib/streamlit/testing/v1/app_test.pyscripts/scan.py + scripts/verify.py against the live GitHub API — nothing here is seeded or synthetic.