Skip to content

neighbors cannot tell merged rows from closed ones or filter by time, so a superseded-PR check takes ~18 s per PR #238

Description

@masatohoshino

Summary

A common cleanup question on a large repository is "was this open PR already landed by a later one?". gitcrawl's neighbors is the natural tool: the answer is among the similar pull requests merged after the open PR was created. Today neighbors cannot tell a merged row from a closed one and cannot filter by time, and its rows carry no state. The only route is --include-closed with a very large --limit, plus a separate threads --include-closed --json dump to look up each row's merge time. That scores every stored vector on every call: about 18 s per PR on a warm cache, whatever --limit is, and rows that rank below the limit are lost.

How often the question comes up

On openclaw/openclaw, 2026-09-01 to 2026-10-09, external pull requests (from authors outside the maintainer team, bots excluded) closed without merging:

  • 621 of 1,866 (33%) were closed with a comment saying another pull request had landed, superseded or duplicated them (classified from the closing comments; about 85% correct in a 60-row hand check).
  • 437 of those name the pull request that had merged first. When that pull request's body mentioned the earlier one (129), it was closed at a median of 0.0 h after the merge; when it did not (308), the median was 26.4 h and 51% took more than a day.

The delay sits in the cases where the later pull request did not mention the earlier one, which is what a similarity search with state and time can surface.

What happens today

gitcrawl main bd30790, on a read-only copy of an openclaw/openclaw archive (165,815 threads, 3,306 open pull requests, last complete sync 2026-10-10T09:06:46Z), embeddings qwen3-embedding:0.6b (1024 dimensions, title_original basis):

gitcrawl neighbors openclaw/openclaw --number <open PR> --include-closed --limit 32765 --json
gitcrawl threads openclaw/openclaw --include-closed --json   # merge times, then a local join
  • neighbors: 18.3 s median per PR with a warm page cache (10 open PRs; 18.0–18.5 s at --limit 1,000, 5,000 or 32,765), 38–39 s cold, about 3.3 GB RSS. It decodes and scores all 165,815 stored vectors each time.
  • The threads dump (992 MB of JSON) adds 5.5 s warm or 32 s cold.
  • --limit above 32,765 fails with too many SQL variables, so a candidate ranked lower can never be returned.

Proposal

Add time filters to neighbors, applied in SQL before vectors are scored and before the limit:

  • --merged-after <time>: pull requests merged after that time.
  • --open-at <time>: rows open at that time.
  • --created-after <time|ref>: rows created after that time; a thread reference compares numbers, which GitHub assigns in creation order.

Each row would also carry state, html_url, is_draft and, when set, the author, author association, and created/closed/merged times, and the output would report state_as_of, the start of the newest complete sync. Existing fields and their order, the default query, and the schema would stay as they are.

With such a change, the same question took a median 1.4 s per PR warm (p95 4.3 s over all 3,306 open PRs) on the same copy, and returned the same top 10 as the workaround above in all 40 checks (10 PRs, two questions, warm and cold). I have this ready as a pull request.

What the candidates are worth

Similarity gives candidates, not proof. To see how often the top candidate is the answer, for every open external pull request on the same copy (2,089) I took the most similar pull request by a different author merged after it was created, and checked random samples by comparing both diffs with openclaw/openclaw main at e3415ea8c55 (model-assisted, blind to the score; a second independent blind pass on 10 pairs agreed on 9 of them and on every "already landed" verdict):

Score of the top candidate Open PRs Sampled Already landed by that PR Partly landed
0.85 or above 53 25 11–12 of 25 (44–48%; Wilson 95% CI 27–67%) 7–8
0.80 to 0.85 126 25 3 of 25 (12%; 4–30%) 7

One pair in the upper band is borderline between "landed" and "partly landed", hence the range. In two more pairs of the upper band, a different pull request had already landed the change. These rates depend on the embedding model and basis above; with the default text-embedding-3-small they may differ.

How far the filters can be trusted

The archive keeps current values, not history. A merge time never changes, so --merged-after is exact up to state_as_of and can only miss merges after it. Reopening clears closed_at, so --open-at can only include extra rows (a row with an earlier close and reopen), never drop one that was open. These directions, and each row's state, assume the closed-thread sweeps have covered the archive since its rows were stored. On the copy above, 0 of 1,100 checked --open-at rows were wrong and all 1,100 checked merged_at values matched GitHub's mergedAt.

Activity

  1. added
    P2Normal priority bug or improvement with limited blast radius.
    clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.
    clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.
    clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.
    impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.
    issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.
    on Oct 10, 2026
  2. clawsweeper commented on Oct 10, 2026

    @clawsweeper

    Codex review: this still needs some work.

    Summary
    This issue remains necessary: current main lacks the requested filters and result metadata, and an open same-author PR explicitly owns the implementation.

    Reproducibility: Current source establishes the absent filters and metadata and the loading-before-limiting path; the contributor supplies CLI evidence, but this review ran no target code.

    Root-cause cluster
    Relationship: canonical
    Canonical: #238
    Summary: This issue tracks the missing neighbor-selection capability, and the linked open PR proposes its implementation.

    Members:

    Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

    Maintainer decision needed

    • Question: Should neighbors expose all three proposed time filters, additive thread metadata, and the state_as_of freshness contract?
    • Recommendation: Approve the proposed surface: Review feat(neighbors): filter by state and merge time before ranking #239 with preserved defaults and explicit reopening and sweep-coverage limitations.
    • Why: The report demonstrates practical value, but the new public flags and historical-state semantics require owner judgment, and the inspected discussion records no human decision.

    Next step
    Review #239 and settle its filter and output contract before resolving this issue.

    Review details

    Best possible solution:

    Provide approved SQL filters before vector decoding and ranking, with additive metadata and clearly documented archive freshness limits.

    Do we have a high-confidence way to reproduce the issue?

    Current source establishes the absent filters and metadata and the loading-before-limiting path; the contributor supplies CLI evidence, but this review ran no target code.

    Is this the best way to solve the issue?

    Filtering within the existing SQL selection directly addresses the workload without a storage migration; the linked PR is the appropriate place to settle public semantics and compatibility.

    AGENTS.md: found but not applied because it conflicted with ClawSweeper's review contract.

    Remaining risk / open question:

    • Historical open-state selection relies on current archive values, so reopening and incomplete closed-thread sweep coverage limit its accuracy.
    • The reported timings and exact SQL-variable failure threshold were not independently reproduced.

    Codex review notes: model internal, reasoning medium; reviewed against bd30790d7735.

    Label changes

    Label changes:

    No label changes.

    Label justifications:

    • P2: A useful large-archive search improvement with limited operational blast radius and an existing implementation PR.
    • impact:ux-friction: Finding later-merged candidates requires large neighbor retrieval and a separate thread-dump join.
    Evidence reviewed

    What I checked:

    How this review workflow works
    • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
    • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
    • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
    • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
    • Maintainers can also comment @clawsweeper review to request a fresh review only.
    • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
    • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
    • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

    Reviewed October 10, 2026, 6:27 PM ET / 22:27 UTC.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions