Skip to content

fix(search): preserve exact Javadoc member citations#114

Open
WilliamAGH wants to merge 41 commits into
mainfrom
dev
Open

fix(search): preserve exact Javadoc member citations#114
WilliamAGH wants to merge 41 commits into
mainfrom
dev

Conversation

@WilliamAGH

Copy link
Copy Markdown
Owner

Outcome

  • extracts canonical Oracle Javadoc member sections and persists exact DOM anchors separately from fragmentless page URLs
  • removes heuristic Javadoc URL/member rewriting so citations always use ingested source identity
  • makes remote and local reindexing atomic and exact by comparing deterministic Qdrant point IDs, upserting complete replacements before deleting obsolete points, and failing closed on ambiguous marker cleanup
  • excludes class-use and redirect-backed root type vectors, including an idempotent production prune before Java API ingestion
  • reconciles Java 21/24/25 mirrors against release-correct seed inventories and bulk-projects mirror paths
  • introduces a narrow documentation-ingestion application boundary for CLI and web callers

Production migration

After deployment, run the Java 21/24/25 mirror ingestion. The pipeline prunes retired class-use/root redirect vectors first, then reindexes all governed Javadoc pages with exact anchors.

Verification

  • make build
  • make test
  • make lint
  • documentation fetch projection tests
  • Java API fetch projection tests
  • documentation seed tests
  • retired Java API vector prune tests
  • exact Java 21/24/25 mirror verification: 5,443 / 5,710 / 5,723 pages
  • independent final review: approved with no P0/P1/P2 findings

Copilot AI review requested due to automatic review settings July 18, 2026 18:33
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 217 files, which is 117 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ca33b93a-f8bd-40a1-b36f-dd580d5bbb70

📥 Commits

Reviewing files that changed from the base of the PR and between 1263e64 and 1d90481.

