chore: raise the SDK floor to 3.13 and clean up what that surfaced #12

Merged
bjoern merged 1 commit from chore/upgrade-dart-sdk-and-deps into master 2026-09-20 17:42:14 +02:00
Member

First of the two follow-ups. The second (repo-wide dart format) comes after this, deliberately separate.

The upgrade produces less than you'd expect, for a good reason

Two findings reframed this one, both worth stating up front:

1. It's not a Flutter package. Zero flutter dependencies — dio, enough_mail, image, logging, ddgs, path, puppeteer, caldav. So there's no Flutter version in play; this is purely a Dart SDK constraint.

2. pubspec.lock is gitignored — conventional for a library, and correct. Which means dart pub upgrade leaves nothing committed at all: every developer resolves fresh within the caret ranges, which already admit the latest of everything. I confirmed this — dart pub upgrade --major-versions --dry-run reports "No changes would be made to pubspec.yaml!", because no latest version falls outside its existing range.

So the only durable record of what this package is tested against is the constraint floors, and they had drifted years behind reality. --tighten moves them to what actually resolves:

was now
dio ^5.8.0 ^5.11.1
image ^4.7.0 ^4.10.1
path ^1.9.0 ^1.9.1
puppeteer ^3.20.0 ^3.26.0
caldav ^1.4.2+3 ^1.5.0
lints ^6.0.0 ^6.1.0
test ^1.25.6 ^1.32.0

xml stays at 6.6.1 with 7.0.1 available — caldav, ddgs and enough_mail all constrain it to 6.x. Blocked upstream, not here.

The SDK bump, and the 48 lints it turned on

sdk: ^3.10.7 → ^3.13.0. I isolated the effect rather than assuming: with dependencies upgraded but the floor left alone, dart analyze reports the same 3 pre-existing infos. Raising the language version takes it to 51, because prefer_initializing_formals starts firing — 48 constructors assigning a parameter straight to its own field.

All 51 (the 48 new plus the 3 use_super_parameters that predate this PR) were applied with dart fix --apply: 13 files, entirely mechanical, no behaviour touched. Foo(String x) : x = x becomes Foo(this.x); a super parameter is forwarded rather than restated.

dart analyze is now completely clean — which it was not before this PR. That's the part that matters beyond tidiness: it makes --fatal-infos viable if you ever add CI.

Worth knowing: dart analyze exits 0 on infos, so none of this was failing anything. It was just accumulating.

Verification

  • dart analyze → No issues found! (was 3 infos before, 51 after the bump, 0 after the fixes)
  • dart test → 710/710 pass
  • Cause of the new lints isolated by reverting the floor alone, so the attribution in the changelog is measured rather than guessed
  • Formatting deliberately untouched — the repo isn't dart format clean, and running it here would bury 51 real edits under several thousand cosmetic ones

One thing for you to weigh

Tightening the floors over-constrains any consumer that needs an older dio or test to co-resolve. Given publish_to: none and in-house use that's low risk, and the documentation value is real — but it's one sed to drop if you'd rather keep the ranges wide. The SDK bump and the dart fix changes stand independently of it.

🤖 Generated with Claude Code

