Skip to content

Fix regex API term extraction discarding quotes - #152

Merged
shouze merged 3 commits into
mainfrom
fix/regex-api-term-quotes
Aug 23, 2026
Merged

Fix regex API term extraction discarding quotes#152
shouze merged 3 commits into
mainfrom
fix/regex-api-term-quotes

Conversation

@shouze

@shouze shouze commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Closes #147.

Regex queries like /"react":\s*"[~^]?[0-9]/ were losing almost all their expected results, because the term sent to the GitHub search API dropped every double quote character in the pattern. longestLiteralSequence() in src/regex.ts now treats " as a valid literal character instead of a sequence-breaking one, and extractApiTerm() escapes and wraps the extracted term in GitHub's documented quote-escaping syntax whenever it contains a quote.

Verified directly against the live GitHub API (org fulll): the regex above now sends the API term "\"react\"" (227 candidates, all containing the literal substring), instead of the previous bare term react (20288 candidates, mostly unrelated noise such as react-native imports, docs, and @types/react, which never surfaced the right package.json files within the API's 1000-result best-match cap).

Existing behaviour for patterns without quotes (TODO|FIXME|HACK, from.*['"]axios, etc.) is unchanged.

How did you verify your code works?

  • Added regression tests in src/regex.test.ts covering the exact reported pattern and the escaped apiQuery it must now produce.
  • Ran the full suite (bun test), lint (bun run lint), format check (bun run format:check) and knip (bun run knip); all green.
  • Verified the derived API term against the live GitHub REST API with curl, confirming a drop from 20288 to 227 candidates for the reported query.
  • Built the binary (bun run build.ts) and ran the original repro command end to end: the compiled binary with the same query and org now returns 9 repositories instead of 2.

longestLiteralSequence() now accumulates " as a valid literal character
instead of breaking the sequence on it. extractApiTerm() escapes and wraps
the extracted term in an outer pair of quotes (GitHub's documented escaping
syntax) whenever it contains a quote, instead of sending an unwrapped term
that GitHub would otherwise strip the quotes from or treat too broadly.

Verified against the live GitHub API: /"react":\s*"[~^]?[0-9]/ now sends
"\"react\"" (227 candidates) instead of the previous bare react term
(20288 candidates, mostly noise never surfacing the right files within the
API's 1000-result best-match cap).

Closes #147
@github-actions

Copy link
Copy Markdown

Coverage after merging fix/regex-api-term-quotes into main will be

95.88%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.57%100%100%93.89%319–323, 384, 401, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.50%100%97.44%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.28%100%100%99.23%272
   render.ts89.87%100%89.47%89.89%167, 191–196, 198–200, 202–203, 254–255, 276, 463–464, 487–489, 555–559, 571–572, 577–584, 586–594, 596–597
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%

Comment thread src/regex.ts Fixed
@shouze shouze changed the title Fix regex API term extraction discarding quotes (#147) Fix regex API term extraction discarding quotes Aug 23, 2026
CodeQL flagged escapeApiTerm() for incomplete string escaping: it escaped
double-quote characters but not backslashes, per GitHub's documented escape
syntax (which only recognises \\ and \" as escapes). A literal backslash
in the term was left unescaped, which could be misread once wrapped in the
outer quoted phrase.

Escape backslashes first, then quotes, matching standard escaping order and
GitHub's own documented rules. longestLiteralSequence() never actually
emits a raw backslash in practice (it only ever appends the character
*after* a backslash, never the backslash itself), so this is a pure
defense-in-depth hardening fix with no observable behaviour change for any
existing input -- confirmed by the full test suite staying green.

escapeApiTerm() is now exported for direct unit testing of the
backslash-then-quote escaping order.

See #152 (comment)
@github-actions

Copy link
Copy Markdown

Coverage after merging fix/regex-api-term-quotes into main will be

95.88%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.57%100%100%93.89%319–323, 384, 401, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.50%100%97.44%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.29%100%100%99.24%277
   render.ts89.87%100%89.47%89.89%167, 191–196, 198–200, 202–203, 254–255, 276, 463–464, 487–489, 555–559, 571–572, 577–584, 586–594, 596–597
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%

@shouze
shouze marked this pull request as ready for review August 23, 2026 14:06
Copilot AI lite review requested due to automatic review settings August 23, 2026 14:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes regex-query API term extraction so patterns containing double quotes (e.g. JSON keys like "react") keep those quotes in the derived GitHub Search API term, preventing overly broad candidate sets and the 1000-result cap from hiding relevant matches.

Changes:

  • Add escapeApiTerm() to escape internal quotes/backslashes and wrap extracted terms in GitHub’s exact-phrase quoting syntax when needed.
  • Update extractApiTerm() / longestLiteralSequence() to treat " as a literal character and to apply escapeApiTerm() to extracted terms (including OR-joined alternation branches).
  • Add regression/unit tests covering the reported reproduction pattern and the escaping behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/regex.ts Keeps " in extracted literal sequences and escapes/wraps API terms so quoted literals survive GitHub’s query parsing.
src/regex.test.ts Adds regression coverage for issue #147 and direct unit tests for the new escaping behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/regex.test.ts Outdated
…quotes

Addresses review feedback: the test name implied the escaped output was just
\"react\", but escapeApiTerm() also wraps the term in outer quotes, so the
actual expectation is "\"react\"". No assertion or behaviour change.

See #152 (comment)
@github-actions

Copy link
Copy Markdown

Coverage after merging fix/regex-api-term-quotes into main will be

95.88%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.57%100%100%93.89%319–323, 384, 401, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.50%100%97.44%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.29%100%100%99.24%277
   render.ts89.87%100%89.47%89.89%167, 191–196, 198–200, 202–203, 254–255, 276, 463–464, 487–489, 555–559, 571–572, 577–584, 586–594, 596–597
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%

@shouze
shouze merged commit 8ea32dd into main Aug 23, 2026
5 checks passed
@shouze
shouze deleted the fix/regex-api-term-quotes branch August 23, 2026 15:00
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.

Regex API term extraction discards quotes, causing regex queries to lose most matches

3 participants