Commit Graph
5344 Commits
Author SHA1 Message Date
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Anthony Stirling
fc048872d7 build(deps): bump idna from 3.12 to 3.15 in /testing/cucumber in the pip group across 1 directory (#6403)
Bumps the pip group with 1 update in the /testing/cucumber directory:
[idna](https://github.com/kjd/idna).

Updates `idna` from 3.12 to 3.15
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/kjd/idna/blob/master/HISTORY.md">idna's
changelog</a>.</em></p>
<blockquote>
<h2>3.15 (2026-05-12)</h2>
<ul>
<li>Enforce DNS-length cap on individual labels early in
<code>check_label</code>,
short-circuiting contextual-rule processing for oversized input
while staying compatible with UTS 46 usage.</li>
<li>Tidy core helpers: hoist bidi category sets to module-level
frozensets (avoiding per-codepoint list construction), simplify
length checks, and reuse the shared <code>_unicode_dots_re</code> from
<code>idna.core</code> in the codec module.</li>
<li>Use <code>raise ... from err</code> for proper exception chaining
and
switch internal string formatting to f-strings.</li>
<li>Allow <code>flit_core</code> 4.x in the build backend.</li>
<li>Expand the ruff lint set (flake8-bugbear, flake8-simplify,
pyupgrade, perflint) and apply the surfaced fixes; pin lint CI
to Python 3.14.</li>
<li>Add Dependabot configuration for GitHub Actions.</li>
<li>Convert README and HISTORY from reStructuredText to Markdown.</li>
<li>Reference CVE-2026-45409 for the 3.14 advisory in place of the
initial GHSA identifier.</li>
</ul>
<p>Thanks to Felix Yan, Stan Ulbrych, and metsw24-max for
contributions to this release.</p>
<h2>3.14 (2026-05-10)</h2>
<ul>
<li>Removed opportunity to process long inputs into quadratic
time by rejecting oversize inputs up-front. Closes a bypass
of the CVE-2024-3651 mitigation. [CVE-2026-45409]</li>
</ul>
<p>Thanks to Stan Ulbrych for reporting the issue.</p>
<h2>3.13 (2026-04-22)</h2>
<ul>
<li>Correct classification error for codepoint U+A7F1</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/kjd/idna/commit/af30a092e158181d0b35ac66dfa813788126bdd8"><code>af30a09</code></a>
Release 3.15</li>
<li><a
href="https://github.com/kjd/idna/commit/30314d4628744ca14cf2b5820564e5127a9f86f2"><code>30314d4</code></a>
Pre-release 3.15rc0</li>
<li><a
href="https://github.com/kjd/idna/commit/05d4b219aa9eddc47371fcbd2000f0301016f3e9"><code>05d4b21</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/237">#237</a> from
kjd/convert-docs-to-markdown</li>
<li><a
href="https://github.com/kjd/idna/commit/2987fdba1962bbb2358399e0084ba062b98a0bee"><code>2987fdb</code></a>
Convert README and HISTORY from reStructuredText to Markdown</li>
<li><a
href="https://github.com/kjd/idna/commit/59fa8002d514bf4a5ce7b58f67b9ec587d53fa9c"><code>59fa800</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/236">#236</a> from
kjd/dependabot/github_actions/actions-f3e34333ea</li>
<li><a
href="https://github.com/kjd/idna/commit/def69834ced5d4b3c50439d8b99c4c856ec19ca2"><code>def6983</code></a>
Merge branch 'master' into
dependabot/github_actions/actions-f3e34333ea</li>
<li><a
href="https://github.com/kjd/idna/commit/bbd8004a797185d8c56bb555cd5c88fde05e0631"><code>bbd8004</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/234">#234</a> from
StanFromIreland/patch-1</li>
<li><a
href="https://github.com/kjd/idna/commit/edd07c05024344a6ccb517414ccb36683aee99fc"><code>edd07c0</code></a>
Bump github/codeql-action from 3.35.2 to 4.35.2 in the actions
group</li>
<li><a
href="https://github.com/kjd/idna/commit/5557db030c11bdec50d62aa5f631d705d33ba123"><code>5557db0</code></a>
Merge branch 'master' into patch-1</li>
<li><a
href="https://github.com/kjd/idna/commit/f11746cf4981d25123ef7830d3ee60f07de8ae3d"><code>f11746c</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/235">#235</a> from
StanFromIreland/patch-2</li>
<li>Additional commits viewable in <a
href="https://github.com/kjd/idna/compare/v3.12...v3.15">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=idna&package-manager=pip&previous-version=3.12&new-version=3.15)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <[email protected]>
2026-05-24 09:51:19 +00:00
dependabot[bot]andGitHub 6ee533c427 build(deps): bump ws from 8.20.0 to 8.20.1 in /frontend (#6400)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:47:49 +01:00
dependabot[bot]andGitHub a13683e84a build(deps): bump protobufjs from 7.5.6 to 7.6.0 in /frontend (#6401)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:44:02 +01:00
914b474d84 build(deps-dev): bump ip-address from 10.1.0 to 10.2.0 in /frontend (#6319)
Co-authored-by: Anthony Stirling <[email protected]>
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:43:11 +01:00
dependabot[bot]andGitHub 51f69a718f build(deps): bump svelte from 5.55.0 to 5.55.9 in /frontend (#6409)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:42:51 +01:00
dependabot[bot]andGitHub 7f597051e4 build(deps): bump reportlab from 4.5.0 to 4.5.1 in /testing/cucumber (#6414)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:42:26 +01:00
dependabot[bot]andGitHub e113df6252 build(deps): bump requests from 2.33.1 to 2.34.2 in /testing/cucumber (#6416)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:42:11 +01:00
dependabot[bot]andGitHub 06b4a4184b build(deps): bump com.diffplug.spotless from 8.4.0 to 8.5.0 (#6417)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:41:52 +01:00
dependabot[bot]andGitHub 19982d7207 build(deps): bump actions/ai-inference from 2.0.7 to 2.1.0 (#6415)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:30:44 +01:00
dependabot[bot]andGitHub cdfefb02bc build(deps): bump github/codeql-action from 4.35.4 to 4.35.5 (#6421)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:30:28 +01:00
dependabot[bot]andGitHub 5ba6a65c1a build(deps): bump step-security/harden-runner from 2.19.1 to 2.19.3 (#6422)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-22 22:30:02 +01:00
ConnorYohandGitHub 017c8d59fa feat(ai): add Contradiction Agent on a new ChunkedMapper primitive (#6369)
## Summary

Adds a new AI specialist that finds **textual contradictions** across
one or more PDFs — conflicting claims, recommendations, points of view,
contested facts — built entirely in Python on top of the new
`DocumentService` + `ChunkedReasoner` stack from #6314. Replaces the
closed #6304, which was started before #6314 landed and therefore
over-engineered (Java orchestrator, two-round handshake, resume
artifact, discriminated-union lift).

Two commits:
1. **`refactor(engine): extract ChunkedMapper[T] from ChunkedReasoner`**
— pure refactor, public API of ChunkedReasoner unchanged. New
`ChunkedMapper[T: BaseModel]` is a generic parallel-chunk primitive
(slicing, semaphore, time-bounded extraction, cancellation drain,
progress events) that's now a peer to ChunkedReasoner rather than locked
inside it. The compression loop stays on ChunkedReasoner where it
belongs.
2. **`feat(ai): add Contradiction Agent on ChunkedMapper`** — the agent
itself, plus integrations into `PdfReviewAgent` and `PdfQuestionAgent`.

## Architecture

- **Python-only.** No Java code. No `AgentToolId.CONTRADICTION_AGENT`.
No dedicated HTTP endpoint. No resume artifact, no discriminated-union
lift in `contracts/common.py`. Detector runs inside the Python engine
and the Python engine alone.
- **Review path** (`PdfReviewAgent`): a new
`ContradictionIntentClassifier` fires on contradiction-flavoured
prompts; agent runs detection synchronously and emits a single
`EditPlanResponse(steps=[ADD_COMMENTS])`. Single-turn flow — no resume.
- **Question path** (`PdfQuestionAgent`): a new
`ContradictionCapability` joins `RagCapability` and
`WholeDocReaderCapability` in the smart-model toolset, exposing
`find_contradictions(query)`. The smart model picks it from the toolset
alongside `search_knowledge` and `read_full_document`.

## Inside `ContradictionDetector.detect()`

1. `DocumentService.read_pages(file_id)` → ordered `list[Page]`.
2. `ChunkedMapper[_ExtractedClaims].map_pages(...)` — char-budgeted
multi-page slicing; each slice runs the claim-extractor LLM in parallel
under a semaphore.
3. Page-traceability: the extractor returns `_ExtractedClaim.page`
(which `[Page N]` marker the claim came from). The wrapper validates
`page ∈ chunk.pages`; if not, mechanical fallback searches the chunk's
page text for the verbatim quote and reassigns. If still no match, drop
the claim.
4. `Claim.anchor_quality: Literal[\"verbatim\", \"paraphrased\"]` is set
by a substring check against the declared page's text. Verbatim quotes
feed `anchor_text` for snap-to-quote add-comments placement; paraphrased
ones fall back to margin geometry.
5. Subject canonicalisation: ONE fast-model LLM call collapses synonyms
across the document. Fails open to lexical bucketing.
6. Pre-filters: drop identical-quote pairs; drop same-page same-polarity
paraphrases.
7. Per-bucket pair detection in parallel (separate semaphore, cap 5).
Buckets > 12 claims chunk into windows of 12 with overlap 2; pairs
deduped across overlapping windows by frozen `(i, j)` index pair.
8. Summary fast-model call with fallback string on error.

## Prompt-injection hardening

Every prompt that interpolates user-supplied or PDF-extracted text wraps
content in `<user_message>` / `<verdict>` / `<content>` tags with an
explicit SECURITY preamble instructing the model to treat tagged content
as data only.

## Limitations

- **Combined math + contradiction intent**: when both intent classifiers
fire on the same prompt, contradiction takes precedence and the math
intent is silently dropped. Documented in the Review module docstring
and pinned by
`test_review_integration.py::test_contradiction_precedence_over_math`.
- **Cross-window contradiction reach**: within a subject bucket, pairs
more than ~10 claim indices apart in the same chunked window may be
missed by the overlap-2 strategy. Documented in `test_detector.py`.
Acceptable for v1.

## Settings (engine/src/stirling/config/settings.py)

```python
contradiction_detect_concurrency = 5     # per-bucket detector semaphore
contradiction_bucket_chunk_size = 12     # max claims per detector call
contradiction_bucket_chunk_overlap = 2   # overlap for >threshold buckets
```

`chars_per_slice` and extraction concurrency are reused from the
existing `chunked_reasoner_*` settings.

## Test plan

- [x] `uv run pytest tests/ -v` — **245/245 pass** (210 pre-existing +
35 new)
- [x] `uv run ruff check src/ tests/` — clean
- [x] `uv run pyright src/stirling/agents/contradiction/
src/stirling/contracts/contradiction.py` — 0 errors
- [x] `./gradlew :proprietary:test` — green; no Java was touched, but
verified untouched
- [x] Page-traceability tests cover: valid page kept, hallucinated page
dropped, mechanical-reassign on misattribution, anchor-quality verbatim
vs paraphrased
- [x] Review integration: ADD_COMMENTS plan with two paired CommentSpecs
per contradiction; NeedIngestResponse precheck; precedence vs math
intent pinned
- [x] Question integration: all three capabilities wired into
smart-model toolset; `find_contradictions` returns formatted report text
- [x] ChunkedMapper standalone: slicing, multi-chunk ordering, worker
failures, timeouts, cancellation drain, semaphore saturation
- [x] ChunkedReasoner regression: all pre-existing tests pass unchanged
after the internal split

## Relationship to closed #6304

#6304 was closed in favour of this PR. The closed PR predated #6314 and
modelled the agent as a Java-orchestrated two-round examine/deliberate
flow with its own HTTP endpoint and a discriminated-union resume
artifact. With #6314 making full ordered page text available to the
engine via `DocumentService.read_pages`, none of that is needed. Net
effect: drop ~600 lines of Java, drop the two-round handshake, drop the
`ToolReportArtifact` lift, while ending up with a more scalable agent
(chunk-based instead of page-based extraction; tested to
ChunkedReasoner-equivalent scale).
2026-05-22 13:23:52 +00:00
0a50e765b7 Restructure/frontend editor (#6404)
## Move editor under `frontend/editor/`

Pure restructure: `frontend/` becomes the workspace, `frontend/editor/`
holds
  the PDF editor. 1775 file renames + 40 wiring edits. No logic changes.

  ### Why

`frontend/` is currently the editor — its `src/`, `public/`,
`src-tauri/`,
  config files all sit at the root. Promoting `frontend/` to a
workspace and putting the editor in a sibling folder leaves room for
future
apps to drop in alongside it, sharing one `package.json` /
`node_modules` /
  lint config / Storybook.

  ### What moves

  frontend/
  ├── editor/                ← NEW: everything editor-specific
  │   ├── src/               ← was frontend/src/
  │   ├── public/            ← was frontend/public/
  │   ├── src-tauri/         ← was frontend/src-tauri/
│ ├── index.html, vite.config.ts, vitest.config.ts, playwright.config.ts
  │   ├── tsconfig*.json, tailwind.config.js, postcss.config.js
  │   ├── scripts/
  │   ├── .env, .env.desktop, .env.saas
  │   └── DeveloperGuide.md
├── package.json, package-lock.json, node_modules/ ← workspace install
  ├── eslint.config.mjs, .prettierrc, .prettierignore ← shared tooling
  ├── .gitignore
  └── README.md

  ### Wiring edits (40 files)

  - `.taskfiles/frontend.yml`, `desktop.yml`, `e2e.yml`
  - `build.gradle`, `app/core/build.gradle`
- `eslint.config.mjs`, `frontend/package.json`, `.gitignore`,
`.prettierignore`
  - `docker/frontend/Dockerfile`
  - 8 `.github/workflows/*.yml`, plus `.github/dependabot.yml`,
    `.github/config/.files.yaml`, `.github/labeler-config-srvaroa.yml`
  - `scripts/translations/**`
- Docs: `AGENTS.md`, `CLAUDE.md`, `ADDING_TOOLS.md`,
`DeveloperGuide.md`,
`WINDOWS_SIGNING.md`, `devGuide/HowToAddNewLanguage.md`,
`frontend/README.md`,
    `frontend/editor/DeveloperGuide.md`

Plus 3 renamed + edited: `editor/vite.config.ts` (env path +
node_modules
  walk-up), `editor/scripts/setup-env.mts` (renamed from `.ts` for
`import.meta.url`), `editor/scripts/build-provisioner.mjs` (resolve
src-tauri
  relative to script).

  ### Verification

  | Check | Result |
  |---|---|
  | `task frontend:typecheck:all` (6 variants) | exit 0 |
  | `task frontend:lint` (eslint + dpdm) | exit 0 |
  | `task frontend:format:check` | exit 0 |
  | `task frontend:test` | 657 tests pass, 50 files |
| `task frontend:build:{core,proprietary,saas,desktop,prototypes}` | all
green |
| `task desktop:build` | full Tauri pipeline →
`Stirling-PDF_2.11.0_x64_en-US.msi` |
  | `playwright test --list --project=stubbed` | 172 tests discovered |

`task desktop:build` exercises the heaviest path — Rust + WiX + MSI
bundle
against the moved `editor/src-tauri/`. If anything in the restructure
was
  wrong it wouldn't have built.

  ### Test plan

  - [ ] `frontend-validation.yml` green
  - [ ] `e2e-stubbed.yml` green
  - [ ] `tauri-build.yml` green on at least one platform
  - [ ] `check_toml.yml` runs on a translation-touching PR

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-22 13:40:34 +01:00
Anthony StirlingandGitHub 48027ee9d6 JDK25 - Integrate Stirling-Tools JPDFium for PDF operations (#6387) 2026-05-22 13:19:46 +01:00
22d56bb1fb test Depot runners for team commits (#6394)
Co-authored-by: ConnorYoh <[email protected]>
2026-05-21 16:54:20 +01:00
9d081d1792 SaaS Consolidation (#6384)
Co-authored-by: ConnorYoh <[email protected]>
2026-05-21 16:05:35 +01:00
089de247b4 Updated Spanish translation (#6309)
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Ludy <[email protected]>
Co-authored-by: Anthony Stirling <[email protected]>
2026-05-21 13:16:07 +01:00
dependabot[bot]andGitHub 0c3a512b21 build(deps): bump softprops/action-gh-release from 2.6.1 to 3.0.0 (#6346)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:34:16 +01:00
dependabot[bot]andGitHub 707cfa3140 build(deps): bump devalue from 5.6.4 to 5.8.1 in /frontend (#6367)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:18:43 +01:00
dependabot[bot]andGitHub ea91a35518 build(deps): bump org.postgresql:postgresql from 42.7.10 to 42.7.11 (#6375)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:17:36 +01:00
dependabot[bot]andGitHub 5a5aada2d8 build(deps): bump pypdf from 6.10.2 to 6.11.0 in /testing/cucumber (#6376)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:17:18 +01:00
dependabot[bot]andGitHub a4ef70eaf8 build(deps): bump sigstore/cosign-installer from 4.1.1 to 4.1.2 (#6377)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:17:04 +01:00
dependabot[bot]andGitHub d76d25654a build(deps): bump actions/dependency-review-action from 4.9.0 to 5.0.0 (#6378)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:16:48 +01:00
dependabot[bot]andGitHub 31b00b7d06 build(deps): bump github/codeql-action from 4.35.3 to 4.35.4 (#6379)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:16:42 +01:00
dependabot[bot]andGitHub f00c12ad8a build(deps): bump step-security/harden-runner from 2.19.0 to 2.19.1 (#6380)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:16:38 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1f5c046362 build(deps): bump tokio from 1.49.0 to 1.50.0 in /frontend/src-tauri in the tokio group across 1 directory (#6296)
Bumps the tokio group with 1 update in the /frontend/src-tauri
directory: [tokio](https://github.com/tokio-rs/tokio).

Updates `tokio` from 1.49.0 to 1.50.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/tokio/releases">tokio's
releases</a>.</em></p>
<blockquote>
<h2>Tokio v1.50.0</h2>
<h1>1.50.0 (Mar 3rd, 2026)</h1>
<h3>Added</h3>
<ul>
<li>net: add <code>TcpStream::set_zero_linger</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7837">#7837</a>)</li>
<li>rt: add <code>is_rt_shutdown_err</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7771">#7771</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>io: add optimizer hint that <code>memchr</code> returns in-bounds
pointer (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7792">#7792</a>)</li>
<li>io: implement vectored writes for <code>write_buf</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7871">#7871</a>)</li>
<li>runtime: panic when <code>event_interval</code> is set to 0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7838">#7838</a>)</li>
<li>runtime: shorten default thread name to fit in Linux limit (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7880">#7880</a>)</li>
<li>signal: remember the result of <code>SetConsoleCtrlHandler</code>
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7833">#7833</a>)</li>
<li>signal: specialize windows <code>Registry</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7885">#7885</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>io: always cleanup <code>AsyncFd</code> registration list on
deregister (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7773">#7773</a>)</li>
<li>macros: remove (most) local <code>use</code> declarations in
<code>tokio::select!</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7929">#7929</a>)</li>
<li>net: fix <code>GET_BUF_SIZE</code> constant for <code>target_os =
&quot;android&quot;</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7889">#7889</a>)</li>
<li>runtime: avoid redundant unpark in current_thread scheduler (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7834">#7834</a>)</li>
<li>runtime: don't park in <code>current_thread</code> if
<code>before_park</code> defers waker (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7835">#7835</a>)</li>
<li>io: fix write readiness on ESP32 on short writes (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7872">#7872</a>)</li>
<li>runtime: wake deferred tasks before entering
<code>block_in_place</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7879">#7879</a>)</li>
<li>sync: drop rx waker when oneshot receiver is dropped (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7886">#7886</a>)</li>
<li>runtime: fix double increment of <code>num_idle_threads</code> on
shutdown (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7910">#7910</a>,
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7918">#7918</a>,
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7922">#7922</a>)</li>
</ul>
<h3>Unstable</h3>
<ul>
<li>fs: check for io-uring opcode support (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7815">#7815</a>)</li>
<li>runtime: avoid lock acquisition after uring init (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7850">#7850</a>)</li>
</ul>
<h3>Documented</h3>
<ul>
<li>docs: update outdated unstable features section (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7839">#7839</a>)</li>
<li>io: clarify the behavior of <code>AsyncWriteExt::shutdown()</code>
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7908">#7908</a>)</li>
<li>io: explain how to flush stdout/stderr (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7904">#7904</a>)</li>
<li>io: fix incorrect and confusing <code>AsyncWrite</code>
documentation (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7875">#7875</a>)</li>
<li>rt: clarify the documentation of <code>Runtime::spawn</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7803">#7803</a>)</li>
<li>rt: fix missing quotation in docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7925">#7925</a>)</li>
<li>runtime: correct the default thread name in docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7896">#7896</a>)</li>
<li>runtime: fix <code>event_interval</code> doc (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7932">#7932</a>)</li>
<li>sync: clarify RwLock fairness documentation (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7919">#7919</a>)</li>
<li>sync: clarify that <code>recv</code> returns <code>None</code> once
closed and no more messages (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7920">#7920</a>)</li>
<li>task: clarify when to use <code>spawn_blocking</code> vs dedicated
threads (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7923">#7923</a>)</li>
<li>task: doc that task drops before <code>JoinHandle</code> completion
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7825">#7825</a>)</li>
<li>signal: guarantee that listeners never return <code>None</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7869">#7869</a>)</li>
<li>task: fix task module feature flags in docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7891">#7891</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/tokio/commit/0273e45ead199dac7725faee1e3dc35a9c8753ab"><code>0273e45</code></a>
chore: prepare Tokio v1.50.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7934">#7934</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/e3ee4e58dc9bb7accf26dfd51b0a2146922b5269"><code>e3ee4e5</code></a>
chore: prepare tokio-macros v2.6.1 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7943">#7943</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/8c980ea75a0f8dd2799403777db700c2e8f4cda4"><code>8c980ea</code></a>
io: add <code>write_all_vectored</code> to <code>tokio-util</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7768">#7768</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/e35fd6d6b7d9a8ba37ee621835ef91372c2565cb"><code>e35fd6d</code></a>
ci: fix patch during clippy step (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7935">#7935</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/03fe44c10302fdb55c29dbe5b08d4f8769c80272"><code>03fe44c</code></a>
runtime: fix <code>event_interval</code> doc (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7932">#7932</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/d18e5dfbb0cdc28725bebb28cde80a6c11ee32bc"><code>d18e5df</code></a>
io: fix race in <code>Mock::poll_write</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7882">#7882</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/f21f2693f02aec9a876ac2bd21566c85e15b682e"><code>f21f269</code></a>
runtime: fix race condition during the blocking pool shutdown (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7922">#7922</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/d81e8f0acbdd7d866bce4f733b3545fd834c7840"><code>d81e8f0</code></a>
macros: remove (most) local <code>use</code> declarations in
<code>tokio::select!</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7929">#7929</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/25e7f2641ef2555d688c267059431a2802805f1d"><code>25e7f26</code></a>
rt: fix missing quotation in docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7925">#7925</a>)</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/e1a91ef114a301b542d810abab9956f2868861b9"><code>e1a91ef</code></a>
util: fix typo in docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7926">#7926</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-1.49.0...tokio-1.50.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 14:16:18 +01:00
dependabot[bot]andGitHub 1787443102 build(deps): bump fast-uri from 3.0.6 to 3.1.2 in /devTools (#6332)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:15:08 +01:00
dependabot[bot]andGitHub 8fb281525b build(deps): bump quinn-proto from 0.11.13 to 0.11.14 in /frontend/src-tauri (#6322)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:13:31 +01:00
LudyandGitHub 4c3be4992f deps: align Bouncy Castle modules to shared version property (#6362) 2026-05-20 14:11:43 +01:00
dependabot[bot]andGitHub 2790467241 build(deps): bump urllib3 from 2.6.3 to 2.7.0 in /testing/cucumber in the pip group across 1 directory (#6352)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:11:11 +01:00
dependabot[bot]andGitHub dd770dfa76 build(deps): bump rustls-webpki from 0.103.9 to 0.103.13 in /frontend/src-tauri (#6323)
Signed-off-by: dependabot[bot] <[email protected]>
2026-05-20 14:10:56 +01:00
ConnorYohandGitHub b146d9994d fix(task): make task dev / task dev:all work on Windows (#6392)
## Summary

`#6145` (port picker) and `#6244` (gradle unification) combined to break
`task dev` / `task dev:all` on Windows. Two independent regressions,
both addressed here.

### 1. `find-free-port.ps1` panic (`#6145`)

```
$ task --dry dev
The argument 'scriptsfind-free-port.ps1' to the -File parameter does not exist.
panic: ended up with a non-nil exitStatus.err but a zero exitStatus.code
```

- **Backslash stripped.** `Taskfile.yml` had
`scripts\find-free-port.ps1`. go-task pipes the `sh:` block through
mvdan/sh, which treats `\` as a POSIX escape and silently drops it,
leaving `scriptsfind-free-port.ps1`. PowerShell can't find the file,
exits non-zero, mvdan/sh panics on the inconsistent exit status.
Switched to a forward slash.
- **`-Preferred 8080,5173` is brittle.** Relies on PowerShell parsing
the comma-list into `[int[]]`. Dropped the named flag; switched the
script's `param` to `[Parameter(ValueFromRemainingArguments =
$true)][int[]]$Preferred`; pass each port as its own positional token
(matching how the bash variant is called).

### 2. `bash gradlew` can't find Java on Windows (`#6244`)

```
[backend:dev] ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
```

`#6244` unified all gradle invocations under `bash gradlew` on the
assumption that Git-Bash inherits Windows-side env. It doesn't (and
neither does WSL bash, which can also shadow `bash` on a developer's
PATH). The standard Adoptium/Temurin installer sets `JAVA_HOME` in the
Windows env only, so `bash gradlew` fails before Spring Boot even loads.

Restored the per-platform branch for every backend task: `cmd /c
".\gradlew.bat ..."` on Windows, `./gradlew ...` on Linux/macOS. Two
Windows-specific gotchas to be aware of for future edits:

- mvdan/sh strips `\` outside of double quotes, so `cmd /c
.\gradlew.bat` ends up as `.gradlew.bat`. The entire payload must be
wrapped in double quotes (`cmd /c "..."`).
- Modern Windows excludes cwd from cmd.exe's search path, so the leading
`.\` is required — bare `cmd /c gradlew.bat` errors with "is not
recognized" even from the repo root.

## Test plan

- [x] `task --dry dev` / `task --dry dev:all` on Windows resolve ports
cleanly and dispatch the inner tasks
- [x] `powershell -NoProfile -File scripts/find-free-port.ps1 8080 5173
5001` prints three ports
- [x] `task backend:dev PORT=8081` on Windows starts Spring Boot in ~9s;
`/api/v1/info/status` returns `{"status":"UP"}`
- [x] `task dev:all` on Windows brings up all three services healthy:
backend `/api/v1/info/status` 200, engine `/health` 200, frontend `/`
200
- [ ] Linux / macOS path unaffected (only the Windows branches changed
in behaviour)
2026-05-20 12:57:41 +00:00
2399da6893 migrate exportUpdatedPages from bytes to stream (#6201)
Co-authored-by: ConnorYoh <[email protected]>
2026-05-19 23:03:44 +01:00
EthanHealy01andGitHub 2c15044dfa Snag/disable logo drag (#6393) 2026-05-19 18:13:58 +00:00
ConnorYohandGitHub 31f6ea4b25 perf(frontend): stabilize hot-path context subscriptions to fix excessive rerenders (#6373)
## Summary

The frontend was rerendering excessively across many interactions —
typing, clicking tools, opening modals, toggling the sidebar — because
**multiple compounding ref-instability cascades defeated `memo()` checks
in hot paths**. This PR fixes the cascades structurally.

Seven focused commits, low-to-high blast radius:

1. `perf(contexts): memoize BannerContext provider value`
2. `perf(contexts): memoize CommentAuthor and ActiveDocument provider
values`
3. `perf(contexts): memoize AppConfigContext provider value`
4. `perf(useToolManagement): stop spreading tool entries to keep refs
stable` — **root-cause fix**
5. `refactor(ToolPicker): hoist module-scope styles and helpers`
6. `feat(ToolWorkflowContext): add ref-stable Actions and Data subset
contexts` — additive
7. `perf(tools): migrate hot consumers to slim contexts and wrap in
memo()`

(Plus `style: apply prettier formatting` for CI.)

## What was wrong

Whenever something high-up in the tree caused a render, a chain of
unstable references propagated downward and forced every `ToolButton` to
re-execute its full body (hooks, derived computations, hook
subscriptions to other contexts). The chain:

- **4 unstable Context providers** (`Banner`, `CommentAuthor`,
`ActiveDocument`, `AppConfig`) were passing fresh `value={{ … }}`
objects on every render. Every consumer rerendered on every ancestor
render.
- **`useToolManagement.toolRegistry`** spread `{...baseTool, name,
description}` — a no-op spread that manufactured a new tool object
identity on every memo recompute.
- **The big `ToolWorkflowContext`** (25+ fields including
`state.searchQuery`) rebuilt its entire value on every
keystroke/click/toggle, forcing every `useToolWorkflow()` consumer (~36
files) to rerender.
- **`useToolNavigation`** transitively subscribed every `ToolButton` to
the full workflow context.
- **`ToolButton` & `ToolPicker`** weren't `memo()`-wrapped, so nothing
checked.
- **`ToolPanel`** passed inline `onSelect={(id) =>
handleToolSelect(...)}` — fresh ref every render, defeats child
memoization.
- **`ToolPicker`** allocated inline styles / `[]` / `toTitleCase` inside
the function body — churned `useToolSections`'s internal memo.

## Interaction matrix — what improves

The PR fixes the underlying ref-stability problem; the same fix benefits
*every* interaction that previously triggered the cascade:

| Interaction | Before | After |
|---|---|---|
| **Typing in tool search** | All visible buttons rerender per keystroke
| Only buttons whose matched-text changes rerender |
| **Clicking a tool** | All 36 `useToolWorkflow()` consumers rerender |
Only previously-selected and newly-selected buttons rerender (via
`isSelected` prop) |
| **Toggling sidebar / panel mode / reader mode** | Every tool button
rerenders | Tool components stay still (slim context doesn't see UI
state) |
| **Switching workbench / navigation** | `handleToolSelect` identity
changes → cascades through `onSelect` props | Ref-stabilized in Actions
context. Identity stable. Children's memo bails |
| **Modal/dialog open/close** | AppConfig churns → every `useAppConfig`
consumer rerenders (ToolButton reads `premiumEnabled`) | AppConfig
memoized; consumers rerender only when config changes |
| **Banner show/hide** | BannerProvider value churns → every consumer
rerenders on any ancestor render | Memoized; AppLayout rerenders only
when banner content changes |
| **Any state update high in the tree** | Compounding cascade defeats
memo everywhere | Stable subscriptions; memo bails out |

## Evidence

Per-keystroke prop instability on `ToolButton` (cleanest measurable
signal, captured via custom memo comparators logging which prop refs
differ):

| | `tool` ref diffs | `onSelect` ref diffs | `matchedSynonym` value
diffs | Total |
|---|---|---|---|---|
| Before | 18 | 18 | 6 | **42** |
| After  | 0  | 0  | 6 | **6 (all legitimate)** |

→ **86% reduction** in spurious per-keystroke prop instability. The 6
remaining matched-synonym diffs are correct (different substring
highlighted per keystroke).

Context value rebuild counts during a keystroke (verified with
instrumented `useMemo` factories): `useToolWorkflowData=0`,
`useToolWorkflowActions=0`, `AppConfigContext=0`.

The same stabilization applies to click/toggle/modal interactions — they
were all driven by the same cascading invalidations.

## Honest caveat on render-count metrics

`React.Profiler` counts and function-body execution counts in **dev
mode** came back identical before vs after (StrictMode + concurrent
rendering + Mantine internal commits dominate the numbers). The PR's
value is measured against the **prop-stability signal** above, not
Profiler counts. Production builds — where StrictMode doesn't
double-render and Mantine internals aren't constantly committing — will
show memo bail out properly.

## Risk × benefit

| # | Commit | Risk | Benefit |
|---|--------|------|---------|
| 1 | BannerContext memo |  Trivial | 🟦 Small |
| 2 | CommentAuthor + ActiveDocument memo |  Trivial | 🟦 Small |
| 3 | AppConfig memo |  Trivial | 🟦 Moderate (wide consumer base) |
| 4 | useToolManagement spread removal |  Trivial | 🟥 **High (root
cause)** |
| 5 | ToolPicker hoist |  Trivial | 🟦 Small |
| 6 | ToolWorkflowContext split | 🟧 Low-Med | 🟥 **High (foundation)** |
| 7 | Hot consumer migration + memo | 🟧 Low-Med | 🟥 **High
(actualization)** |

Commit 6 introduces an invariant: ref-stabilized callbacks in the
Actions context must only be invoked from event handlers (post-commit),
never during render. All current call sites comply.

## Test plan

- [x] `npx playwright test --project=stubbed` — 145 / 6 skipped / 0
failed before and after.
- [x] Targeted regression: `main-dashboard`, `tool-search`, `navigation`
— 11/11 passing.
- [x] CI passing on commits (one infrastructure flake on
`docker-compose-tests` — "No space left on device" — unrelated;
rerunning).
- [ ] Manual sanity check in a dev build after merge.

## What this enables

The same Actions + Data subset-context pattern can be applied to
`FileContext`, `NavigationContext`, and other big contexts. The
foundation is in place.
2026-05-19 15:56:50 +00:00
Anthony StirlingandGitHub f9fbc37800 add translations (#6390) 2026-05-19 11:25:13 +01:00
6b9567cf38 Split and delete forms (#6277)
Delete orphaned forms when removing pages and maintain forms correctly
when splitting

---------

Co-authored-by: ConnorYoh <[email protected]>
2026-05-18 11:14:55 +00:00
c731d5fd5d UI redesign staging (#6149)
Co-authored-by: Reece Browne <[email protected]>
Co-authored-by: James Brunton <[email protected]>
2026-05-15 15:36:50 +01:00
James BruntonandGitHub beb99e273b Improve edit agent's knowledge of tools (#6356)
# Description of Changes
Give Edit Agent access to descriptions of the request from the Java API.
This opens the door to us better documenting our Java APIs to give the
stirling engine better knowledge of what the various tools are and how
to use them.

Also improves the tool selection sub-agent to get the tool parameters
and descriptions so it can more intelligently decide which operations
should be used to fulfil the user's request. Also provides it more
encouragement to string together multiple operations if necessary.
2026-05-14 18:30:39 +00:00
ece1bb6865 Feature/pdf to markdown agent (#6271)
Co-authored-by: James Brunton <[email protected]>
2026-05-14 16:20:45 +00:00
LudyandGitHub 5b9ef852ab ci: remove frontend validation PR comment after successful check (#6360)
# Description of Changes

- Added a GitHub Actions step to remove the frontend validation check
comment when the frontend check succeeds on pull requests.
- The step searches for an existing PR comment containing the `<!--
frontend-check -->` marker and deletes it if found.
- The change was made to keep pull request discussions clean by removing
stale frontend check comments once the validation passes.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-05-14 13:19:55 +00:00
James BruntonandGitHub 672e81d286 Add ability for Stirling engine to reason across large documents (#6314)
# Description of Changes
Adds storage in the database for full document content alongside the RAG
content (and changes the service to `DocumentService` instead of
`RagService`). Then adds a generic capability that should be usable by
any agent (currently just used by the Question Agent) which allows the
agent to pull out the full contents of the doc, chunks it into various
sections that will fit in the context window, and then processes them in
parallel to create an intermediate result, and then processes the
intermediate result into a final answer. It will re-chunk as many times
as necessary to get the content small enough for the actual answer to be
analysed (I've tested on PDFs ~3500 pages long, which is well above the
context limit and requires maybe 3 rounds of compression to get an
answer).

The new full doc analysis stuff is heavier than the RAG lookup so both
remain. The agents should use RAG for targeted info and the chunked
reasoner for info that requires reading the full doc.
2026-05-14 13:19:38 +00:00
James BruntonandGitHub 8abe734f0b Fix main frontend validation (#6361)
# Description of Changes
#6312 reformatted `tauri.conf.json` via the Gradle script, which
reformats the entire file to not match the Prettier style. This PR
reformats the file back to Prettier format and changes the script to
update the version number without reformatting the entire file.

To be honest I'm not a huge fan of updating the version number with
regexes but it'd be a fool's errand to try and get Gradle to output JSON
in Prettier format, and this seems simpler than shelling out to run
Prettier over the file after the version string has been updated. Any
better ideas, let me know.
2026-05-14 12:31:45 +00:00
stirlingbot[bot]GitHubstirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>Anthony Stirling
8a59c10f42 Update Backend 3rd Party Licenses (#6312)
Auto-generated by stirlingbot[bot]

This PR updates the backend license report based on dependency changes.

---------

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <[email protected]>
2026-05-13 16:30:58 +01:00
Anthony StirlingandGitHub d62f2ad3ed unoserver docker (#6328)
# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-05-12 13:22:15 +01:00
f60a075443 Add Playwright/bootRun/test.sh tasks (#6244)
## Description

Consolidates Playwright running under cohesive Task namespaces, isolates
Playwright state from the developer's local working tree, and swaps CI's
frontend webserver from `vite` dev to `vite preview` against a pre-built
`dist/`.

### `e2e:*` namespace

Renames `.taskfiles/testing.yml` to `.taskfiles/e2e.yml` and
consolidates everything Playwright-related under one `e2e:` namespace:

- `e2e:stubbed` / `e2e:live` / `e2e:enterprise` / `e2e:cross-browser`:
project-specific runners
- `e2e:check` (no-Docker subset) and `e2e:check:all` (full)
- `e2e:oauth:up` / `:down`, `e2e:saml:up` / `:down`: symmetric lifecycle
for the keycloak compose stacks
- `e2e:install`: Playwright browser install
- `docker:test`: full Docker integration suite

The redundant `frontend:test:e2e:*` project shortcuts are removed. CI
workflows (`e2e-stubbed.yml`, `e2e-live.yml`, `build-enterprise.yml`,
`nightly.yml`) are updated to call the new task names.

### Isolated Playwright state

New `STIRLING_BASE_PATH` (and `-Dstirling.base-path=`) override in
`InstallationPathConfig` redirects the entire state tree (configs,
backups, customFiles, pipeline, logs) at startup. `task e2e:live` points
it at `.test-state/playwright/` (purged on every invocation) so the
suite never touches the developer's local DB, settings.yml or backups.

`task e2e:live` auto-spawns gradle, waits for `/api/v1/info/status` to
come up, runs Playwright, then tears down the whole backend process
tree.

### CI runs Playwright against `vite preview`

Builds the frontend up-front with `VITE_BUILD_FOR_PREVIEW=1` (forces
absolute base so deep SPA routes resolve `/assets/...`) and the
playwright `webServer` now uses `vite preview --port 5173 --strictPort`
in CI. Avoids the per-page on-demand transform cost that was blowing the
30s navigation timeout under `--workers=3` on
`all-tool-pages-load.spec.ts`. Local dev keeps `vite` dev for HMR.

### OAuth/SAML compose helpers

`start-oauth-test.sh` and `start-saml-test.sh` gain a `--license-key
<KEY>` (`-k`) flag so CI and scripted runs can skip the interactive
license prompt. `start-oauth-test.sh` also moves from `for arg in "$@"`
to a `while`-with-`shift` arg loop to support multi-arg flags
consistently with the SAML script.

### Backend gradlew unification

Drops the per-platform `cmd /c gradlew.bat` branches from `backend.yml`
and routes every gradle invocation through `bash gradlew`. Works
uniformly on Linux/macOS and Windows-with-Git-Bash.

### Compare.tsx flake fix (re-land of
[#6316](https://github.com/Stirling-Tools/Stirling-PDF/pull/6316))

Piggybacks Anthony's never-merged fix from #6316. Without it,
`e2e:stubbed` continues to flake under `--workers=3` on
`compare.spec.ts`'s second-upload case via a React "Maximum update depth
exceeded" infinite loop in the Compare auto-fill effect. CI traces from
recent failed runs match exactly; 10 local runs of `compare.spec.ts`
with `CI=1 --workers=3` pass cleanly with the fix applied.

---------

Co-authored-by: James Brunton <[email protected]>
2026-05-11 14:50:07 +00:00
James BruntonandGitHub c059e13423 Fix desktop app overscrolling inappropriately (#6350)
# Description of Changes
Fix #6348
2026-05-11 14:31:00 +00:00
575684ee4b Add edit text support to stirling engine (#6245)
# Description of Changes
Hooks up the (alpha) PDF Editor backend to the AI engine Edit Agent via
an intermediary API which is easier for the agent to call. It suffers
from all the same issues that the PDF Editor does in actually editing
the text, but should also benefit from any fixes to that.

It also adds protection against the underlying tools misbehaving by
hanging, and fixes a hanging bug in the PDF Editor.

---------

Co-authored-by: EthanHealy01 <[email protected]>
2026-05-11 09:57:41 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
294b616a63 build(deps): bump org.springframework.boot:spring-boot-dependencies from 4.0.5 to 4.0.6 (#6337)
Bumps
[org.springframework.boot:spring-boot-dependencies](https://github.com/spring-projects/spring-boot)
from 4.0.5 to 4.0.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/spring-projects/spring-boot/releases">org.springframework.boot:spring-boot-dependencies's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.6</h2>
<h2>🐞 Bug Fixes</h2>
<ul>
<li>Default security is misconfigured when
spring-boot-actuator-autoconfigure is present and spring-boot-health is
not <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50188">#50188</a></li>
<li>Elasticsearch Rest5Client auto-configuration misconfigures
underlying HTTP client <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50187">#50187</a></li>
<li>ApplicationPidFileWriter does not handle symlinks correctly <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50185">#50185</a></li>
<li>RandomValuePropertySource is not suitable for secrets <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50183">#50183</a></li>
<li>Cassandra auto-configuration misconfigures CqlSessionBuilder <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50180">#50180</a></li>
<li>ApplicationTemp does not handle symlinks correctly <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50178">#50178</a></li>
<li>Remote DevTools performs comparison incorrectly <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50176">#50176</a></li>
<li>spring.rabbitmq.ssl.verify-hostname is applied inconsistently <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50174">#50174</a></li>
<li>Whole number values are ignored when configuring min and max
expected values and SLO boundaries for a distribution summary meter <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50077">#50077</a></li>
<li>Classic starters are missing several modules <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50071">#50071</a></li>
<li>Module spring-boot-resttestclient is missing from
spring-boot-starter-test-classic <a
href="https://redirect.github.com/spring-projects/spring-boot/pull/50069">#50069</a></li>
<li>Annotations like <code>@Ssl</code> don't work on <code>@Bean</code>
methods when using <code>@ServiceConnection</code> <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50064">#50064</a></li>
<li>EnversRevisionRepositoriesRegistrar should reuse
<code>@EnableEnversRepositories</code> rather than configuring the JPA
counterpart <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50039">#50039</a></li>
<li>WebFlux Cloud Foundry links endpoint includes query string from
received request in resolved links <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50017">#50017</a></li>
<li>Imports on a containing test class are ignored when a nested class
has imports <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50012">#50012</a></li>
<li>With spring.jackson.use-jackson2-defaults set to true,
FAIL_ON_UNKNOWN_PROPERTIES is enabled <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49951">#49951</a></li>
<li>500 response from env endpoint when supplied pattern is invalid <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49946">#49946</a></li>
<li>Reactive MongoDB starter has a transitive dependency on the
synchronous MongoDB driver <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49945">#49945</a></li>
<li>HTTP method is lost when configuring excludes in EndpointRequest <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49943">#49943</a></li>
<li>Honor HttpMethod for reactive additional endpoint paths <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49880">#49880</a></li>
<li>Docker Compose support doesn't work with apache/artemis image <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49869">#49869</a></li>
<li>Docker Compose support doesn't work with apache/activemq image <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49866">#49866</a></li>
<li>Spring Security's PathPatternRequestMatcher.Builder is not
auto-configured when using WebMvcTest and spring-boot-security-test <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49854">#49854</a></li>
<li>API versioning path strategy should be applied path last as it is
not meant to yield <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49800">#49800</a></li>
</ul>
<h2>📔 Documentation</h2>
<ul>
<li>Update docs to encourage Java fundamentals for beginners that prefer
to learn that way <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50146">#50146</a></li>
<li>HTTP Service Interface Clients still document that API versioning
can be configured via properties <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50126">#50126</a></li>
<li>Link to the observability section of the Lettuce documentation is
broken <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50097">#50097</a></li>
<li>Javadoc for StaticResourceLocation.FAVICON doesn't describe icons
location <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50085">#50085</a></li>
<li>MySamlRelyingPartyConfiguration is missing a Kotlin sample <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50024">#50024</a></li>
<li>Incorrect default value for
management.httpexchanges.recording.include in configuration metadata <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50019">#50019</a></li>
<li>Link to the Kubernetes documentation when discussing startup probes
<a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50015">#50015</a></li>
<li>Typo in JdbcSessionAutoConfiguration Javadoc <a
href="https://redirect.github.com/spring-projects/spring-boot/pull/49873">#49873</a></li>
<li>Clarify that configuration property default values are not available
through the Environment <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49851">#49851</a></li>
<li>Document the need for Liquibase and Flyway starters <a
href="https://redirect.github.com/spring-projects/spring-boot/pull/49839">#49839</a></li>
<li>Kafka documentation refers to deprecated JSON serializer and
deserializer classes <a
href="https://redirect.github.com/spring-projects/spring-boot/pull/49826">#49826</a></li>
</ul>
<h2>🔨 Dependency Upgrades</h2>
<ul>
<li>Upgrade to Elasticsearch Client 9.2.8 <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50027">#50027</a></li>
<li>Upgrade to Groovy 5.0.5 <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49911">#49911</a></li>
<li>Upgrade to Hibernate 7.2.12.Final <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50134">#50134</a></li>
<li>Upgrade to Jackson Bom 3.1.2 <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50051">#50051</a></li>
<li>Upgrade to <a
href="https://github.com/jaxen-xpath/jaxen/releases/tag/v2.0.1">Jaxen
2.0.1</a> <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/50104">#50104</a></li>
<li>Upgrade to <a
href="https://github.com/FirebirdSQL/jaybird/releases/tag/v6.0.5">Jaybird
6.0.5</a> <a
href="https://redirect.github.com/spring-projects/spring-boot/issues/49914">#49914</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/8821ad2cd381bb4b9615a61479e1de7305a8ba39"><code>8821ad2</code></a>
Release v4.0.6</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/9e4048a03f17adfe78057a3c4d5b4693305c0ae0"><code>9e4048a</code></a>
Merge branch '3.5.x' into 4.0.x</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/20bb11c3984802990572ddbeae8b66885a8f2462"><code>20bb11c</code></a>
Next development version (v3.5.15-SNAPSHOT)</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/98daa8ea30f39a5b0ca6768b5cbc2dc8698ef4e1"><code>98daa8e</code></a>
Merge branch '3.5.x' into 4.0.x</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/9dc5aa2863f598a15d3dfa116f4b89249daba7e7"><code>9dc5aa2</code></a>
Polish</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/874f6294b91da18367b8b5ab7b2fad3fa23cfba6"><code>874f629</code></a>
Fix default security with actuator but without health</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/e41b3bf731d1134bc18ec1f68ac01e0fe1c54923"><code>e41b3bf</code></a>
Enable hostname verification for SSL connections to Elasticsearch</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/ef8527bb0ef8f564f4f9c57a7be99a7aa96c6ab0"><code>ef8527b</code></a>
Merge branch '3.5.x' into 4.0.x</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/f533a4549c3999aac30cb5830f07dc304933e93d"><code>f533a45</code></a>
Do not follow symlinks when writing PID file</li>
<li><a
href="https://github.com/spring-projects/spring-boot/commit/4a7bd332b6d19fef1aa4cf28434985f2b03a2e0f"><code>4a7bd33</code></a>
Merge branch '3.5.x' into 4.0.x</li>
<li>Additional commits viewable in <a
href="https://github.com/spring-projects/spring-boot/compare/v4.0.5...v4.0.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.springframework.boot:spring-boot-dependencies&package-manager=gradle&previous-version=4.0.5&new-version=4.0.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-11 10:52:41 +01:00
LudyandGitHub f61121953e fix: replace deprecated payload too large status (#6336)
# Description of Changes

- Replaced the deprecated `HttpStatus.PAYLOAD_TOO_LARGE` usage with
`HttpStatus.CONTENT_TOO_LARGE` in `GlobalExceptionHandler`
- Updated the upload-size exception response creation and response
status to use the newer HTTP 413 enum
- Updated related unit tests to assert `HttpStatus.CONTENT_TOO_LARGE`
- The change was made to avoid using the deprecated Spring HTTP status
enum while keeping the returned status code behavior unchanged


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-05-11 10:38:19 +01:00