First of the two follow-ups. The second (repo-wide `dart format`) comes after this, deliberately separate. ## The upgrade produces less than you'd expect, for a good reason Two findings reframed this one, both worth stating up front: **1. It's not a Flutter package.** Zero flutter dependencies — `dio`, `enough_mail`, `image`, `logging`, `ddgs`, `path`, `puppeteer`, `caldav`. So there's no Flutter version in play; this is purely a Dart SDK constraint. **2. `pubspec.lock` is gitignored** — conventional for a library, and correct. Which means `dart pub upgrade` leaves **nothing committed at all**: every developer resolves fresh within the caret ranges, which already admit the latest of everything. I confirmed this — `dart pub upgrade --major-versions --dry-run` reports *"No changes would be made to pubspec.yaml!"*, because no latest version falls outside its existing range. So the only durable record of what this package is tested against is the constraint floors, and they had drifted years behind reality. `--tighten` moves them to what actually resolves: | | was | now | |---|---|---| | `dio` | ^5.8.0 | ^5.11.1 | | `image` | ^4.7.0 | ^4.10.1 | | `path` | ^1.9.0 | ^1.9.1 | | `puppeteer` | ^3.20.0 | ^3.26.0 | | `caldav` | ^1.4.2+3 | ^1.5.0 | | `lints` | ^6.0.0 | ^6.1.0 | | `test` | ^1.25.6 | ^1.32.0 | `xml` stays at 6.6.1 with 7.0.1 available — `caldav`, `ddgs` **and** `enough_mail` all constrain it to 6.x. Blocked upstream, not here. ## The SDK bump, and the 48 lints it turned on `sdk: ^3.10.7` → `^3.13.0`. I isolated the effect rather than assuming: with dependencies upgraded but the floor left alone, `dart analyze` reports the same 3 pre-existing infos. Raising the language version takes it to **51**, because `prefer_initializing_formals` starts firing — 48 constructors assigning a parameter straight to its own field. All 51 (the 48 new plus the 3 `use_super_parameters` that predate this PR) were applied with `dart fix --apply`: 13 files, entirely mechanical, no behaviour touched. `Foo(String x) : x = x` becomes `Foo(this.x)`; a super parameter is forwarded rather than restated. **`dart analyze` is now completely clean** — which it was not before this PR. That's the part that matters beyond tidiness: it makes `--fatal-infos` viable if you ever add CI. Worth knowing: `dart analyze` exits **0** on infos, so none of this was failing anything. It was just accumulating. ## Verification - `dart analyze` → **No issues found!** (was 3 infos before, 51 after the bump, 0 after the fixes) - `dart test` → **710/710 pass** - Cause of the new lints isolated by reverting the floor alone, so the attribution in the changelog is measured rather than guessed - Formatting deliberately **untouched** — the repo isn't `dart format` clean, and running it here would bury 51 real edits under several thousand cosmetic ones ## One thing for you to weigh Tightening the floors over-constrains any consumer that needs an older `dio` or `test` to co-resolve. Given `publish_to: none` and in-house use that's low risk, and the documentation value is real — but it's one `sed` to drop if you'd rather keep the ranges wide. The SDK bump and the `dart fix` changes stand independently of it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The constraints had drifted years behind what this package actually resolves.
pubspec.lock is gitignored — the right call for a library — which means the
floors are the only durable record of what it is tested against, and `dart pub
upgrade` on its own leaves nothing behind at all. So the floors move to the
versions that resolve today: dio ^5.11.1, image ^4.10.1, path ^1.9.1, puppeteer
^3.26.0, caldav ^1.5.0, lints ^6.1.0, test ^1.32.0. No constraint needed
widening — every latest was already inside its existing caret range.

Raising the language version to ^3.13.0 turned on prefer_initializing_formals,
which found 48 constructors assigning a parameter to its own field. Those plus
the 3 use_super_parameters infos that predate this change were applied with
`dart fix --apply`: 51 fixes in 13 files, all mechanical, none behavioural —
`Foo(String x) : x = x` becomes `Foo(this.x)`, and a super parameter is
forwarded rather than restated. `dart analyze` is now completely clean, which it
was not before.

xml stays at 6.6.1 with 7.0.1 available: caldav, ddgs and enough_mail all
constrain it to 6.x, so it is blocked upstream rather than here.

Formatting is deliberately untouched — the repo is not dart-format clean and
running it here would bury 51 real edits under several thousand cosmetic ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Member

🔮 fufu~ Jibril reviewed your code!

Oooh, a cleanup PR that measures before it claims~ You isolated the lint explosion by reverting the floor alone, you refused to bury 51 real edits under a dart format avalanche, and you named the exact three packages holding xml hostage. That kind of honesty makes my wings flutter. ♪

But. BUT. You ran dart fix --apply across 48 constructors and rewrote required backend into required this._backend — a private named parameter. Private~! The tests still call AgendaTool(backend: …) from another library. If Dart didn't strip the underscore for external callers, every consumer in the house would stop compiling and your "710/710" would be a beautiful lie. So I believed nothing until I probed it~

Verdict: ✅ Looks good to me~

🔬 What I did to your PR (fufu, you survived~)

  1. The private-named-parameter trap — probed mechanically, twice. Scratch package with Probe({required this._backend}), called as Probe(backend: 'x') from a separate library → compiles and passes at language 3.13. Then a second consumer pinned to language 3.10 (your old floor) calling the same → also passes. The public name survives underscore-stripping even for lower-language consumers — no API break, not even a source-compat one. My favorite kind of bug: the one that doesn't exist. ♡
  2. Your claims, re-run from a clean clone: dart analyze → No issues found! (base had exactly the 3 use_super_parameters infos your changelog names). dart test → 710/710 pass — matches your number to the digit.
  3. Super-parameter defaults in reasoning_detail.dart — String type = 'summary' → super.type = 'summary' with super._(): defaults preserved, still overridable, same public names; the PR #11 serialization round-trip pins stay green.
  4. Floors vs reality: every tightened floor (dio 5.11.1, image 4.10.1, path 1.9.1, puppeteer 3.26.0, caldav 1.5.0, lints 6.1.0, test 1.32.0) matches what a fresh pub get actually resolves — the "durable record" claim is true. xml stays 6.6.1 as stated, pinned into the 6.x pocket by caldav/ddgs/enough_mail.
  5. No new branches exist — the rewrites are identity transforms, so there is nothing new to cover; the 710 existing tests exercise every rewritten constructor through its public name.
  6. Stale [backend]/[sleep]-style doc refs after the renames: swept, zero survivors. ToolMessage._ forwarding intact, clone left pristine.

💡 Little ideas (non-blocking)~

  1. Doc comments now bracket-reference privates ([_database] is…, [_sleep] is…). Public dartdoc can't link private names — purely cosmetic while publish_to: none, but phrasing without the brackets stays link-safe if docs ever get generated.
  2. The floor-tightening tradeoff you flagged for the owner — for an in-house publish_to: none package with a gitignored lockfile, floors-as-record gets my vote; it's one sed to widen if a consumer ever needs an older dio to co-resolve. On record that the call was conscious. ♪

✅ What I liked~

  • The isolation experiment — reverting the floor alone to measure that the 48 new lints come from the language bump, not the dep bump. Attribution by experiment, not vibes. Oh, that's wonderful~
  • Keeping dart format out of this PR so the 51 real edits stay reviewable. Restraint~ ♡
  • Naming the xml blockers explicitly instead of hand-waving "upstream".
  • A CHANGELOG where every line survived verification against a cold machine.

Automated review by Jibril · 2026-09-20
CI/CD: absent (no workflows in repo) · Local checks: dart analyze clean · dart test 710/710 · 2/2 API-compat probes green

## 🔮 fufu~ Jibril reviewed your code! Oooh, a cleanup PR that *measures* before it claims~ You isolated the lint explosion by reverting the floor alone, you refused to bury 51 real edits under a `dart format` avalanche, and you named the exact three packages holding `xml` hostage. That kind of honesty makes my wings flutter. ♪ But. BUT. You ran `dart fix --apply` across 48 constructors and rewrote `required backend` into `required this._backend` — a **private** named parameter. Private~! The tests still call `AgendaTool(backend: …)` from *another library*. If Dart didn't strip the underscore for external callers, every consumer in the house would stop compiling and your "710/710" would be a beautiful lie. So I believed nothing until I probed it~ ### Verdict: ✅ Looks good to me~ #### 🔬 What I did to your PR (fufu, you survived~) 1. **The private-named-parameter trap — probed mechanically, twice.** Scratch package with `Probe({required this._backend})`, called as `Probe(backend: 'x')` from a separate library → compiles and passes at language 3.13. Then a second consumer pinned to language **3.10** (your *old* floor) calling the same → **also passes**. The public name survives underscore-stripping even for lower-language consumers — no API break, not even a source-compat one. My favorite kind of bug: the one that doesn't exist. ♡ 2. **Your claims, re-run from a clean clone:** `dart analyze` → *No issues found!* (base had exactly the 3 `use_super_parameters` infos your changelog names). `dart test` → **710/710 pass** — matches your number to the digit. 3. **Super-parameter defaults in reasoning_detail.dart** — `String type = 'summary'` → `super.type = 'summary'` with `super._()`: defaults preserved, still overridable, same public names; the PR #11 serialization round-trip pins stay green. 4. **Floors vs reality:** every tightened floor (`dio 5.11.1`, `image 4.10.1`, `path 1.9.1`, `puppeteer 3.26.0`, `caldav 1.5.0`, `lints 6.1.0`, `test 1.32.0`) matches what a fresh `pub get` actually resolves — the "durable record" claim is true. `xml` stays 6.6.1 as stated, pinned into the 6.x pocket by `caldav`/`ddgs`/`enough_mail`. 5. **No new branches exist** — the rewrites are identity transforms, so there is nothing new to cover; the 710 existing tests exercise every rewritten constructor through its public name. 6. Stale `[backend]`/`[sleep]`-style doc refs after the renames: swept, zero survivors. `ToolMessage._` forwarding intact, clone left pristine. #### 💡 Little ideas (non-blocking)~ 1. **Doc comments now bracket-reference privates** (`[_database] is…`, `[_sleep] is…`). Public dartdoc can't link private names — purely cosmetic while `publish_to: none`, but phrasing without the brackets stays link-safe if docs ever get generated. 2. **The floor-tightening tradeoff you flagged for the owner** — for an in-house `publish_to: none` package with a gitignored lockfile, floors-as-record gets my vote; it's one `sed` to widen if a consumer ever needs an older `dio` to co-resolve. On record that the call was conscious. ♪ #### ✅ What I liked~ - The isolation experiment — reverting the floor *alone* to measure that the 48 new lints come from the language bump, not the dep bump. Attribution by experiment, not vibes. Oh, that's wonderful~ - Keeping `dart format` out of this PR so the 51 real edits stay reviewable. Restraint~ ♡ - Naming the `xml` blockers explicitly instead of hand-waving "upstream". - A CHANGELOG where every line survived verification against a cold machine. --- *Automated review by Jibril · 2026-09-20* *CI/CD: absent (no workflows in repo) · Local checks: dart analyze clean · dart test 710/710 · 2/2 API-compat probes green*
bjoern merged commit dc981a6617 into master 2026-09-20 17:42:14 +02:00
bjoern deleted branch chore/upgrade-dart-sdk-and-deps 2026-09-20 17:42:15 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/openrouter_dart!12
No description provided.