📒 Files selected for processing (247)
  • .env.example
  • .github/workflows/build.yml
  • AGENTS.md
  • Dockerfile
  • Makefile
  • README.md
  • build.gradle.kts
  • config/spotbugs/spotbugs-exclude.xml
  • docs/api.md
  • docs/architecture.md
  • docs/configuration.md
  • docs/contracts/code-change.md
  • docs/development.md
  • docs/domains/all-parsing-and-markdown-logic.md
  • docs/domains/local-store-directories.md
  • docs/getting-started.md
  • docs/github-repository-ingestion.md
  • docs/ingestion.md
  • docs/pipeline-commands.md
  • docs/retrieval-pipeline.md
  • docs/type-safety-zod-validation.md
  • frontend/rules/ast-grep/domain-types-in-schemas.yml
  • frontend/rules/ast-grep/no-core-record-unknown.yml
  • frontend/rules/ast-grep/no-domain-record-cast.yml
  • frontend/rules/ast-grep/no-record-string-unknown.yml
  • frontend/rules/ast-grep/no-zod-loose-types.yml
  • frontend/rules/ast-grep/types-are-not-schemas.yml
  • frontend/rules/ast-grep/warn-broken-contract-union.yml
  • frontend/src/lib/components/ChatView.svelte
  • frontend/src/lib/components/ChatView.test.ts
  • frontend/src/lib/components/LearnView.ownership.test.ts
  • frontend/src/lib/components/LearnView.svelte
  • frontend/src/lib/components/LearnView.test.ts
  • frontend/src/lib/components/MessageBubble.svelte
  • frontend/src/lib/components/MessageBubble.test.ts
  • frontend/src/lib/composables/createStreamingState.svelte.ts
  • frontend/src/lib/services/chat.test.ts
  • frontend/src/lib/services/chat.ts
  • frontend/src/lib/services/markdown.test.ts
  • frontend/src/lib/services/markdown.ts
  • frontend/src/lib/services/sse.test.ts
  • frontend/src/lib/validation/schemas.ts
  • frontend/src/lib/validation/validate.ts
  • frontend/src/test/citationPartialFailureStatus.ts
  • frontend/vite.config.ts
  • frontend/vitest.config.ts
  • gradle/libs.versions.toml
  • infra/docker-compose-qdrant.yml
  • scripts/atomic_exchange_directories.py
  • scripts/documentation_seed.py
  • scripts/fetch_all_docs.sh
  • scripts/lib/common_qdrant.sh
  • scripts/lib/documentation_fetch_metadata.sh
  • scripts/lib/documentation_fetch_sources.sh
  • scripts/lib/documentation_seed_mirrors.sh
  • scripts/lib/documentation_sources.sh
  • scripts/lib/embedding_preflight.sh
  • scripts/lib/github_identity.sh
  • scripts/migrate_qdrant_cloud_to_local.sh
  • scripts/monitor_indexing.sh
  • scripts/monitor_progress.sh
  • scripts/process_all_to_qdrant.sh
  • scripts/process_github_repo.sh
  • scripts/prune_retired_java_api_vectors.sh
  • scripts/test_documentation_fetch_projection.sh
  • scripts/test_documentation_fetch_publication.sh
  • scripts/test_documentation_seed.py
  • scripts/test_embedding_preflight.sh
  • scripts/test_github_sync_failure_contract.sh
  • scripts/test_java_api_fetch_projection.sh
  • scripts/test_process_all_to_qdrant_environment.sh
  • scripts/test_process_all_to_qdrant_postconditions.sh
  • scripts/test_prune_retired_java_api_vectors.sh
  • scripts/test_qdrant_1_18_integration.sh
  • scripts/test_single_index.sh
  • scripts/update_all_github_repos.sh
  • src/main/java/com/williamcallahan/javachat/application/ingestion/DocumentationIngestionUseCase.java
  • src/main/java/com/williamcallahan/javachat/application/ingestion/FileLimit.java
  • src/main/java/com/williamcallahan/javachat/application/ingestion/PageLimit.java
  • src/main/java/com/williamcallahan/javachat/application/search/JavaApiMethodSelector.java
  • src/main/java/com/williamcallahan/javachat/application/search/JavaInvocationSignature.java
  • src/main/java/com/williamcallahan/javachat/cli/DocumentProcessor.java
  • src/main/java/com/williamcallahan/javachat/cli/DocumentationSet.java
  • src/main/java/com/williamcallahan/javachat/cli/DocumentationSetCatalog.java
  • src/main/java/com/williamcallahan/javachat/cli/GitHubRepoProcessor.java
  • src/main/java/com/williamcallahan/javachat/config/AppProperties.java
  • src/main/java/com/williamcallahan/javachat/config/DocsLocalPathMapper.java
  • src/main/java/com/williamcallahan/javachat/config/DocsSourceRegistry.java
  • src/main/java/com/williamcallahan/javachat/config/DocumentationConfig.java
  • src/main/java/com/williamcallahan/javachat/config/DocumentationManifestFieldRules.java
  • src/main/java/com/williamcallahan/javachat/config/DocumentationSeedDocumentTypeCatalog.java
  • src/main/java/com/williamcallahan/javachat/config/DocumentationSourceManifest.java
  • src/main/java/com/williamcallahan/javachat/config/EmbeddingConfig.java
  • src/main/java/com/williamcallahan/javachat/config/JavaApiDocumentationManifest.java
  • src/main/java/com/williamcallahan/javachat/config/LocalEmbedding.java
  • src/main/java/com/williamcallahan/javachat/config/QdrantCollectionNames.java
  • src/main/java/com/williamcallahan/javachat/config/QdrantGitHubCollectionDiscovery.java
  • src/main/java/com/williamcallahan/javachat/config/QdrantHealthIndicator.java
  • src/main/java/com/williamcallahan/javachat/config/QdrantIndexInitializer.java
  • src/main/java/com/williamcallahan/javachat/config/QdrantRestConnection.java
  • src/main/java/com/williamcallahan/javachat/config/RemoteEmbedding.java
  • src/main/java/com/williamcallahan/javachat/config/SecurityConfig.java
  • src/main/java/com/williamcallahan/javachat/config/SpringDocsUrlNormalizer.java
  • src/main/java/com/williamcallahan/javachat/config/SystemPromptConfig.java
  • src/main/java/com/williamcallahan/javachat/domain/javaapi/JavadocMemberAnchor.java
  • src/main/java/com/williamcallahan/javachat/domain/markdown/EnrichmentKindCatalog.java
  • src/main/java/com/williamcallahan/javachat/domain/markdown/MarkdownEnrichment.java
  • src/main/java/com/williamcallahan/javachat/model/GuidedLesson.java
  • src/main/java/com/williamcallahan/javachat/service/AuditService.java
  • src/main/java/com/williamcallahan/javachat/service/ChatService.java
  • src/main/java/com/williamcallahan/javachat/service/ChunkProcessingService.java
  • src/main/java/com/williamcallahan/javachat/service/CitationCandidateRanker.java
  • src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java
  • src/main/java/com/williamcallahan/javachat/service/DocumentFactory.java
  • src/main/java/com/williamcallahan/javachat/service/EmbeddingBatchEmbedder.java
  • src/main/java/com/williamcallahan/javachat/service/EmbeddingModelKeepAlive.java
  • src/main/java/com/williamcallahan/javachat/service/ExternalServiceHealth.java
  • src/main/java/com/williamcallahan/javachat/service/FileIngestionMarkerStore.java
  • src/main/java/com/williamcallahan/javachat/service/GuidedLearningService.java
  • src/main/java/com/williamcallahan/javachat/service/GuidedTOCProvider.java
  • src/main/java/com/williamcallahan/javachat/service/HtmlContentExtractor.java
  • src/main/java/com/williamcallahan/javachat/service/HybridSearchService.java
  • src/main/java/com/williamcallahan/javachat/service/HybridVectorService.java
  • src/main/java/com/williamcallahan/javachat/service/JavaApiAnchoredSection.java
  • src/main/java/com/williamcallahan/javachat/service/LocalStoreService.java
  • src/main/java/com/williamcallahan/javachat/service/OpenAIStreamingService.java
  • src/main/java/com/williamcallahan/javachat/service/OpenAiCompatibleEmbeddingClient.java
  • src/main/java/com/williamcallahan/javachat/service/OpenAiProviderRoutingService.java
  • src/main/java/com/williamcallahan/javachat/service/OpenAiRequestFactory.java
  • src/main/java/com/williamcallahan/javachat/service/OpenAiResponseStreamException.java
  • src/main/java/com/williamcallahan/javachat/service/ProgressTracker.java
  • src/main/java/com/williamcallahan/javachat/service/QdrantPayloadFieldSchema.java
  • src/main/java/com/williamcallahan/javachat/service/QdrantRetrievalConstraintBuilder.java
  • src/main/java/com/williamcallahan/javachat/service/RetrievalConstraint.java
  • src/main/java/com/williamcallahan/javachat/service/RetrievalService.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneService.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/IngestionProvenanceDeriver.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/IngestionQuarantineService.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/IngestionStorageServices.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/JavaPackageExtractor.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsDirectoryIngestionService.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/SourceCodeFileIngestionProcessor.java
  • src/main/java/com/williamcallahan/javachat/service/markdown/CitationProcessor.java
  • src/main/java/com/williamcallahan/javachat/service/markdown/EnrichmentPlaceholderizer.java
  • src/main/java/com/williamcallahan/javachat/support/JavaApiPageExtractor.java
  • src/main/java/com/williamcallahan/javachat/util/QueryVersionExtractor.java
  • src/main/java/com/williamcallahan/javachat/web/ChatController.java
  • src/main/java/com/williamcallahan/javachat/web/IngestionController.java
  • src/main/java/com/williamcallahan/javachat/web/SseStatusContractCatalog.java
  • src/main/java/com/williamcallahan/javachat/web/SseSupport.java
  • src/main/resources/application.properties
  • src/main/resources/docs-sources.properties
  • src/main/resources/documentation-seed-document-types.manifest
  • src/main/resources/documentation-sources.manifest
  • src/main/resources/enrichment-kinds.manifest
  • src/main/resources/guided/lessons/building-rest-apis-with-spring-boot.md
  • src/main/resources/guided/lessons/choosing-a-jvm-language.md
  • src/main/resources/guided/lessons/clojure-on-the-jvm.md
  • src/main/resources/guided/lessons/collections.md
  • src/main/resources/guided/lessons/data-access-and-testing-in-spring-boot.md
  • src/main/resources/guided/lessons/dependency-injection-and-configuration.md
  • src/main/resources/guided/lessons/groovy-on-the-jvm.md
  • src/main/resources/guided/lessons/interfaces-and-inheritance.md
  • src/main/resources/guided/lessons/modules.md
  • src/main/resources/guided/lessons/quarkus-fundamentals.md
  • src/main/resources/guided/lessons/spring-boot-fundamentals.md
  • src/main/resources/guided/lessons/spring-boot-vs-quarkus.md
  • src/main/resources/java-api-documentation-sources.manifest
  • src/main/resources/sse-status-contracts.json
  • src/test/java/com/williamcallahan/javachat/ExtractorQualityTest.java
  • src/test/java/com/williamcallahan/javachat/JavaChatApplicationTests.java
  • src/test/java/com/williamcallahan/javachat/StandaloneExtractionTest.java
  • src/test/java/com/williamcallahan/javachat/application/ingestion/IngestionLimitTest.java
  • src/test/java/com/williamcallahan/javachat/application/search/JavaApiMethodSelectorTest.java
  • src/test/java/com/williamcallahan/javachat/application/search/JavaInvocationSignatureTest.java
  • src/test/java/com/williamcallahan/javachat/cli/DocumentProcessorFailureContractTest.java
  • src/test/java/com/williamcallahan/javachat/cli/DocumentProcessorSelectionTest.java
  • src/test/java/com/williamcallahan/javachat/cli/DocumentationSourceCatalogParityTest.java
  • src/test/java/com/williamcallahan/javachat/cli/GitHubRepoProcessorIsolationTest.java
  • src/test/java/com/williamcallahan/javachat/cli/JavaApiDocumentationSourceParityTest.java
  • src/test/java/com/williamcallahan/javachat/config/AppPropertiesValidationTest.java
  • src/test/java/com/williamcallahan/javachat/config/DocsSourceRegistryTest.java
  • src/test/java/com/williamcallahan/javachat/config/DocumentationManifestFieldRulesTest.java
  • src/test/java/com/williamcallahan/javachat/config/DocumentationSourceManifestTest.java
  • src/test/java/com/williamcallahan/javachat/config/EmbeddingConfigStartupTest.java
  • src/test/java/com/williamcallahan/javachat/config/JavaApiDocumentationManifestTest.java
  • src/test/java/com/williamcallahan/javachat/config/QdrantGitHubCollectionDiscoveryTest.java
  • src/test/java/com/williamcallahan/javachat/config/QdrantHealthIndicatorTest.java
  • src/test/java/com/williamcallahan/javachat/config/QdrantIndexInitializerTest.java
  • src/test/java/com/williamcallahan/javachat/config/QdrantRestConnectionTest.java
  • src/test/java/com/williamcallahan/javachat/config/SecurityConfigNonWebStartupTest.java
  • src/test/java/com/williamcallahan/javachat/config/SystemPromptConfigTest.java
  • src/test/java/com/williamcallahan/javachat/domain/ingestion/GitHubCollectionNamingScriptTest.java
  • src/test/java/com/williamcallahan/javachat/domain/javaapi/JavadocMemberAnchorTest.java
  • src/test/java/com/williamcallahan/javachat/domain/markdown/EnrichmentKindCatalogTest.java
  • src/test/java/com/williamcallahan/javachat/domain/markdown/MarkdownEnrichmentTest.java
  • src/test/java/com/williamcallahan/javachat/service/AuditServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/ChunkProcessingServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/CitationCandidateRankerTest.java
  • src/test/java/com/williamcallahan/javachat/service/DocsIngestionServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/DocumentFactoryTest.java
  • src/test/java/com/williamcallahan/javachat/service/EmbeddingBatchEmbedderTest.java
  • src/test/java/com/williamcallahan/javachat/service/EmbeddingProviderFailureTest.java
  • src/test/java/com/williamcallahan/javachat/service/EnrichmentServiceCacheTest.java
  • src/test/java/com/williamcallahan/javachat/service/ExternalServiceHealthTest.java
  • src/test/java/com/williamcallahan/javachat/service/GuidedLearningServiceCitationTest.java
  • src/test/java/com/williamcallahan/javachat/service/GuidedLessonCuratedContentTest.java
  • src/test/java/com/williamcallahan/javachat/service/GuidedTOCProviderTest.java
  • src/test/java/com/williamcallahan/javachat/service/HtmlContentExtractorTest.java
  • src/test/java/com/williamcallahan/javachat/service/HybridSearchServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/HybridVectorServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/LocalStoreServiceFileMarkerTest.java
  • src/test/java/com/williamcallahan/javachat/service/LocalStoreServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/MarkdownServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/OpenAIStreamingProviderFailureTest.java
  • src/test/java/com/williamcallahan/javachat/service/OpenAIStreamingServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/OpenAiCompatibleEmbeddingClientTest.java
  • src/test/java/com/williamcallahan/javachat/service/OpenAiCompatibleEmbeddingClientWireTest.java
  • src/test/java/com/williamcallahan/javachat/service/OpenAiRequestFactoryTest.java
  • src/test/java/com/williamcallahan/javachat/service/QdrantRetrievalConstraintBuilderTest.java
  • src/test/java/com/williamcallahan/javachat/service/QdrantScoredPointDocumentMapperTest.java
  • src/test/java/com/williamcallahan/javachat/service/RetrievalConstraintTest.java
  • src/test/java/com/williamcallahan/javachat/service/RetrievalServiceCitationTest.java
  • src/test/java/com/williamcallahan/javachat/service/RetrievalServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/IngestionProvenanceDeriverTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/IngestionQuarantineServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/JavaPackageExtractorTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/LocalDocsDirectoryIngestionServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessorTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/MalformedUtf8LocalDocsIngestionTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/SourceCodeFileIngestionProcessorTest.java
  • src/test/java/com/williamcallahan/javachat/service/markdown/EnrichmentPlaceholderizerTest.java
  • src/test/java/com/williamcallahan/javachat/support/EnvironmentVariablePrecedenceTest.java
  • src/test/java/com/williamcallahan/javachat/util/QueryVersionExtractorTest.java
  • src/test/java/com/williamcallahan/javachat/web/ChatControllerRetrievalDiagnosticsTest.java
  • src/test/java/com/williamcallahan/javachat/web/ChatControllerStreamingFailureTest.java
  • src/test/java/com/williamcallahan/javachat/web/ChatPreparationSseIntegrationTest.java
  • src/test/java/com/williamcallahan/javachat/web/GuidedLearningControllerBackpressureOverflowTest.java
  • src/test/java/com/williamcallahan/javachat/web/GuidedLearningControllerCuratedContentTest.java
  • src/test/java/com/williamcallahan/javachat/web/GuidedLearningControllerStreamingFailureTest.java
  • src/test/java/com/williamcallahan/javachat/web/GuidedSseCitationEventTest.java
  • src/test/java/com/williamcallahan/javachat/web/IngestionControllerTest.java
  • src/test/java/com/williamcallahan/javachat/web/SseStatusContractCatalogTest.java
  • src/test/java/com/williamcallahan/javachat/web/SseSupportTest.java
  • src/test/resources/application-test.properties

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
📝 Walkthrough

