docs: align stale figures with code and the enforced XSTS gate

- README, roadmap: XSTS status quad and gates table now read the enforced
  0/43/0/31 (Tests/XSTSSuiteTests.swift); test count 986/169 to 1448/258;
  encoding list and the remaining-work section reflect shipped reality;
  check-all expansion lists the validation and changelog gates
- GEMINI.md, onboarding-antigravity.md: valid-schemas-rejected 1 to 0 and the
  pinned baselines updated to current
- SECURITY.md: complete the reporting address
- Parsing.InputEncoding: doc comment lists the full shipped encoding set
- Schema.XSDParserUnion: guard the localName interpolation with ?? "" to match
  the same line and silence an optional-interpolation warning (internal dedup
  key, behavior preserving)
- CHANGELOG: Unreleased entries for the above
This commit is contained in:
Mihaela Mihaljevic 2026-06-19 21:28:31 +02:00
parent b73384bc2e
commit 8d30010e0d
8 changed files with 68 additions and 44 deletions

View File

@ -28,6 +28,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Silenced an optional-interpolation warning in the union dedup signature
(`XSDParserUnion`): the `localName` interpolation now guards with `?? ""` to
match the `name`-attribute interpolation on the same line. The signature is an
internal dedup key compared only against same-run signatures, so the change is
behavior-preserving (it removes the `Optional("…")` rendering, not any key
collisions).
- Documentation accuracy sweep: brought stale current-state figures into line with
the code and the enforced gate. The README test count (986/169 -> 1448/258) and
XSTS status quad, the roadmap gates table, and the Antigravity onboarding
baselines now read the enforced `0 / 43 / 0 / 31`; the encoding coverage (the
README feature list and the `Parsing.InputEncoding` doc comment) now lists the
full shipped set (the ISO-8859 family, Windows code pages 1250-1258, KOI8-R/U,
and the CJK multi-byte encodings) instead of a three-entry subset; the
"remaining parity" section now states that libxml2 documented-surface parity is
complete (epics #71/#74/#105 closed) with production readiness (#167) as the
remaining work; the README `check-all.sh` expansion lists the validation-coverage,
validation-field, and changelog gates; and the SECURITY.md reporting address is
corrected.
- Replaced XSD content-model occurrence unrolling with a counted automaton. - Replaced XSD content-model occurrence unrolling with a counted automaton.
`ContentMatcher` now tracks occurrence counters in active configurations instead `ContentMatcher` now tracks occurrence counters in active configurations instead
of copying particle bodies into states, preserving exact finite `{m,n}` behavior of copying particle bodies into states, preserving exact finite `{m,n}` behavior

View File

@ -8,7 +8,7 @@ rule here and a guideline elsewhere conflict, this file wins.
PureXML is an XML/XSD validator. **Never reject a valid schema or a valid PureXML is an XML/XSD validator. **Never reject a valid schema or a valid
document.** In the conformance counts this is `valid-schemas-rejected`; it is document.** In the conformance counts this is `valid-schemas-rejected`; it is
**1** and must **never rise**. Under-rejecting (missing an invalid schema) is **0** and must **never rise**. Under-rejecting (missing an invalid schema) is
acceptable; over-rejecting (rejecting a valid one) is a failure and must not be acceptable; over-rejecting (rejecting a valid one) is a failure and must not be
merged. When unsure, do less. merged. When unsure, do less.
@ -67,6 +67,6 @@ merged. When unsure, do less.
## Definition of done ## Definition of done
All gates green; conformance differential shows invalid-accepted down and **no All gates green; conformance differential shows invalid-accepted down and **no
other bucket up** (valid-rejected still 1); the critic found zero false other bucket up** (valid-rejected still 0); the critic found zero false
positives; baseline/CHANGELOG/burndown updated. If you rejected even one valid positives; baseline/CHANGELOG/burndown updated. If you rejected even one valid
schema, the change is wrong regardless of how many invalid ones it caught. schema, the change is wrong regardless of how many invalid ones it caught.

View File

@ -100,7 +100,7 @@ flowchart TB
EncodingMismatch["#137 encoding-declaration mismatches: complete"]:::done EncodingMismatch["#137 encoding-declaration mismatches: complete"]:::done
BaseURI["#138 per-entity base URIs: complete"]:::done BaseURI["#138 per-entity base URIs: complete"]:::done
Epic122["#122 conformance suite maintenance: complete (#130 survivor)"]:::epic Epic122["#122 conformance suite maintenance: complete (#130 survivor)"]:::epic
XSTS["#129 XSTS runner shipped; gates #145-#148 at 1/264/173/155 (v0.2.0)"]:::review XSTS["#129 XSTS runner shipped; gates #145-#148 at 0/43/0/31"]:::review
XSLTTS["#130 XSLT 1.0 suite (xalan-test): ~126 baseline failures"]:::review XSLTTS["#130 XSLT 1.0 suite (xalan-test): ~126 baseline failures"]:::review
Parity100["Behavioral parity closed: #141 top-level params, #142 public streaming, #143 XPath budget, #144 WASI runtime proof, pl/ru sort collation"]:::done Parity100["Behavioral parity closed: #141 top-level params, #142 public streaming, #143 XPath budget, #144 WASI runtime proof, pl/ru sort collation"]:::done
Epic139["#139 faster than libxml2, measured + streaming (benchmarks in docs/benchmarks.md; quadratics killed; unsafe authorized)"]:::epic Epic139["#139 faster than libxml2, measured + streaming (benchmarks in docs/benchmarks.md; quadratics killed; unsafe authorized)"]:::epic
@ -139,11 +139,11 @@ flowchart TB
## Status ## Status
**Current focus:** production readiness for IDE use ([#167](https://github.com/mihaelamj/PureXML/issues/167)). XSTS settled baselines (v0.2.0): **1 / 264 / 173 / 155**. See [`docs/roadmap.md`](docs/roadmap.md) for milestones and open tasks. **Current focus:** production readiness for IDE use ([#167](https://github.com/mihaelamj/PureXML/issues/167)). XSTS settled baselines (valid schemas rejected / invalid schemas accepted / valid instances rejected / invalid instances accepted), enforced in `Tests/XSTSSuiteTests.swift`: **0 / 43 / 0 / 31**. See [`docs/roadmap.md`](docs/roadmap.md) for milestones and open tasks.
PureXML is a working, dependency-free XML library today: parse, emit, validate, PureXML is a working, dependency-free XML library today: parse, emit, validate,
query, and stream documents on macOS, Linux, Windows, and WASM. The test suite query, and stream documents on macOS, Linux, Windows, and WASM. The test suite
currently runs **986 tests in 169 suites** (`swift test`). currently runs **1448 tests in 258 suites** (`swift test`).
### Shipped (libxml2-aligned surface) ### Shipped (libxml2-aligned surface)
@ -156,8 +156,10 @@ currently runs **986 tests in 169 suites** (`swift test`).
(libxml2 `xmlTextReader`). Handles elements, attributes, text, predefined and (libxml2 `xmlTextReader`). Handles elements, attributes, text, predefined and
numeric entities, comments, CDATA, and processing instructions. Namespace numeric entities, comments, CDATA, and processing instructions. Namespace
bindings (`xmlns`) are resolved to URIs on parse. bindings (`xmlns`) are resolved to URIs on parse.
- **Encoding**: UTF-8/16/32 (with BOM sniffing), ISO-8859-1, and Windows-1252 - **Encoding**: UTF-8/16/32 (with BOM sniffing) from raw bytes or streaming byte
from raw bytes or streaming byte input. input, plus the ISO-8859 single-byte family, the Windows code pages
(1250-1258), KOI8-R/U, and the CJK multi-byte encodings (Shift-JIS,
EUC-JP/KR/TW, GBK, GB18030, Big5, ISO-2022-JP).
- **DTD (opt-in)**: `<!DOCTYPE>` is **off by default** (`Limits.allowDoctype: - **DTD (opt-in)**: `<!DOCTYPE>` is **off by default** (`Limits.allowDoctype:
false`) to keep XXE and entity-expansion closed. When enabled, the internal false`) to keep XXE and entity-expansion closed. When enabled, the internal
subset is parsed; internal general entities expand with a bounded cap; external subset is parsed; internal general entities expand with a bounded cap; external
@ -206,25 +208,21 @@ subset validation or internal entities, and wire a resolver only for trusted,
in-memory replacements. Network fetching (`nanohttp`/`nanoftp`) and libxml2's in-memory replacements. Network fetching (`nanohttp`/`nanoftp`) and libxml2's
threading/memory infrastructure are deliberate non-goals. threading/memory infrastructure are deliberate non-goals.
### Remaining toward full libxml2 feature parity ### Remaining work
The original parity epics (the core I/O stack, query, transform, the schema Feature parity with libxml2's documented surface is **complete**: the core I/O
languages, the validation framework, and editor integration) are all shipped. The stack, the query and transform layers, all four schema languages, the validation
remaining work is the depth gaps a read-only conformance audit surfaced, tracked framework, editor integration, and the encoding set (the ISO-8859 family, the
under epic **#71** (and its parser-breadth sub-epic **#74**): Windows code pages, and the CJK multi-byte encodings) are shipped. The
beyond-parity audit epics (**#71**, its parser-breadth sub-epic **#74**) and the
parity-frontier epic (**#105**) are closed.
| Open work | Issues | What it adds | The remaining distance is **production readiness for IDE use**, tracked under epic
|---|---|---| **#167**: driving the XSTS conformance buckets toward zero (currently
| XSLT 1.0 breadth | #81 #82 | Missing top-level elements and functions, html output | **0 / 43 / 0 / 31**), located schema diagnostics (#169), the schema differential
| HTML5 | #83 #84 | Full tree construction, tokenizer states, entity table | oracle (#171), and cross-document composition (#161). The one active runner
| C14N | #85 | Node-subset canonicalization, `xml:*` inheritance, 2.0 prefix rewrite | burn-down is **#130** (the XSLT 1.0 xalan suite). See
| Legacy encodings | #97 #99 #102 #103 | Single-byte, CJK multi-byte, full GB18030, and Big5 to-Unicode tables | [`docs/roadmap.md`](docs/roadmap.md).
| Validator decomposition | #101 | Inner XSD/DTD validators as composable rules |
| Partial follow-ups | #79 #80 #86 #87 #88 #90 #91 | Remaining bullets on already-advanced areas |
Each open issue carries a checklist of done vs remaining bullets. The encoding
tables (#97, #99) are deferred until they can be vendored from authoritative
Unicode mapping files rather than transcribed.
## Usage ## Usage
@ -287,6 +285,9 @@ That command expands to:
bash scripts/check-style.sh bash scripts/check-style.sh
bash scripts/check-namespacing.sh bash scripts/check-namespacing.sh
bash scripts/check-forbidden-patterns.sh bash scripts/check-forbidden-patterns.sh
bash scripts/check-validation-coverage.sh
bash scripts/check-validation-fields.sh
bash scripts/check-changelog-touched.sh
swiftformat . --config .swiftformat --lint swiftformat . --config .swiftformat --lint
swiftlint --config .swiftlint.yml --strict swiftlint --config .swiftlint.yml --strict
swift build swift build

View File

@ -5,7 +5,7 @@
If you believe you have found a security issue in PureXML, please report it If you believe you have found a security issue in PureXML, please report it
privately. Do not open a public issue for security problems. privately. Do not open a public issue for security problems.
Email **mihaelamj.com** with: Email **mihaelamj@gmail.com** with:
- A description of the issue and its impact. - A description of the issue and its impact.
- Steps to reproduce, or a proof of concept. - Steps to reproduce, or a proof of concept.

View File

@ -1,7 +1,8 @@
public extension PureXML.Parsing { public extension PureXML.Parsing {
/// A character encoding PureXML can decode from raw bytes. Covers the /// A character encoding PureXML can decode from raw bytes. Covers the Unicode
/// Unicode transformation formats plus the single-byte encodings (ISO-8859-1, /// transformation formats, the ISO-8859 single-byte family, the Windows code
/// ISO-8859-5/9/15, and Windows-1252), toward libxml2 encoding parity. /// pages (1250-1258), KOI8-R/U, and the CJK multi-byte encodings (Shift-JIS,
/// EUC-JP/KR/TW, GBK, GB18030, Big5, ISO-2022-JP), for libxml2 encoding parity.
enum InputEncoding: String, Equatable, Sendable { enum InputEncoding: String, Equatable, Sendable {
case utf8 case utf8
case utf16BigEndian case utf16BigEndian

View File

@ -67,7 +67,7 @@ extension PureXML.Schema.XSDParser {
guard XSDNode.localName(tree) == "schema" else { return nil } guard XSDNode.localName(tree) == "schema" else { return nil }
guard let namespace = XSDNode.attribute(tree, "targetNamespace"), !namespace.isEmpty else { return nil } guard let namespace = XSDNode.attribute(tree, "targetNamespace"), !namespace.isEmpty else { return nil }
let components = XSDNode.elementChildren(tree) let components = XSDNode.elementChildren(tree)
.map { "\(XSDNode.localName($0)):\(XSDNode.attribute($0, "name") ?? "")" } .map { "\(XSDNode.localName($0) ?? ""):\(XSDNode.attribute($0, "name") ?? "")" }
.sorted() .sorted()
return "\(namespace)\u{1}\(components.joined(separator: "\u{1}"))" return "\(namespace)\u{1}\(components.joined(separator: "\u{1}"))"
} }

View File

@ -20,7 +20,7 @@ PureXML is an XML/XSD validator. Its single most important quality is:
> **Never reject a valid schema or a valid document.** > **Never reject a valid schema or a valid document.**
In the conformance numbers (Section 5) this is the bucket In the conformance numbers (Section 5) this is the bucket
`valid-schemas-rejected`. It is currently **1** and must **never go up**. A `valid-schemas-rejected`. It is currently **0** and must **never go up**. A
change that fixes ten bad schemas but wrongly rejects one good schema is a change that fixes ten bad schemas but wrongly rejects one good schema is a
**failure** and must not be merged. When in doubt, do less: it is always **failure** and must not be merged. When in doubt, do less: it is always
acceptable to *miss* an invalid schema (under-reject); it is never acceptable to acceptable to *miss* an invalid schema (under-reject); it is never acceptable to
@ -133,10 +133,10 @@ top of that file:
| Constant | Meaning | Current value | Direction | | Constant | Meaning | Current value | Direction |
|---|---|---|---| |---|---|---|---|
| `knownSchemaValidRejected` | valid schemas we wrongly **reject** | **1** | must NEVER rise; drive toward 0 | | `knownSchemaValidRejected` | valid schemas we wrongly **reject** | **0** | must NEVER rise; hold at 0 |
| `knownSchemaInvalidAccepted` | invalid schemas we wrongly **accept** | **390** | drive DOWN | | `knownSchemaInvalidAccepted` | invalid schemas we wrongly **accept** | **43** | drive DOWN |
| `knownInstanceValidRejected` | valid instances we wrongly **reject** | **180** | must not rise; drive toward 0 | | `knownInstanceValidRejected` | valid instances we wrongly **reject** | **0** | must not rise; hold at 0 |
| `knownInstanceInvalidAccepted`| invalid instances we wrongly accept | **160→158** (158) | drive down | | `knownInstanceInvalidAccepted`| invalid instances we wrongly accept | **31** | drive down |
The runner asserts these counts **exactly**. So: The runner asserts these counts **exactly**. So:
@ -406,12 +406,12 @@ Representative existing checks to imitate (read these as templates):
--- ---
## 11. Current state (snapshot, post v0.1.0) ## 11. Current state (snapshot, post v0.2.0)
- Pinned baselines: **valid-schemas-rejected 1**, **invalid-schemas-accepted - Pinned baselines: **valid-schemas-rejected 0**, **invalid-schemas-accepted
390**, **valid-instances-rejected 180**, **invalid-instances-accepted 158**. 43**, **valid-instances-rejected 0**, **invalid-instances-accepted 31**.
(v0.1.0 was tagged at invalid-accepted 394; the count has since dropped to (These ratchet down as conformance work lands; always read the live constants
390. Always read the live constants in `Tests/XSTSSuiteTests.swift`.) in `Tests/XSTSSuiteTests.swift`.)
- The clean structural / applicability rule families are largely **done**: - The clean structural / applicability rule families are largely **done**:
facet validity, structural content-model, UPA determinism, content order, facet validity, structural content-model, UPA determinism, content order,
identity-constraint XPath subset, wildcard namespace, final/block value space, identity-constraint XPath subset, wildcard namespace, final/block value space,

View File

@ -13,14 +13,16 @@ Parallel: **#130** (XSLT suite), **#139** (performance epic; tasks [#175](https:
**M1 done:** #171 schema differential harness (closed; opt-in; 231 XSTS oracle disagreements pinned) + generative fuzz + validation framework (#92). **M1 done:** #171 schema differential harness (closed; opt-in; 231 XSTS oracle disagreements pinned) + generative fuzz + validation framework (#92).
## XSTS gates (v0.2.0 baselines) ## XSTS gates (current enforced baselines)
These mirror the ratchet asserted in `Tests/XSTSSuiteTests.swift`; update both together.
| Gate | Now | Issue | | Gate | Now | Issue |
|---|---|---| |---|---|---|
| Valid schemas rejected | 1 | [#148](https://github.com/mihaelamj/PureXML/issues/148) | | Valid schemas rejected | 0 | [#148](https://github.com/mihaelamj/PureXML/issues/148) |
| Invalid schemas accepted | 261 | [#145](https://github.com/mihaelamj/PureXML/issues/145) | | Invalid schemas accepted | 43 | [#145](https://github.com/mihaelamj/PureXML/issues/145) |
| Valid instances rejected | 99 | [#146](https://github.com/mihaelamj/PureXML/issues/146) | | Valid instances rejected | 0 | [#146](https://github.com/mihaelamj/PureXML/issues/146) |
| Invalid instances accepted | 147 | [#147](https://github.com/mihaelamj/PureXML/issues/147) | | Invalid instances accepted | 31 | [#147](https://github.com/mihaelamj/PureXML/issues/147) |
Gates are **metric trackers**, not implementation tasks. Pick up **task** issues; ratchet baselines in `Tests/XSTSSuiteTests.swift` when counts fall. Gates are **metric trackers**, not implementation tasks. Pick up **task** issues; ratchet baselines in `Tests/XSTSSuiteTests.swift` when counts fall.