From 2037d5baf7a53e0cb4f1af67cab149d9ee544e9f Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Fri, 26 Jun 2026 04:26:30 +0200 Subject: [PATCH 1/4] chore(release): stamp 0.4.8 --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bd9123..aa98282 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.4.8] - 2026-06-26 + ### Fixed -- `xpointer(string-range(...))` no longer uses a quadratic substring search. It matched the search string at every position of each node's value and re-allocated the whole needle-width window per position (O(text * needle), a denial-of-service vector on a long node value with a near-matching needle); it now uses a linear-time Knuth-Morris-Pratt search with the failure function built once. The matches are unchanged: same non-overlapping, left-to-right occurrences, same offset/length. A near-matching needle over a 16000-character node drops from about 0.18 s to about 0.002 s (~100x), and the cost is now linear. Guarded by the new non-overlapping and backtracking cases in `XPointerRangeTests`. +- `xpointer(string-range(...))` no longer uses a quadratic substring search. It matched the search string at every position of each node's value and re-allocated the whole needle-width window per position (O(text * needle), a denial-of-service vector on a long node value with a near-matching needle); it now uses a linear-time Knuth-Morris-Pratt search with the failure function built once. The matches are unchanged: same non-overlapping, left-to-right occurrences, same offset/length. A near-matching needle over a 16000-character node drops from about 0.18 s to about 0.002 s (~100x), and the cost is now linear. Guarded by the new non-overlapping and backtracking cases in `XPointerRangeTests` (#314). -- The XSLT `id()` function no longer scans the whole document ID index on every call. It filtered the entire index by `tokens.contains(...)` (O(index) per call), so a stylesheet calling `id()` across a wide document was quadratic; it now looks each requested token up directly (O(tokens)). The result is unchanged: the same elements in document order. A stylesheet resolving 4000 `id()` references against a 4000-entry index drops from about 0.34 s to about 0.03 s (~13x), and the cost is now linear. (`key()` already used direct lookups.) +- The XSLT `id()` function no longer scans the whole document ID index on every call. It filtered the entire index by `tokens.contains(...)` (O(index) per call), so a stylesheet calling `id()` across a wide document was quadratic; it now looks each requested token up directly (O(tokens)). The result is unchanged: the same elements in document order. A stylesheet resolving 4000 `id()` references against a 4000-entry index drops from about 0.34 s to about 0.03 s (~13x), and the cost is now linear. (`key()` already used direct lookups.) (#315) ## [0.4.7] - 2026-06-26 From 5aee644bf4e0c61a169a935cfa1c6abcec97c715 Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Thu, 2 Jul 2026 14:08:21 +0200 Subject: [PATCH 2/4] chore: repoint remaining github.com/mihaelamj references to codeberg.org/Mihaela --- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- README.md | 14 +++++++------- SUPPORT.md | 4 ++-- Sources/XSLT/XSLTFunctions.swift | 2 +- docs/roadmap.md | 12 ++++++------ docs/rules/rules-swift/CHANGELOG.md | 2 +- docs/rules/rules-swift/README.md | 2 +- docs/rules/rules-swift/documentation-search.md | 2 +- docs/rules/rules-swift/exp/package-swift.md | 4 ++-- docs/rules/rules-swift/ui/flowspec.md | 2 +- docs/rules/rules-swift/ui/pom.md | 2 +- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 137d78f..e50a5de 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ blank_issues_enabled: false contact_links: - name: Questions and ideas - url: https://github.com/mihaelamj/PureXML/discussions + url: https://codeberg.org/Mihaela/PureXML/discussions about: Ask questions, float ideas, or discuss design in Discussions. - name: Security issue - url: https://github.com/mihaelamj/PureXML/blob/main/SECURITY.md + url: https://codeberg.org/Mihaela/PureXML/blob/main/SECURITY.md about: Do not file security issues publicly. Follow the security policy instead. diff --git a/README.md b/README.md index 54400bd..aca762f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # PureXML -[![Style and namespacing](https://github.com/mihaelamj/PureXML/actions/workflows/style.yml/badge.svg)](https://github.com/mihaelamj/PureXML/actions/workflows/style.yml) -[![Swift macOS](https://github.com/mihaelamj/PureXML/actions/workflows/swift-macos.yml/badge.svg)](https://github.com/mihaelamj/PureXML/actions/workflows/swift-macos.yml) -[![Swift Linux](https://github.com/mihaelamj/PureXML/actions/workflows/swift-linux.yml/badge.svg)](https://github.com/mihaelamj/PureXML/actions/workflows/swift-linux.yml) -[![Swift Windows](https://github.com/mihaelamj/PureXML/actions/workflows/swift-windows.yml/badge.svg)](https://github.com/mihaelamj/PureXML/actions/workflows/swift-windows.yml) -[![Swift WASM](https://github.com/mihaelamj/PureXML/actions/workflows/swift-wasm.yml/badge.svg)](https://github.com/mihaelamj/PureXML/actions/workflows/swift-wasm.yml) +[![Style and namespacing](https://codeberg.org/Mihaela/PureXML/actions/workflows/style.yml/badge.svg)](https://codeberg.org/Mihaela/PureXML/actions/workflows/style.yml) +[![Swift macOS](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-macos.yml/badge.svg)](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-macos.yml) +[![Swift Linux](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-linux.yml/badge.svg)](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-linux.yml) +[![Swift Windows](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-windows.yml/badge.svg)](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-windows.yml) +[![Swift WASM](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-wasm.yml/badge.svg)](https://codeberg.org/Mihaela/PureXML/actions/workflows/swift-wasm.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) PureXML is a dependency-free XML package written entirely in Swift. @@ -19,7 +19,7 @@ intentionally strict about portability: - root Swift package layout - macOS, Linux, Windows, and WASI build gates -It is a sibling project to [PureYAML](https://github.com/mihaelamj/PureYAML) and +It is a sibling project to [PureYAML](https://codeberg.org/Mihaela/PureYAML) and follows the same structure, rules, and verification gates. ## Roadmap @@ -141,7 +141,7 @@ flowchart TB ## Status -**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 / 39 / 0 / 26**. See [`docs/roadmap.md`](docs/roadmap.md) for milestones and open tasks. +**Current focus:** production readiness for IDE use ([#167](https://codeberg.org/Mihaela/PureXML/issues/167)). XSTS settled baselines (valid schemas rejected / invalid schemas accepted / valid instances rejected / invalid instances accepted), enforced in `Tests/XSTSSuiteTests.swift`: **0 / 39 / 0 / 26**. See [`docs/roadmap.md`](docs/roadmap.md) for milestones and open tasks. 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 diff --git a/SUPPORT.md b/SUPPORT.md index 5669cb9..80792d9 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,8 +2,8 @@ Need help with PureXML? Here is where to go. -- **Questions and ideas**: open a [Discussion](https://github.com/mihaelamj/PureXML/discussions). -- **Bug reports**: open an [issue](https://github.com/mihaelamj/PureXML/issues/new/choose) +- **Questions and ideas**: open a [Discussion](https://codeberg.org/Mihaela/PureXML/discussions). +- **Bug reports**: open an [issue](https://codeberg.org/Mihaela/PureXML/issues/new/choose) using the bug form. - **Feature requests**: open an issue using the feature form. - **Security issues**: do not open a public issue. See [SECURITY.md](SECURITY.md). diff --git a/Sources/XSLT/XSLTFunctions.swift b/Sources/XSLT/XSLTFunctions.swift index 2483d89..7b2f725 100644 --- a/Sources/XSLT/XSLTFunctions.swift +++ b/Sources/XSLT/XSLTFunctions.swift @@ -322,7 +322,7 @@ extension PureXML.XSLT { switch localPart(name) { case "version": .number(1.0) case "vendor": .string("PureXML") - case "vendor-url": .string("https://github.com/mihaelamj/PureXML") + case "vendor-url": .string("https://codeberg.org/Mihaela/PureXML") default: .string("") } } diff --git a/docs/roadmap.md b/docs/roadmap.md index 73ffb2a..ffe01ce 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,6 +1,6 @@ # Roadmap -Living index of open work. **Pin [#167](https://github.com/mihaelamj/PureXML/issues/167)** on GitHub for the checklist view. Released **v0.2.0** (2026-06-16); pre-1.0 until the production-readiness gates in `docs/production-readiness.md` are earned. +Living index of open work. **Pin [#167](https://codeberg.org/Mihaela/PureXML/issues/167)** on GitHub for the checklist view. Released **v0.2.0** (2026-06-16); pre-1.0 until the production-readiness gates in `docs/production-readiness.md` are earned. ## Current focus (priority order) @@ -9,7 +9,7 @@ Living index of open work. **Pin [#167](https://github.com/mihaelamj/PureXML/iss 3. **#169**: located schema diagnostics (line/column). 4. **#172–#174**: instance-validation cluster tasks. -Parallel: **#130** (XSLT suite), **#139** (performance epic; tasks [#175](https://github.com/mihaelamj/PureXML/issues/175)–[#178](https://github.com/mihaelamj/PureXML/issues/178)). +Parallel: **#130** (XSLT suite), **#139** (performance epic; tasks [#175](https://codeberg.org/Mihaela/PureXML/issues/175)–[#178](https://codeberg.org/Mihaela/PureXML/issues/178)). **M1 done:** #171 schema differential harness (closed; opt-in; 231 XSTS oracle disagreements pinned) + generative fuzz + validation framework (#92). @@ -19,10 +19,10 @@ These mirror the ratchet asserted in `Tests/XSTSSuiteTests.swift`; update both t | Gate | Now | Issue | |---|---|---| -| Valid schemas rejected | 0 | [#148](https://github.com/mihaelamj/PureXML/issues/148) | -| Invalid schemas accepted | 43 | [#145](https://github.com/mihaelamj/PureXML/issues/145) | -| Valid instances rejected | 0 | [#146](https://github.com/mihaelamj/PureXML/issues/146) | -| Invalid instances accepted | 31 | [#147](https://github.com/mihaelamj/PureXML/issues/147) | +| Valid schemas rejected | 0 | [#148](https://codeberg.org/Mihaela/PureXML/issues/148) | +| Invalid schemas accepted | 43 | [#145](https://codeberg.org/Mihaela/PureXML/issues/145) | +| Valid instances rejected | 0 | [#146](https://codeberg.org/Mihaela/PureXML/issues/146) | +| Invalid instances accepted | 31 | [#147](https://codeberg.org/Mihaela/PureXML/issues/147) | Gates are **metric trackers**, not implementation tasks. Pick up **task** issues; ratchet baselines in `Tests/XSTSSuiteTests.swift` when counts fall. diff --git a/docs/rules/rules-swift/CHANGELOG.md b/docs/rules/rules-swift/CHANGELOG.md index 6961eb4..f03e860 100644 --- a/docs/rules/rules-swift/CHANGELOG.md +++ b/docs/rules/rules-swift/CHANGELOG.md @@ -10,7 +10,7 @@ Initial public release of the Swift domain rules, built on the engineering-disci - Where an app starts: `business-rules-and-constraints` (MANDATORY first artifact: business rules as explicit checkable statements, plus the constraints that bound them, which REST services, what compliance, which auth model) and `domain-first` (MANDATORY: start at the domain and business rules, framework-free and headless-provable; the UI framework is the last, reversible, and plural choice). - Swift craft: `code-style`, `namespacing`, `dependency-injection`, `concurrency`, `cross-platform`, `linux-server`, `testing`, `formatting-and-linting`, `documentation`, `documentation-search`, `package-structure`, `package-architecture`, `package-import-contract`, `shared-protocols`. -- UI (`ui/`): `pre-ui-layer` (the display-less model seam, MANDATORY: Domain + Surface, one `perform(Intent)` channel, renderers the only UI import; one model drives the SwiftUI, AppKit, and UIKit renderers at once, both the architecture's payoff and a comparison instrument), `pom` (Page Object Model for UI tests), `flowspec` (declarative UI scenarios via the [FlowSpec](https://github.com/mihaelamj/FlowSpec) package), plus three renderers over the one model (`swiftui-views`, `uikit-views`, `appkit-views`), `view-models`, `components`, `colors`, `fonts`. +- UI (`ui/`): `pre-ui-layer` (the display-less model seam, MANDATORY: Domain + Surface, one `perform(Intent)` channel, renderers the only UI import; one model drives the SwiftUI, AppKit, and UIKit renderers at once, both the architecture's payoff and a comparison instrument), `pom` (Page Object Model for UI tests), `flowspec` (declarative UI scenarios via the [FlowSpec](https://codeberg.org/Mihaela/FlowSpec) package), plus three renderers over the one model (`swiftui-views`, `uikit-views`, `appkit-views`), `view-models`, `components`, `colors`, `fonts`. - Parsing and validation: `parsing-rules` and `validation-rules` (the OpenAPIKit idiom). Validation requires every public type to be validated or excluded with a reason, enforced mechanically. - Apple-platform stance: `framework-policy` (Apple-only mandate), `openapi-generated`. - Drop-in kit: `.gitignore`, `.swiftformat`, `.swiftlint.yml`, `.pre-commit-config.yaml`, and `.githooks/` (a `pre-commit` format-and-lint hook and a `commit-msg` attribution/em-dash check). diff --git a/docs/rules/rules-swift/README.md b/docs/rules/rules-swift/README.md index b6f1629..58a5e67 100644 --- a/docs/rules/rules-swift/README.md +++ b/docs/rules/rules-swift/README.md @@ -141,4 +141,4 @@ The UI rules live under [`ui/`](ui/). Any code with UI keeps the renderer thin o - [ui/colors.md](ui/colors.md) - the color system. - [ui/fonts.md](ui/fonts.md) - font registration in SPM packages. - [ui/pom.md](ui/pom.md) - Page Object Model for UI tests: screens behind page objects, identifiers from one shared source. -- [ui/flowspec.md](ui/flowspec.md) - declarative UI scenarios driven by [FlowSpec](https://github.com/mihaelamj/FlowSpec): one flow, many renderers, replayed headless and on-device. +- [ui/flowspec.md](ui/flowspec.md) - declarative UI scenarios driven by [FlowSpec](https://codeberg.org/Mihaela/FlowSpec): one flow, many renderers, replayed headless and on-device. diff --git a/docs/rules/rules-swift/documentation-search.md b/docs/rules/rules-swift/documentation-search.md index 12bee02..3c65707 100644 --- a/docs/rules/rules-swift/documentation-search.md +++ b/docs/rules/rules-swift/documentation-search.md @@ -1,6 +1,6 @@ # Apple Documentation: Consult cupertino, Do Not Recall -**Status: MANDATORY.** Any fact about an Apple-platform API (availability, a signature, a deprecation, a conformance, an inheritance relationship, default behavior) comes from the documentation, never from memory. An LLM's recall of Apple APIs is stale at its training cutoff and reliably invents signatures, availability floors, and conformances. Before you state such a fact, look it up. The tool for that is [cupertino](https://github.com/mihaelamj/cupertino) (`brew install mihaelamj/tap/cupertino`), a local index over current Apple documentation, available as a CLI and an MCP server. +**Status: MANDATORY.** Any fact about an Apple-platform API (availability, a signature, a deprecation, a conformance, an inheritance relationship, default behavior) comes from the documentation, never from memory. An LLM's recall of Apple APIs is stale at its training cutoff and reliably invents signatures, availability floors, and conformances. Before you state such a fact, look it up. The tool for that is [cupertino](https://codeberg.org/Mihaela/cupertino) (`brew install mihaelamj/tap/cupertino`), a local index over current Apple documentation, available as a CLI and an MCP server. ## What cupertino is, and is not diff --git a/docs/rules/rules-swift/exp/package-swift.md b/docs/rules/rules-swift/exp/package-swift.md index 0c5e7d7..7d0c2cd 100644 --- a/docs/rules/rules-swift/exp/package-swift.md +++ b/docs/rules/rules-swift/exp/package-swift.md @@ -39,11 +39,11 @@ let deps: [Package.Dependency] = { // Custom middlewares let loggingMiddlewareDep = Package.Dependency.package( - url: "https://github.com/mihaelamj/OpenAPILoggingMiddleware", + url: "https://codeberg.org/Mihaela/OpenAPILoggingMiddleware", from: "1.1.0" ) let bearerTokenDep = Package.Dependency.package( - url: "https://github.com/mihaelamj/BearerTokenAuthMiddleware", + url: "https://codeberg.org/Mihaela/BearerTokenAuthMiddleware", from: "1.2.0" ) diff --git a/docs/rules/rules-swift/ui/flowspec.md b/docs/rules/rules-swift/ui/flowspec.md index 3a19087..1bb3664 100644 --- a/docs/rules/rules-swift/ui/flowspec.md +++ b/docs/rules/rules-swift/ui/flowspec.md @@ -1,6 +1,6 @@ # FlowSpec (declarative UI scenarios) -**Status: RECOMMENDED, and the expected form when a UI ships in more than one renderer.** A UI flow is described once, as a declarative scenario, and replayed against every UI implementation. The scenario is the single source of truth for what a flow does; the implementations cannot drift in their behavior because they all run the same steps. The engine is the public package [FlowSpec](https://github.com/mihaelamj/FlowSpec). +**Status: RECOMMENDED, and the expected form when a UI ships in more than one renderer.** A UI flow is described once, as a declarative scenario, and replayed against every UI implementation. The scenario is the single source of truth for what a flow does; the implementations cannot drift in their behavior because they all run the same steps. The engine is the public package [FlowSpec](https://codeberg.org/Mihaela/FlowSpec). ## The model diff --git a/docs/rules/rules-swift/ui/pom.md b/docs/rules/rules-swift/ui/pom.md index 448483b..20007f0 100644 --- a/docs/rules/rules-swift/ui/pom.md +++ b/docs/rules/rules-swift/ui/pom.md @@ -6,7 +6,7 @@ 1. **A base page owns the mechanics.** A single shared base class is constructed with the `XCUIApplication` injected (`init(app:)`) and holds every reusable interaction: waiting for an element to appear or disappear, tapping, asserting existence, scrolling to an element, taking a screenshot. Every method threads `file: StaticString = #filePath, line: UInt = #line` so a failure blames the test's call site, not the base page. Methods are `open` so a page can override a wait without re-implementing it. - A default identifier-driven XCUITest registry ships in `FlowSpecXCUI`, part of the [FlowSpec](https://github.com/mihaelamj/FlowSpec) package, so an app whose views set accessibility identifiers can run scenarios with no custom registry code; the page objects themselves are per-app. See `flowspec.md`. + A default identifier-driven XCUITest registry ships in `FlowSpecXCUI`, part of the [FlowSpec](https://codeberg.org/Mihaela/FlowSpec) package, so an app whose views set accessibility identifiers can run scenarios with no custom registry code; the page objects themselves are per-app. See `flowspec.md`. 2. **One page object per screen.** A concrete page subclasses the base class, file name equals page name. Its locators are computed `XCUIElement` properties that query the app by a shared identifier constant and the typed element kind (`app.buttons[ID.Catalog.search]`, `app.staticTexts[ID.Item.title]`), never a raw string. Its methods split into verifications (return `Self`) and actions (return the next page). From d57457caf44b0d4654818572fcc1bb1634a2317a Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Thu, 2 Jul 2026 21:35:32 +0200 Subject: [PATCH 3/4] chore(rules): track shared-rules baseline v1.1.0 --- .forgejo/workflows/rules-conformance.yml | 24 ++++++++++++++++++++++++ .rules-version | 1 + 2 files changed, 25 insertions(+) create mode 100644 .forgejo/workflows/rules-conformance.yml create mode 100644 .rules-version diff --git a/.forgejo/workflows/rules-conformance.yml b/.forgejo/workflows/rules-conformance.yml new file mode 100644 index 0000000..a035237 --- /dev/null +++ b/.forgejo/workflows/rules-conformance.yml @@ -0,0 +1,24 @@ +# Managed by rules-swift (scripts/sync-rules.sh). Verifies this repo tracks the +# CURRENT shared-rules baseline. The repo's own .swiftformat/.swiftlint.yml are +# repo-specific (baseline + project rules) and are intentionally NOT byte-checked. +name: rules-conformance +on: + push: + pull_request: + workflow_dispatch: +jobs: + rules: + runs-on: macos + steps: + - uses: actions/checkout@v4 + - name: Rules baseline freshness (VERSION) + run: | + BASE=https://codeberg.org/Mihaela/rules-swift/raw/branch/main + canon=$(curl -fsSL "$BASE/VERSION" | tr -d '[:space:]') + mine=$(tr -d '[:space:]' < .rules-version 2>/dev/null || echo MISSING) + if [ "$mine" != "$canon" ]; then + echo "STALE: shared-rules baseline is v$canon, this repo tracks v$mine." + echo "Review the baseline diff, fold it into this repo's rules, then set .rules-version to $canon." + exit 1 + fi + echo "rules baseline FRESH at v$canon (repo-specific rules preserved, not checked)" diff --git a/.rules-version b/.rules-version new file mode 100644 index 0000000..9084fa2 --- /dev/null +++ b/.rules-version @@ -0,0 +1 @@ +1.1.0 From ff0c6d4c3ff66687666d6f9c3beb9f1bc56a0298 Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Sun, 5 Jul 2026 00:27:45 +0200 Subject: [PATCH 4/4] chore(rules): track shared-rules baseline v1.1.2 The v1.1.1 and v1.1.2 canon changes touch only the canon's leak-gate script, which this repo does not vendor, so the stamp is the whole fold. --- .rules-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rules-version b/.rules-version index 9084fa2..45a1b3f 100644 --- a/.rules-version +++ b/.rules-version @@ -1 +1 @@ -1.1.0 +1.1.2