Walkthrough

The pull request adds canonical documentation-source selection, batch Java API seed projection, release-aware Javadoc seeding, retired-vector pruning, structured Java API extraction with exact anchors, replacement-aware ingestion, and updated citation metadata handling with extensive tests.

Changes

Documentation pipeline

Layer / File(s) Summary
Canonical selection and cleanup
scripts/fetch_all_docs.sh, scripts/prune_retired_java_api_vectors.sh, scripts/process_all_to_qdrant.sh
Adds canonical cross-manifest selectors and pre-ingestion Qdrant pruning with batched deletion and verification.
Seed generation and documentation
scripts/documentation_seed.py, scripts/lib/documentation_seed_mirrors.sh, scripts/oracle_javadoc_seed.py, docs/pipeline-commands.md, src/main/resources/java-api-documentation-sources.manifest
Adds batch mirror projection, release-specific Javadoc roots, excludes class-use URLs, updates selector documentation, and lowers Java API HTML thresholds.

Java API ingestion

Layer / File(s) Summary
Structured extraction and chunk metadata
src/main/java/com/williamcallahan/javachat/service/HtmlContentExtractor.java, ChunkProcessingService.java, DocumentFactory.java, JavaApi*.java
Extracts overview and member sections with exact DOM anchors and carries anchors through validated chunk metadata and hashing.
Replacement-aware storage
src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java, HybridVectorService.java, LocalStoreService.java, ingestion/*
Adds deterministic point-identity checks, complete URL replacement, obsolete marker/chunk pruning, and Java API-specific local ingestion behavior.
Application wiring
src/main/java/com/williamcallahan/javachat/application/ingestion/DocumentationIngestionUseCase.java, cli/DocumentProcessor.java, web/IngestionController.java
Introduces the ingestion use-case boundary and wires CLI and web entry points to it.

Validation

Layer / File(s) Summary
Regression and integration coverage
scripts/test_*, src/test/java/com/williamcallahan/javachat/service/*, src/test/java/com/williamcallahan/javachat/service/ingestion/*
Tests selector routing, seed generation, extraction immutability, exact anchors, replacement identity, pruning, citation behavior, and ingestion failure handling.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

  • WilliamAGH/java-chat issue 95 — covers the same Javadoc anchor citation behavior updated in RetrievalService.

Possibly related PRs

Suggested labels: bug, documentation, java, refactor

Suggested reviewers: copilot

Poem

Anchors bloom where Javadocs flow,
Old vectors fade, new chunks grow.
Select a source, inspect the page,
Qdrant turns a cleaner age.
Seeds march on, precise and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the core change: preserving exact Javadoc member citations instead of heuristic rewriting.
Description check ✅ Passed The description is detailed and directly aligned with the PR’s Javadoc citation, ingestion, and mirror-pruning changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added bug Something isn't working documentation Improvements or additions to documentation java Pull requests that update java code refactor Code refactoring labels Jul 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown

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 updates the documentation ingestion and retrieval pipeline to preserve exact Oracle Javadoc member anchors as first-class metadata (separate from fragmentless page URLs), and makes both remote and local reindexing more deterministic/atomic by replacing URL-scoped Qdrant point sets based on stable point IDs rather than point counts.

Changes:

  • Introduces structured Java API extraction (JavaApiPageExtraction) that keeps overview text separate from anchored member sections, and threads an exact anchor metadata field through chunking → storage → citation rendering.
  • Replaces heuristic Javadoc URL/member rewriting with “use ingested source identity” behavior, and adds URL replacement semantics in Qdrant (replaceUrlDocuments) plus exact point-ID coverage checks.
  • Adds strict retired-Java-API vector pruning (class-use pages + redirect-backed root type pages) and strengthens fetch/seed tooling around canonical selector identities.

Reviewed changes

Copilot reviewed 43 out of 43 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/test/java/com/williamcallahan/javachat/util/JavadocTypeCanonicalizerTest.java Removes tests for heuristic member/type canonicalization (feature removed).
src/test/java/com/williamcallahan/javachat/StandaloneExtractionTest.java Updates diagnostics to use extractJavaApiPage(...).combinedText().
src/test/java/com/williamcallahan/javachat/service/RetrievalServiceCitationTest.java Updates citation tests for exact-anchor metadata behavior and de-heuristicization.
src/test/java/com/williamcallahan/javachat/service/LocalStoreServiceTest.java Adds coverage for deleting obsolete ingestion markers by stored hash prefixes.
src/test/java/com/williamcallahan/javachat/service/ingestion/MalformedUtf8LocalDocsIngestionTest.java Adjusts malformed UTF-8 behavior expectations to account for prune boundary changes.
src/test/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneServiceTest.java Adds tests for preserving replacement parsed chunks and hash-prefix marker cleanup.
src/test/java/com/williamcallahan/javachat/service/HybridVectorServiceTest.java Adds tests for exact point-id coverage and atomic URL replacement semantics.
src/test/java/com/williamcallahan/javachat/service/HtmlContentExtractorTest.java Adds tests for exact DOM anchors, class-use exclusion, and non-mutating extraction.
src/test/java/com/williamcallahan/javachat/service/DocsIngestionServiceTest.java Adds tests for fragmentless crawl, Java API segmentation, replacement logic, and class-use deletion.
src/test/java/com/williamcallahan/javachat/service/ChunkProcessingServiceTest.java Adds tests for Java API page segmentation, anchor hashing, and fragmentless URL validation.
src/test/java/com/williamcallahan/javachat/ExtractorQualityTest.java Updates extraction quality checks to use the new Java API extraction shape.
src/main/resources/java-api-documentation-sources.manifest Adjusts minimum HTML file thresholds for governed Java API mirrors.
src/main/java/com/williamcallahan/javachat/web/IngestionController.java Routes ingestion through a new application boundary (DocumentationIngestionUseCase).
src/main/java/com/williamcallahan/javachat/util/JavadocTypeCanonicalizer.java Removes heuristic type canonicalizer (no longer used).
src/main/java/com/williamcallahan/javachat/util/JavadocNestedTypeResolver.java Removes heuristic nested-type URL refinement.
src/main/java/com/williamcallahan/javachat/util/JavadocMemberAnchorResolver.java Removes heuristic member-anchor derivation.
src/main/java/com/williamcallahan/javachat/util/JavadocLinkResolver.java Removes heuristic Javadoc link resolver facade.
src/main/java/com/williamcallahan/javachat/service/RetrievalService.java Switches citations to use ingested exact-anchor metadata and canonicalizes URLs accordingly.
src/main/java/com/williamcallahan/javachat/service/QdrantPayloadFieldSchema.java Adds ANCHOR_FIELD to the canonical Qdrant metadata schema.
src/main/java/com/williamcallahan/javachat/service/LocalStoreService.java Adds strict deletion of obsolete chunk markers selected by stored hash prefixes.
src/main/java/com/williamcallahan/javachat/service/JavaApiPageExtraction.java New record representing overview + anchored member extraction for Java API pages.
src/main/java/com/williamcallahan/javachat/service/JavaApiPageDisposition.java New enum classifying whether Java API pages are indexable (e.g., class-use excluded).
src/main/java/com/williamcallahan/javachat/service/JavaApiAnchoredSection.java New record preserving one authoritative member anchor + member text.
src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java Moves to exact-point-id coverage checks and Java API structured ingestion + exclusion handling.
src/main/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneService.java Adds “prune obsolete state after replacement” path (vectors + markers + parsed chunks).
src/main/java/com/williamcallahan/javachat/service/HybridVectorService.java Adds atomic URL replacement and exact point-id coverage checks via Qdrant scroll identity.
src/main/java/com/williamcallahan/javachat/service/HtmlContentExtractor.java Adds structured Java API extraction (exact DOM anchors, class-use exclusion) and avoids mutation via cloning.
src/main/java/com/williamcallahan/javachat/service/DocumentFactory.java Introduces canonical chunk metadata record including optional exact anchor field.
src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java Implements new ingestion use case boundary; adds fragmentless crawling + URL replacement ingestion flow.
src/main/java/com/williamcallahan/javachat/service/ChunkProcessingService.java Adds Java API page chunking with anchor-aware deterministic hashing and global chunk indexing.
src/main/java/com/williamcallahan/javachat/cli/DocumentProcessor.java Depends on DocumentationIngestionUseCase instead of concrete service.
src/main/java/com/williamcallahan/javachat/application/ingestion/DocumentationIngestionUseCase.java New application boundary interface for ingestion runs.
scripts/test_prune_retired_java_api_vectors.sh New script-level test harness for retired Java API vector pruning without live Qdrant.
scripts/test_java_api_fetch_projection.sh Extends tests to verify selector routing between non-Java docs and Java API projections.
scripts/test_documentation_seed.py Adds tests for batch mirror-path projection and Oracle Javadoc seed constraints.
scripts/prune_retired_java_api_vectors.sh New strict pruning script for retired Java API vectors (class-use + redirect-backed roots).
scripts/process_all_to_qdrant.sh Runs retired Java API prune before ingestion based on effective selector.
scripts/oracle_javadoc_seed.py Makes root-page seed inventory release-correct; removes class-use seed generation.
scripts/lib/documentation_seed_mirrors.sh Switches to batch mirror-path projection for Java API seeds.
scripts/fetch_all_docs.sh Strengthens --doc-sets to select canonical identities across both manifests before fetching.
scripts/documentation_seed.py Adds --project-mirror-paths-file for batch projection and collision validation.
docs/pipeline-commands.md Updates docs for the new selector semantics and adds examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +274 to +279
private static boolean belongsToReplacement(
ParsedChunkReference parsedChunkReference, Set<String> replacementHashSet) {
return replacementHashSet.stream()
.anyMatch(replacementChunkHash ->
replacementChunkHash.startsWith(parsedChunkReference.storedChunkHashPrefix()));
}
Comment on lines 474 to 476
/**
* Refines a raw document URL and gates Javadoc member anchors to {@code api-docs} metadata.
*
* Projects an authoritative ingested Javadoc anchor before applying legacy nested-type refinement.
*/

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java (2)

341-350: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Return a typed marker-transition failure on the skipped path.

markFileIngested wraps write failures in IllegalStateException, but this call is outside a catch block. A marker filesystem error therefore escapes process and can abort the batch instead of returning a failed LocalDocsFileOutcome.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java`
around lines 341 - 350, Update the skipped-file path in process around
markFileIngested so marker filesystem failures are caught and converted into the
typed failed LocalDocsFileOutcome, matching the processor’s existing failure
handling. Preserve the skip logging and successful marker update behavior, and
ensure the exception does not escape process or abort the batch.

361-614: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Extract the newly added workflows from the two monolithic services.

  • src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java#L361-L614: move marker/reindex policy and replacement persistence into focused application components.
  • src/main/java/com/williamcallahan/javachat/service/HybridVectorService.java#L401-L484: move URL-scoped scrolling, identity reconciliation, and obsolete-point deletion into a focused Qdrant component.

As per coding guidelines, “>500 LOC is a monolith. Extract pieces you touch into clean-architecture roots (Large Files).”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java`
around lines 361 - 614, Extract the marker/reindex policy and replacement
persistence workflow from LocalDocsFileIngestionProcessor methods
inspectExistingMarker, inspectUnmarkedVectors, supersededCollectionNames,
processDocuments, storeDocuments, and marker methods into focused application
components, updating the processor to delegate while preserving behavior. Also
update
src/main/java/com/williamcallahan/javachat/service/HybridVectorService.java
lines 401-484 by extracting URL-scoped scrolling, identity reconciliation, and
obsolete-point deletion into a focused Qdrant component, with
HybridVectorService delegating to it; both sites require these extractions
without changing existing outcomes.

