# Changelog

## Score

- CAI 64 → 64 (+0.6)
- Rubric changed (rubric-2026.09.11 → rubric-2026.09.18) — scores are not directly comparable.

## Lenses

- Code Health 69 → 69 (-0.4)
- Architecture 96 → 88 (-7.6)
- Maturity 54 → 56 (+1.3)
- Readiness 65 → 69 (+3.6)
- Security 77 → 77 (+0.0)
- Performance 82 (new)

## Resolved (26)

- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- Duplicated block (13 lines × 2) (Sources/TokeniserState.swift)
- Duplicated block (14 lines × 2) (Sources/Tokeniser.swift)
- Duplicated block (16 lines × 2) (Sources/Element.swift)
- Duplicated block (22 lines × 2) (Sources/Tokeniser.swift)
- Duplicated block (26 lines × 2) (Sources/TokeniserState.swift)
- Edited copy of a member (22 corresponding lines) (Sources/HtmlTreeBuilder.swift)
- Element.containsNormalizedTextASCII (cognitive 25) (Sources/Element.swift)
- Element.containsOwnTextASCII (cognitive 18) (Sources/Element.swift)
- Element.emitNormalizedSlice (cognitive 59) (Sources/Element.swift)
- Element.emitNormalizedSlice (cognitive 59) (Sources/Element.swift)
- Element.emitNormalizedSlice (cyclomatic 25) (Sources/Element.swift)
- Element.emitNormalizedSlice (cyclomatic 25) (Sources/Element.swift)
- Element.text (cognitive 19) (Sources/Element.swift)
- Hotspot: Sources/Attributes.swift (Sources/Attributes.swift)
- Hotspot: Sources/CssSelector.swift (Sources/CssSelector.swift)
- Hotspot: Sources/Element.swift (Sources/Element.swift)
- Hotspot: Sources/HtmlTreeBuilder.swift (Sources/HtmlTreeBuilder.swift)
- Low cohesion: Element (LCOM4 51) (Sources/Element.swift)
- …and 6 more

## New (109)

- Array.regionMatches (cognitive 17) (Sources/String.swift)
- CharacterReader.containsAsciiCaseInsensitive (cognitive 21) (Sources/CharacterReader.swift)
- Document.patchedOuterHtmlUTF8 (cognitive 16) (Sources/Document.swift)
- Duplicate intent between `nodeName` and `tagName`. In HTML DOM, these are often synonymous for elements, but the API exposes both with both String and UTF8 variants. This leads to 4 methods doing nearly the same thing.
- Duplicated block (10 lines × 2) (Tools/SwiftSoupProfile/main.swift)
- Duplicated block (10 lines × 2) (Tools/benchmark_exclusion.swift)
- Duplicated block (10–11 lines × 2) (Tools/SwiftSoupProfile/main.swift)
- Duplicated block (10–13 lines × 2) (Tools/SwiftSoupProfile/main.swift)
- Duplicated block (11 lines × 3) (Sources/Element.swift)
- Duplicated block (13 lines × 2) (Sources/TokeniserState.swift)
- Duplicated block (13 lines × 2) (Sources/TokeniserState.swift)
- Duplicated block (16 lines × 2) (Sources/HtmlTreeBuilder.swift)
- Duplicated block (17 lines × 2) (Sources/Tokeniser.swift)
- Duplicated block (17–20 lines × 3) (Tools/SwiftSoupProfile/main.swift)
- Duplicated block (18 lines × 2) (Sources/String.swift)
- Duplicated block (2–8 lines × 4) (Tools/compare_blank_text.py)
- Duplicated block (2–9 lines × 7) (Tools/compare_blank_text.py)
- Duplicated block (5 lines × 2) (Tools/benchmark_exclusion.swift)
- Duplicated block (5 lines × 4) (Tools/compare_exclusion.py)
- Duplicated block (6 lines × 3) (Tools/SwiftSoupProfile/main.swift)
- …and 89 more

## Changes since last survey

- 124 commits — 45 feature/other, 79 fixes

## By area

- (repo) — 46 commits
- Tests/SwiftSoupTests — 37 commits
- Sources/Element.swift — 7 commits
- Sources/Document.swift — 5 commits
- Sources/CharacterReader.swift — 4 commits
- Sources/Evaluator.swift — 3 commits
- Sources/HtmlTreeBuilder.swift — 3 commits
- Sources/Tokeniser.swift — 3 commits
- (root) — 2 commits
- Sources/Collector.swift — 2 commits
- Sources/Entities.swift — 2 commits
- Sources/XmlTreeBuilder.swift — 2 commits
- .github/workflows — 1 commit
- Sources/Cleaner.swift — 1 commit
- Sources/Elements.swift — 1 commit
- Sources/FormElement.swift — 1 commit
- Sources/ParseErrorList.swift — 1 commit
- Sources/TokenQueue.swift — 1 commit
- Sources/TokeniserState.swift — 1 commit
- SwiftSoup.xcodeproj/project.pbxproj — 1 commit

## Notable commits

- fix: Add regression coverage for custom-evaluators
- fix: Add regression coverage for empty-reader-search
- fix: Add regression coverage for fragment-mutations
- fix: Add regression coverage for output-policy
- fix: Add regression coverage for raw-text
- fix: Add regression coverage for rcdata-modes
- fix: Add regression coverage for tokenqueue-chomp
- fix: Add regression coverage for unicode-cursors
- fix: Add regression coverage for xml-charset
- fix: Add upstream regression coverage for apostrophe-references
- fix: Add upstream regression coverage for nbsp-serialization
- fix: Add upstream regression coverage for numeric-references
- fix: Fix XML detection and borrowed-buffer document initialization
- fix: Merge pull request #421 from lake-of-fire/fix/upstream-document-clone-state-20260920
- fix: Merge pull request #422 from lake-of-fire/fix/upstream-parser-reuse-state-20260920
- fix: Merge pull request #423 from lake-of-fire/fix/upstream-rawtext-fragments-20260920
- fix: Merge pull request #424 from lake-of-fire/fix/upstream-detached-element-matches-20260920
- fix: Merge pull request #425 from lake-of-fire/fix/upstream-wrap-non-element-20260920
- fix: Merge pull request #426 from lake-of-fire/fix/upstream-source-syntax-adoption-20260920
- fix: Merge pull request #428 from lake-of-fire/fix/upstream-xml-bogus-declaration-20260922
- …and 104 more
