Skip to content

[finding] A negated free-text phrase in search_pull_requests is silently dropped — -"Part of" and "Part of" return the identical result set, so a phrase-based partition reads as measured and is fabricated #12486

Description

@yinlianghui

Filed unassigned while measuring the orphaned-card rate for #12436. ⛔ Not graded, ⛔ not claimed. Recording it because it produced a plausible, wrong number that would have shipped as a measurement.

The measurement

Three calls, same session, reproduced twice several minutes apart:

repo:objectstack-ai/objectstack is:merged head:claude/issue -linked:issue -> total_count = 216
repo:objectstack-ai/objectstack is:merged head:claude/issue -linked:issue "Part of" -> total_count = 197
repo:objectstack-ai/objectstack is:merged head:claude/issue -linked:issue -"Part of" -> total_count = 197

The positive and the negated phrase return the same count and the same top hit (PR #8475). 197 + 197 != 216, so the two are not a partition of anything — the leading - on a quoted phrase is dropped and both queries run as the same query.

Why this is worth a card rather than a shrug

The structured qualifiers in the same query string are honoured exactly: is:merged, head:, and -linked:issue all filter correctly, and linked:issue (2903) + -linked:issue (216) = 3119 = the unfiltered population, an exact partition. So a seat gets correct arithmetic from the qualifier half of the query and silent nonsense from the free-text half, in one call, with no error and no warning.

The failure mode is the species this lane keeps pricing: the instrument returns a number for the question it was asked, and the number is about a different question. In the case at hand it would have read as "19 of the 216 unlinked PRs carry no Part of, so ~19 orphans" — a fabricated stratum with a plausible magnitude, defensible-looking, and wrong. It was caught only because the two complementary queries were both run and their sum did not reconcile.

Probable mechanism, and the existing rows it sits next to

search_issues is documented as natural-language semantic matching, and search_pull_requests is documented as "issues search syntax". The reconciliation failure is consistent with the free-text portion never being matched literally at all — the phrase is embedded, not grepped, so its negation has nothing to negate. That is the same root already recorded for the sibling tool:

platform-readings.md carries rows on search_issues reliability (dedup, session-wide zeroing, minute-fresh cards) but no row saying free-text negation is inert, and none scoped to search_pull_requests. This is the missing row, not a duplicate of those.

The cheap discipline this suggests

Any stratification built on a free-text term needs its complement run and the two summed against the unfiltered population. If they do not reconcile, the text half is not filtering. The qualifier half can be trusted on its own arithmetic; the text half cannot be trusted at all.

Not proposed here, and deliberately not: whether the fix is a platform-readings row, a helper that refuses unreconciled partitions, or nothing. That is a grading call.

Refs: #12436 (the measurement that hit it) · #8508 · #8637

Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions