# Changelog

> **This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.**

## Score

- CAI 62 → 55 (-6.6)
- Rubric changed (rubric-2026.10.1 → rubric-2026.10.5) — scores are not directly comparable.

## Lenses

- Code Health 66 → 67 (+1.3)
- Architecture 89 → 89 (+0.0)
- Maturity 76 → 49 (-26.7)
- Readiness 54 → 56 (+2.0)
- Security 81 → 81 (+0.0)
- Accessibility 61 → 52 (-9.2)
- Performance 100 → 100 (+0.0)

## Resolved (26)

- Documentation: no project overview (README.md)
- Duplicated block (10 lines × 4) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (11 lines × 6) (haystack/components/embedders/azure_document_embedder.py)
- Duplicated block (12 lines × 2) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (12 lines × 2) (haystack/components/generators/chat/openai.py)
- Duplicated block (12 lines × 2) (haystack/components/generators/chat/openai.py)
- Duplicated block (14 lines × 2) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (14 lines × 2) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (22 lines × 2) (haystack/components/rankers/llm_ranker.py)
- Duplicated block (29 lines × 2) (haystack/components/evaluators/llm_evaluator.py)
- Duplicated block (32 lines × 2) (haystack/components/query/query_expander.py)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Hotspot: haystack/components/builders/answer_builder.py (haystack/components/builders/answer_builder.py)
- Hotspot: haystack/core/serialization.py (haystack/core/serialization.py)
- Leaked secret: high-entropy-secret (haystack/telemetry/_telemetry.py)
- Members sharing a duplicated core (4 members, 50+ identical tokens) (haystack/components/evaluators/document_map.py)
- Members sharing a duplicated core (4 members, 50+ identical tokens) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Off-boarding risk: anonymized user #1
- Redundant existence check. The `has` method duplicates the functionality of checking if a key exists before calling `get`, or checking if `get` returns the default. In Python, `key in state.data` or `state.get(key, default) is not default` (with care for default values) is standard. Having a dedicated `has` method is inconsistent with the standard dictionary-like interface implied by `get` and `set`.
- …and 6 more

## New (31)

- ChatMessage.from_openai_dict_format (cognitive 31) (haystack/dataclasses/chat_message.py)
- ChatMessage.from_openai_dict_format (cyclomatic 22) (haystack/dataclasses/chat_message.py)
- Duplicated block (10 lines × 9) (haystack/components/classifiers/openai_decisions_document_classifier.py)
- Duplicated block (10–11 lines × 2) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (10–11 lines × 2) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (12 lines × 2) (haystack/components/extractors/image/llm_document_content_extractor.py)
- Duplicated block (25 lines × 2) (haystack/components/rankers/llm_ranker.py)
- Duplicated block (27 lines × 2) (haystack/components/evaluators/document_map.py)
- Duplicated block (34 lines × 2) (haystack/components/evaluators/llm_evaluator.py)
- Duplicated block (41 lines × 2) (haystack/components/query/query_expander.py)
- Duplicated block (6 lines × 2) (haystack/components/classifiers/openai_decisions_document_classifier.py)
- Duplicated block (6 lines × 2) (haystack/components/routers/openai_decisions_image_router.py)
- Duplicated block (64 lines × 2) (haystack/components/routers/openai_decisions_image_router.py)
- FileTooLong: dataclasses/chat_message.py (haystack/dataclasses/chat_message.py)
- HTMLToDocument.run (cognitive 18) (haystack/components/converters/html.py)
- Hotspot: haystack/components/generators/chat/openai_responses.py (haystack/components/generators/chat/openai_responses.py)
- Hotspot: haystack/components/generators/utils.py (haystack/components/generators/utils.py)
- Hotspot: haystack/core/pipeline/base.py (haystack/core/pipeline/base.py)
- Hotspot: haystack/dataclasses/chat_message.py (haystack/dataclasses/chat_message.py)
- Hotspot: haystack/tools/from_function.py (haystack/tools/from_function.py)
- …and 11 more

## Changes since last survey

- 173 commits — 142 feature/other, 31 fixes

## By area

- docs-website/reference_versioned_docs — 39 commits
- docs-website/docs — 28 commits
- docs-website/reference — 25 commits
- haystack/components — 20 commits
- .github/workflows — 13 commits
- docs-website/package.json — 6 commits
- docs-website/versioned_docs — 6 commits
- .clusterfuzzlite/Dockerfile — 5 commits
- haystack/core — 4 commits
- (root) — 3 commits
- haystack/dataclasses — 3 commits
- haystack/hooks — 3 commits
- (repo) — 2 commits
- docs-website/docusaurus.config.js — 2 commits
- haystack/document_stores — 2 commits
- haystack/logging.py — 2 commits
- haystack/tools — 2 commits
- test/components — 2 commits
- docs-website/api — 1 commit
- haystack/evaluation — 1 commit

## Notable commits

- fix: fix!: parse list-of-parts content in ChatMessage.from_openai_dict_format (#12446)
- fix: fix: align PythonCodeSplitter line splits with ast (#13301)
- fix: fix: always close PDF in `_convert_pdf_to_images`; narrow bare except in `SentenceSplitter` (#12942)
- fix: fix: bound log values nested in lists and dicts (#13031)
- fix: fix: correct LLMDocumentContentExtractor failure messages and docstring (#13175)
- fix: fix: count literal special-token strings as ordinary text in TiktokenCounter (#13009)
- fix: fix: don't return a snapshot path when saving the pipeline snapshot fails (#13174)
- fix: fix: drop documents missing the meta field when MetaFieldRanker can't sort (#13231)
- fix: fix: drop the ATX closing sequence from MarkdownHeaderSplitter header metadata (#13282)
- fix: fix: fill in the LLMEvaluator failure summary and clarify its fallback warnings (#13173)
- fix: fix: keep both filters when FilterPolicy.MERGE combines OR/NOT filters (#12816)
- fix: fix: keep docstring-only Python chunks valid (#12346)
- fix: fix: keep line endings when FileSystemToolResultStore writes text (#13253)
- fix: fix: keep pipeline snapshots reusable after resume (#13076)
- fix: fix: keep the Agent running when a tool result store write fails (#13226)
- fix: fix: log traceback in `logger.exception()` of Haystack loggers (#13189)
- fix: fix: make QueryExpander default prompt consistent with n_expansions (#13110)
- fix: fix: map raw reasoning text to reasoning_text field in OpenAIResponse components (#13124)
- fix: fix: normalize SASEvaluator cross encoder scores based on the model (#13244)
- fix: fix: parse empty tool call arguments in the non-streaming OpenAI generators (#13047)
- …and 153 more

## Architecture

- 0 containers · 1 bounded contexts · 0 dependency edges (baseline)
