Detail Bug Report
https://app.detail.dev/org_befd6425-a158-4e24-9d4d-1e5c08769515/bugs/bug_cbeea9a2-5f20-431d-b7dc-1fd583a4c9c5
Introduced in cacf649 by @WilliamAGH on Sep 1, 2026
Summary
- Context:
QueryVersionExtractor.extractVersionNumbers parses learner queries to find Java release versions. It has three production callers: (1) RetrievalService.queryVersionEvidence scopes Java API documentation retrieval from its result (RetrievalService.java:656, :669) on the default chat path; (2) ChatService.buildContextSegments calls extractVersionNumbers again directly (ChatService.java:279) to label per-document source-record headers; (3) GuidedLearningService.buildStructuredGuidedPromptWithContext calls it (GuidedLearningService.java:236) to choose retrieval context doc sets on the guided-learning path. QueryVersionExtractor.boostQueryWithVersionContext also rewrites the hybrid-search query from the retained tokens (RetrievalService.java:354 → QueryVersionExtractor.java:62-65).
- Bug: The
EXPLICIT_QUANTITY_SUFFIX_PATTERN added by commit cacf6493 to reject Java <N> <time-unit> quantity phrases omits the most common time units — years, weeks, months — while rejecting days?|hours?|minutes?|seconds?|times|lines?.
- Actual vs. expected: A temporal phrase such as
switched to Java 6 months ago extracts [�"6�] as a Java release. The expected behavior is []. The report's basis for "expected" is an inference (see "Evidence: hypothesised intent, not evidenced"), not a stated rule.
- Impact: All three consumption paths receive a spurious version token, but the impact on each is mild:
- Guided-learning path: the retrieval supplements for a Java lesson lose the
dev-java source (Oracle's external tutorial content from dev.java/learn/) and are narrowed to java/java21-complete (API reference, v21) instead of dev-java + java/java25-complete. The lesson's own prose tutorial — the curated markdown at src/main/resources/guided/lessons/<slug>.md — is loaded unconditionally and prioritised HIGH regardless of the bug (see "Guided-learning path: what is and isn't lost"). So the consequence is a degradation of retrieval-supplement diversity (tutorial+API → API-only), not a loss of all tutorial prose.
- Chat path: the configured default (Java 25) retrieval scope becomes a spurious Java 21 scope — a swap between two valid, current Java API corpora, so practical degradation is mild.
- Header injection: a
requestedVersions="6" header is injected into the LLM context, byte-for-byte identical to what the system intentionally emits for a genuine out-of-range Java 6 request — the bug changes whether that path is taken, not what it emits.
Code with Bug
private static final Pattern EXPLICIT_QUANTITY_SUFFIX_PATTERN =
Pattern.compile("[\\s-]+(?:days?|hours?|minutes?|seconds?|times|lines?)\\b", Pattern.CASE_INSENSITIVE); // <-- BUG 🔴 missing years?|weeks?|months?
quantitySuffixMatcher.region(explicitVersionMatcher.end(), query.length());
if (quantitySuffixMatcher.lookingAt()) {
continue; // only fires when the noun after the digits is one of days/hours/minutes/seconds/times/line[s]
}
retainedVersions.add(explicitVersionMatcher.group(1));
Explanation
extractVersionNumbers first matches Java|JDK ... <digits> and then uses EXPLICIT_QUANTITY_SUFFIX_PATTERN to skip extraction when the digits are immediately followed by a “quantity noun” (e.g., Java 100 days of practice). Because the suffix pattern does not include months|weeks|years, phrases like Java 6 months ago are not recognized as quantity phrases and the digits are retained as a requested Java version.
This spurious token is then consumed by multiple flows:
- Guided learning:
requestedVersions becomes non-empty, so effectiveDocSetsFor(...) replaces the lesson’s normal doc sets (dev-java + java/java25-complete) with Java API-only doc sets resolved from the spurious version (ultimately java/java21-complete), reducing retrieved supplement diversity.
- Chat retrieval: the spurious token causes version evidence to resolve to Java 21 and overrides the configured default Java 25 scope.
- Context headers:
ChatService.buildContextSegments embeds requestedVersions="6" in the source-record header for Java docs, matching the “adjacent-same-family” pathway.
Recommended Fix
Extend the suffix pattern and add test cases:
private static final Pattern EXPLICIT_QUANTITY_SUFFIX_PATTERN =
Pattern.compile("[\\s-]+(?:days?|hours?|minutes?|seconds?|times|lines?|weeks?|months?|years?)\\b", Pattern.CASE_INSENSITIVE); // <-- FIX 🟢 add weeks?|months?|years?
Caveat: this expands existing word-hyphen false positives (already present for days?) to new noun-hyphen compounds such as Java N year-ahead / month-release / week-long.
History
This bug was introduced in commit cacf649. The commit added the new EXPLICIT_QUANTITY_SUFFIX_PATTERN filter (along with its region-based check in extractVersionNumbers) to reject quantity phrases like "Java 100 days of practice" while preserving genuine release requests like "Java 21"; however, the original regex enumerated only days?|hours?|minutes?|seconds?|times|lines? and never included the longer duration units months?|weeks?|years?, so the incompleteness was present from the moment the filter was first created rather than being introduced by a later edit.
Detail Bug Report
https://app.detail.dev/org_befd6425-a158-4e24-9d4d-1e5c08769515/bugs/bug_cbeea9a2-5f20-431d-b7dc-1fd583a4c9c5
Introduced in cacf649 by @WilliamAGH on Sep 1, 2026
Summary
QueryVersionExtractor.extractVersionNumbersparses learner queries to find Java release versions. It has three production callers: (1)RetrievalService.queryVersionEvidencescopes Java API documentation retrieval from its result (RetrievalService.java:656,:669) on the default chat path; (2)ChatService.buildContextSegmentscallsextractVersionNumbersagain directly (ChatService.java:279) to label per-document source-record headers; (3)GuidedLearningService.buildStructuredGuidedPromptWithContextcalls it (GuidedLearningService.java:236) to choose retrieval context doc sets on the guided-learning path.QueryVersionExtractor.boostQueryWithVersionContextalso rewrites the hybrid-search query from the retained tokens (RetrievalService.java:354→QueryVersionExtractor.java:62-65).EXPLICIT_QUANTITY_SUFFIX_PATTERNadded by commitcacf6493to rejectJava <N> <time-unit>quantity phrases omits the most common time units —years,weeks,months— while rejectingdays?|hours?|minutes?|seconds?|times|lines?.switched to Java 6 months agoextracts[�"6�]as a Java release. The expected behavior is[]. The report's basis for "expected" is an inference (see "Evidence: hypothesised intent, not evidenced"), not a stated rule.dev-javasource (Oracle's external tutorial content fromdev.java/learn/) and are narrowed tojava/java21-complete(API reference, v21) instead ofdev-java+java/java25-complete. The lesson's own prose tutorial — the curated markdown atsrc/main/resources/guided/lessons/<slug>.md— is loaded unconditionally and prioritisedHIGHregardless of the bug (see "Guided-learning path: what is and isn't lost"). So the consequence is a degradation of retrieval-supplement diversity (tutorial+API → API-only), not a loss of all tutorial prose.requestedVersions="6"header is injected into the LLM context, byte-for-byte identical to what the system intentionally emits for a genuine out-of-rangeJava 6request — the bug changes whether that path is taken, not what it emits.Code with Bug
Explanation
extractVersionNumbersfirst matchesJava|JDK ... <digits>and then usesEXPLICIT_QUANTITY_SUFFIX_PATTERNto skip extraction when the digits are immediately followed by a “quantity noun” (e.g.,Java 100 days of practice). Because the suffix pattern does not includemonths|weeks|years, phrases likeJava 6 months agoare not recognized as quantity phrases and the digits are retained as a requested Java version.This spurious token is then consumed by multiple flows:
requestedVersionsbecomes non-empty, soeffectiveDocSetsFor(...)replaces the lesson’s normal doc sets (dev-java+java/java25-complete) with Java API-only doc sets resolved from the spurious version (ultimatelyjava/java21-complete), reducing retrieved supplement diversity.ChatService.buildContextSegmentsembedsrequestedVersions="6"in the source-record header for Java docs, matching the “adjacent-same-family” pathway.Recommended Fix
Extend the suffix pattern and add test cases:
Caveat: this expands existing word-hyphen false positives (already present for
days?) to new noun-hyphen compounds such asJava N year-ahead/month-release/week-long.History
This bug was introduced in commit cacf649. The commit added the new
EXPLICIT_QUANTITY_SUFFIX_PATTERNfilter (along with its region-based check inextractVersionNumbers) to reject quantity phrases like "Java 100 days of practice" while preserving genuine release requests like "Java 21"; however, the original regex enumerated onlydays?|hours?|minutes?|seconds?|times|lines?and never included the longer duration unitsmonths?|weeks?|years?, so the incompleteness was present from the moment the filter was first created rather than being introduced by a later edit.