Source: Coding guidelines

src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java (1)

183-205: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate every hash before replacing the Qdrant corpus.

Line 197 silently skips missing hash metadata after Qdrant has already been replaced, leaving local markers inconsistent. Build and validate all marker inputs before the external mutation; fail the run if any replacement document lacks its hash.

As per coding guidelines, “Use typed exception handling patterns; propagate meaningful errors, never swallow silently.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java`
around lines 183 - 205, The replaceAndMarkDocuments flow must validate every
replacement document’s hash before calling
hybridVectorService.replaceUrlDocuments. Update markDocumentsIngested or
introduce a validation step to reject any document missing
QdrantPayloadFieldSchema.HASH_FIELD, propagating a meaningful typed exception
instead of silently continuing; only perform the Qdrant replacement after
validation succeeds.

Source: Coding guidelines

🧹 Nitpick comments (1)
src/test/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessorTest.java (1)

620-649: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the six-argument helper with a test fixture object.

The added overload extends an already long positional collaborator train, making call-site mistakes increasingly easy. Bundle these dependencies into a named test fixture or builder.

As per coding guidelines, “>4 parameters use parameter object or builder; never add 5th positional argument.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessorTest.java`
around lines 620 - 649, Replace the overloaded six-argument
createIngestionProcessor helpers with a named test fixture or builder that
groups the collaborator dependencies, including quarantineService. Update all
call sites to construct or configure this fixture and pass it to
createIngestionProcessor, eliminating the positional parameter train while
preserving the existing default mock behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/pipeline-commands.md`:
- Around line 93-97: Update the Java API refresh example in the documentation to
obtain selector values from --list-java-api-sources instead of hard-coding the
current release list. Keep the example manifest-driven so future Java API
sources are included automatically, and remove the explicit
java/java21-complete, java/java24-complete, and java/java25-complete inventory.

In
`@src/main/java/com/williamcallahan/javachat/application/ingestion/DocumentationIngestionUseCase.java`:
- Line 15: Replace the raw int ingestion limits in
DocumentationIngestionUseCase.crawlAndIngest and its related API boundaries with
validated PageLimit and FileLimit records. Add constructor validation rejecting
zero or negative values, and update CLI, tests, and direct callers to construct
these records only after transport/input validation so ingestion always receives
valid application values.

In
`@src/main/java/com/williamcallahan/javachat/service/ChunkProcessingService.java`:
- Around line 375-406: Remove Optional-valued constructor inputs from the
segment models: in ChunkProcessingService.java lines 375-406, keep
JavaApiPageSegment construction behind the overview and member factories, and in
lines 436-452 retain any nullable anchor representation privately; callers must
not supply Optional. In DocumentFactory.java lines 167-230, preserve the
withAnchor and withoutAnchor factories while encapsulating absent-anchor
handling inside their implementation.

In
`@src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java`:
- Around line 254-260: Update fetchPageSnapshot to use a named maximum
response-size constant instead of maxBodySize(0), and configure jsoup to enforce
that cap. Ensure oversized responses fail the crawl before full body
materialization, while retaining the existing snapshot preparation for responses
within the limit.
- Around line 57-65: Update the DocsIngestionService constructor to inject
AppProperties instead of the `@Value` app.docs.root-url parameter, then initialize
the root URL from AppProperties.getDocs().getRootUrl(). Remove the direct `@Value`
wiring while leaving the other constructor dependencies unchanged.
- Around line 239-244: Update the link-discovery flow in DocsIngestionService
around removeUrlFragment to normalize the configured root and candidate URLs as
parsed origin/path components rather than relying on startsWith(rootUrl). Before
queueing or continuing any crawl, validate the final response URL after
redirects and reject URLs whose host, port, or path falls outside the configured
source boundary.

In
`@src/main/java/com/williamcallahan/javachat/service/HtmlContentExtractor.java`:
- Around line 28-33: Extract the Java API-specific page classification,
overview, anchor parsing, and member extraction logic from HtmlContentExtractor
into a new focused JavaApiPageExtractor under the project’s canonical
architecture root, placing its extraction contract alongside it or in an
adjacent canonical location. Update HtmlContentExtractor to delegate to this
component while retaining only generic HTML cleanup responsibilities, and
preserve the existing public behavior.

In
`@src/main/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneService.java`:
- Around line 120-132: In the cleanup flow containing parsedChunkReferences and
obsoleteChunkHashes, invoke deleteObsoleteChunkIngestionMarkersByHashPrefixes
before deleteChunkIngestionMarkers so ambiguous prefixes fail closed before any
exact-marker deletion occurs. Preserve the existing arguments and subsequent
deleteObsoleteParsedChunks call.

In
`@src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java`:
- Around line 287-326: The ingestion flow around chunkingOutcome.documents()
currently accepts partial results; update it to trigger the existing
force-processing path whenever chunkingOutcome.skippedChunks() is greater than
zero, not only when chunkingOutcome.skippedAllChunks() is true. Ensure the
complete forced document set is processed and its hashes recorded, while
retaining the current fast path for outcomes with no skipped chunks.

In
`@src/main/java/com/williamcallahan/javachat/service/JavaApiAnchoredSection.java`:
- Around line 14-30: Make JavadocMemberAnchor the single validated domain type
for exact DOM identifiers: add and validate this record in
JavaApiAnchoredSection.java, then change JavaApiAnchoredSection to accept it. In
ChunkProcessingService.java lines 464-471, remove the local anchor validator and
construct/use JavadocMemberAnchor. In DocumentFactory.java lines 240-245, remove
its duplicate validation and serialize the canonical anchor’s string value.

---

Outside diff comments:
In
`@src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java`:
- Around line 183-205: The replaceAndMarkDocuments flow must validate every
replacement document’s hash before calling
hybridVectorService.replaceUrlDocuments. Update markDocumentsIngested or
introduce a validation step to reject any document missing
QdrantPayloadFieldSchema.HASH_FIELD, propagating a meaningful typed exception
instead of silently continuing; only perform the Qdrant replacement after
validation succeeds.

In
`@src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java`:
- Around line 341-350: Update the skipped-file path in process around
markFileIngested so marker filesystem failures are caught and converted into the
typed failed LocalDocsFileOutcome, matching the processor’s existing failure
handling. Preserve the skip logging and successful marker update behavior, and
ensure the exception does not escape process or abort the batch.
- Around line 361-614: Extract the marker/reindex policy and replacement
persistence workflow from LocalDocsFileIngestionProcessor methods
inspectExistingMarker, inspectUnmarkedVectors, supersededCollectionNames,
processDocuments, storeDocuments, and marker methods into focused application
components, updating the processor to delegate while preserving behavior. Also
update
src/main/java/com/williamcallahan/javachat/service/HybridVectorService.java
lines 401-484 by extracting URL-scoped scrolling, identity reconciliation, and
obsolete-point deletion into a focused Qdrant component, with
HybridVectorService delegating to it; both sites require these extractions
without changing existing outcomes.

---

Nitpick comments:
In
`@src/test/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessorTest.java`:
- Around line 620-649: Replace the overloaded six-argument
createIngestionProcessor helpers with a named test fixture or builder that
groups the collaborator dependencies, including quarantineService. Update all
call sites to construct or configure this fixture and pass it to
createIngestionProcessor, eliminating the positional parameter train while
preserving the existing default mock behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7bf67b10-7722-4464-bfd6-25cac31e07f3

📥 Commits

Reviewing files that changed from the base of the PR and between 76420a2 and 1263e64.

📒 Files selected for processing (43)
  • docs/pipeline-commands.md
  • scripts/documentation_seed.py
  • scripts/fetch_all_docs.sh
  • scripts/lib/documentation_seed_mirrors.sh
  • scripts/oracle_javadoc_seed.py
  • scripts/process_all_to_qdrant.sh
  • scripts/prune_retired_java_api_vectors.sh
  • scripts/test_documentation_seed.py
  • scripts/test_java_api_fetch_projection.sh
  • scripts/test_prune_retired_java_api_vectors.sh
  • src/main/java/com/williamcallahan/javachat/application/ingestion/DocumentationIngestionUseCase.java
  • src/main/java/com/williamcallahan/javachat/cli/DocumentProcessor.java
  • src/main/java/com/williamcallahan/javachat/service/ChunkProcessingService.java
  • src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java
  • src/main/java/com/williamcallahan/javachat/service/DocumentFactory.java
  • src/main/java/com/williamcallahan/javachat/service/HtmlContentExtractor.java
  • src/main/java/com/williamcallahan/javachat/service/HybridVectorService.java
  • src/main/java/com/williamcallahan/javachat/service/JavaApiAnchoredSection.java
  • src/main/java/com/williamcallahan/javachat/service/JavaApiPageDisposition.java
  • src/main/java/com/williamcallahan/javachat/service/JavaApiPageExtraction.java
  • src/main/java/com/williamcallahan/javachat/service/LocalStoreService.java
  • src/main/java/com/williamcallahan/javachat/service/QdrantPayloadFieldSchema.java
  • src/main/java/com/williamcallahan/javachat/service/RetrievalService.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneService.java
  • src/main/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessor.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocLinkResolver.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocMemberAnchorResolver.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocNestedTypeResolver.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocTypeCanonicalizer.java
  • src/main/java/com/williamcallahan/javachat/web/IngestionController.java
  • src/main/resources/java-api-documentation-sources.manifest
  • src/test/java/com/williamcallahan/javachat/ExtractorQualityTest.java
  • src/test/java/com/williamcallahan/javachat/StandaloneExtractionTest.java
  • src/test/java/com/williamcallahan/javachat/service/ChunkProcessingServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/DocsIngestionServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/HtmlContentExtractorTest.java
  • src/test/java/com/williamcallahan/javachat/service/HybridVectorServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/LocalStoreServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/RetrievalServiceCitationTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneServiceTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/LocalDocsFileIngestionProcessorTest.java
  • src/test/java/com/williamcallahan/javachat/service/ingestion/MalformedUtf8LocalDocsIngestionTest.java
  • src/test/java/com/williamcallahan/javachat/util/JavadocTypeCanonicalizerTest.java
💤 Files with no reviewable changes (5)
  • src/main/java/com/williamcallahan/javachat/util/JavadocMemberAnchorResolver.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocLinkResolver.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocNestedTypeResolver.java
  • src/test/java/com/williamcallahan/javachat/util/JavadocTypeCanonicalizerTest.java
  • src/main/java/com/williamcallahan/javachat/util/JavadocTypeCanonicalizer.java

Comment thread docs/pipeline-commands.md
Comment thread src/main/java/com/williamcallahan/javachat/service/ChunkProcessingService.java Outdated
Comment thread src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java Outdated
Comment thread src/main/java/com/williamcallahan/javachat/service/DocsIngestionService.java Outdated
Comment thread src/main/java/com/williamcallahan/javachat/service/HtmlContentExtractor.java Outdated
Comment on lines +120 to +132
List<ParsedChunkReference> parsedChunkReferences = readParsedChunkReferences(sourceUrl);
Set<String> obsoleteChunkHashes = new LinkedHashSet<>();
if (previousFileRecord != null) {
obsoleteChunkHashes.addAll(previousFileRecord.chunkHashes());
}
obsoleteChunkHashes.removeAll(replacementHashSet);
if (!obsoleteChunkHashes.isEmpty()) {
localStoreService.deleteChunkIngestionMarkers(List.copyOf(obsoleteChunkHashes));
}
localStoreService.deleteObsoleteChunkIngestionMarkersByHashPrefixes(
obsoleteStoredHashPrefixes(parsedChunkReferences, replacementHashSet),
List.copyOf(replacementChunkHashes));
deleteObsoleteParsedChunks(parsedChunkReferences, replacementHashSet);

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Check prefix ambiguity before deleting any exact markers.

deleteChunkIngestionMarkers mutates state before deleteObsoleteChunkIngestionMarkersByHashPrefixes can reject an ambiguous prefix. If ambiguity is found, cleanup has already partially completed. Invoke the prefix-based fail-closed operation first, then delete remaining exact hashes.

Proposed ordering
-        if (!obsoleteChunkHashes.isEmpty()) {
-            localStoreService.deleteChunkIngestionMarkers(List.copyOf(obsoleteChunkHashes));
-        }
         localStoreService.deleteObsoleteChunkIngestionMarkersByHashPrefixes(
                 obsoleteStoredHashPrefixes(parsedChunkReferences, replacementHashSet),
                 List.copyOf(replacementChunkHashes));
+        if (!obsoleteChunkHashes.isEmpty()) {
+            localStoreService.deleteChunkIngestionMarkers(List.copyOf(obsoleteChunkHashes));
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
List<ParsedChunkReference> parsedChunkReferences = readParsedChunkReferences(sourceUrl);
Set<String> obsoleteChunkHashes = new LinkedHashSet<>();
if (previousFileRecord != null) {
obsoleteChunkHashes.addAll(previousFileRecord.chunkHashes());
}
obsoleteChunkHashes.removeAll(replacementHashSet);
if (!obsoleteChunkHashes.isEmpty()) {
localStoreService.deleteChunkIngestionMarkers(List.copyOf(obsoleteChunkHashes));
}
localStoreService.deleteObsoleteChunkIngestionMarkersByHashPrefixes(
obsoleteStoredHashPrefixes(parsedChunkReferences, replacementHashSet),
List.copyOf(replacementChunkHashes));
deleteObsoleteParsedChunks(parsedChunkReferences, replacementHashSet);
List<ParsedChunkReference> parsedChunkReferences = readParsedChunkReferences(sourceUrl);
Set<String> obsoleteChunkHashes = new LinkedHashSet<>();
if (previousFileRecord != null) {
obsoleteChunkHashes.addAll(previousFileRecord.chunkHashes());
}
obsoleteChunkHashes.removeAll(replacementHashSet);
localStoreService.deleteObsoleteChunkIngestionMarkersByHashPrefixes(
obsoleteStoredHashPrefixes(parsedChunkReferences, replacementHashSet),
List.copyOf(replacementChunkHashes));
if (!obsoleteChunkHashes.isEmpty()) {
localStoreService.deleteChunkIngestionMarkers(List.copyOf(obsoleteChunkHashes));
}
deleteObsoleteParsedChunks(parsedChunkReferences, replacementHashSet);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/williamcallahan/javachat/service/ingestion/IngestedFilePruneService.java`
around lines 120 - 132, In the cleanup flow containing parsedChunkReferences and
obsoleteChunkHashes, invoke deleteObsoleteChunkIngestionMarkersByHashPrefixes
before deleteChunkIngestionMarkers so ambiguous prefixes fail closed before any
exact-marker deletion occurs. Preserve the existing arguments and subsequent
deleteObsoleteParsedChunks call.

Comment thread src/main/java/com/williamcallahan/javachat/service/JavaApiAnchoredSection.java Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1263e6496c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -247,41 +287,43 @@ public LocalDocsFileOutcome process(Path root, Path file) {
List<Document> documents = chunkingOutcome.documents();
if (!documents.isEmpty()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force complete local replacements after partial skips

When local chunk-hash markers cause only some chunks to be skipped but Qdrant is missing the skipped points, such as after a collection reset that leaves data/index intact, this early return upserts only the non-skipped documents and then records the full chunk-hash inventory for the file. The run reports success while the URL is missing every skipped chunk until a later ingestion happens to detect the exact-ID mismatch, so the local path needs the same complete-replacement check used by the crawler before marking the file complete.

Useful? React with 👍 / 👎.

A canceled bounded-elastic retrieval could finish after the test that created it, leaking an unrelated pipeline error into the next test's global log capture. Synchronize the actual retrieval task before disposing the stream so suite order and machine timing cannot change the outcome.
The test's real sleep could consume the entire shared query deadline under
loaded CI scheduling. Sequential dispatch timestamps already verify that later
queries receive the remaining budget without making the assertion flaky.
The guided lesson page header already owns the lesson title, so remove each
curated document's duplicate opening heading. Guard the content resources so a
second primary heading cannot be reintroduced.
Track malformed URL-scoped parsed files as obsolete cleanup candidates while
keeping unverified hashes away from ingestion-marker deletion. This prevents
corrupt local artifacts from surviving every replacement run.
Select the runtime constructor explicitly when Spring sees the service's test
constructor. Cover CLI-profile context creation so batch ingestion cannot fail
before document processing begins.
Keep GitHub synchronization with its direct runtime owner and fail when active-generation discovery or repository metadata cannot be verified.
Own source selection, stable-version validation, citation provenance, and configurable documentation roots at their runtime boundaries.
Align the OpenAI client, Qdrant client and server, and gRPC stack while isolating local Qdrant storage for the new embedding generation.
Use Qwen 4B at 2,560 native dimensions with intent-specific gateway tiers, strict response validation, and no competing remote provider path.
Require exact 4B/2,560 core schemas and active GitHub prefixes, and keep readiness down when governed collection validation fails.
Fail closed on provider or file errors, require exact per-source Qdrant postconditions, and preserve prior generation markers and points until replacement succeeds.
Align local, CI, deployment, ingestion, and monitoring guidance with the shared gateway and isolated Qdrant generation contract.
Treat all as a selector expansion owned by the full-source fetch path so
operators can request the complete canonical corpus without naming each source.

- keep quick mirrors excluded from all
- reject all when mixed with named selectors
- cover the routing contract without duplicating the source inventory
Generate source identity hashes through the already-required Python runtime so
staged fetch publication works consistently on macOS and Linux hosts.

- remove the platform-specific shasum dependency
- assert the stable SHA-256 staging identity in the fetch projection test
Readiness now intentionally covers Qdrant, so the container smoke must provide
the same pinned dependency instead of waiting on an impossible localhost link.

- start Qdrant 1.18.3 on the CI Compose network
- connect the application container through the Qdrant service name
- remove the ephemeral dependency volume during always-run cleanup
Prevent slow SDK setup from accumulating burst credit before an embedding request begins.
Keep admission, pacing, async completion, and caller timeouts within the gateway limits.

- Space every consecutive SDK embedding dispatch by tier
- Retain concurrency permits until in-flight futures complete
- Cover pacing deadlines, interruption, timeout, and permit recovery
The lesson source panel could show unrelated vector-search matches instead of the official links authored into the lesson. Derive static lesson sources from the canonical Markdown AST and preserve inline-code link labels.

- remove Qdrant discovery from static lesson citations
- retain authored source order, URLs, and titles
- cover the Pattern Matching JLS links and inline code labels
Require an explicit Responses API completion event before recording stream success, preserve refusal text, and classify terminal server, rate-limit, output-limit, and content-filter states. Keep visible partial answers while rendering terminal failures separately and treat invisible-only output as empty.
Extract plural Java release requests, search each requested API generation under exact source constraints, and preserve per-release evidence through reranking and final prompt limits. Keep guided prompts scoped to the requested releases while leaving non-Java lesson retrieval unconstrained by incidental Java version mentions.
Reserve the floating chat control footprint in the lesson scrollport's programmatic target area so expanded source links are not obscured on mobile. Correct the modules lesson's duplicate greeting punctuation.
A query naming an exact Java method overload (for example
java.util.List.of(E, E)) was routed through the general reranker, which
scores candidates by semantic similarity and can rank a package-use or
overview page above the authoritative overload page. Multi-release
comparisons could therefore answer from documents that never described
the requested overload.

Exact-overload queries now retrieve Java API citation candidates
directly, order them with CitationCandidateRanker, and skip reranking
entirely. Missing evidence raises instead of silently degrading to
whatever the reranker surfaced, and each requested release must supply
its own evidence. Detection is gated on the retrieval constraint
targeting a Java API doc set, so non-Java scopes that merely mention
Java syntax keep the ordinary reranked path.

- Add requiresExactJavaOverloadEvidence to gate the exact-overload path
  on JavaApiMethodSelector plus the constraint's Java API doc sets
- Add requireExactOverloadEvidence to fail loudly when a requested
  release has no official overload evidence
- Retrieve and order exact-overload candidates in retrieveCandidates and
  bypass rerankerService when building prompt documents
- Cover multi-release exact-overload grounding and the non-Java scope
  exclusion in RetrievalServiceTest
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation java Pull requests that update java code refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants