{"owner":"cfug","repo":"dio","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# Agent Contribution Guidelines\n\nLanguage: English | [简体中文](AGENTS-ZH.md)\n\nThis document defines the rules for AI agents (and the humans operating them)\nworking on this repository — whether you are contributing a pull request or\nassisting a maintainer locally. It supplements, and never overrides,\n[CONTRIBUTING.md](CONTRIBUTING.md) and the\n[Compatibility Policy](COMPATIBILITY_POLICY.md).\n\ndio is one of the most depended-on packages in the Dart/Flutter ecosystem.\nA single careless change can break tens of thousands of downstream projects.\nContributions here are not a playground: every change must be motivated,\ntested, and compatible.\n\n## 1. Motivation first — no speculative changes\n\n**Do not invent work.** A change is only acceptable when it solves a problem\nthat actually exists.\n\n- Every non-trivial change must be traceable to a concrete motivation:\n  a reproducible bug, an accepted issue/discussion, an RFC-style proposal,\n  or an explicit maintainer request. \"This seems useful\" is not a motivation.\n- Before implementing a feature, answer these questions in the issue or the\n  PR description — if you cannot, do not open the PR:\n  1. What cannot be done (or is done poorly) with the current dio?\n  2. Who needs this, and in which real-world scenario?\n  3. Why does it belong in dio itself, instead of an interceptor, an adapter,\n     a transformer, or a separate package? dio is intentionally extensible;\n     most needs are served by its extension points without core changes.\n  4. What is the cost — API surface, maintenance burden, compatibility risk?\n- One PR, one concern. Do not bundle several unrelated features or fixes\n  into a single PR. Bundled \"improvement packs\" might be closed unreviewed.\n- For any user-facing feature, open an issue for discussion **before**\n  writing code, unless a maintainer has already asked for it. A bare\n  `Closes #NNNN` is not the same as prior discussion: the referenced issue\n  must show that maintainers have expressed interest or accepted the\n  direction. Feature PRs without that grounding waste both your tokens and\n  the maintainers' time, and might be closed.\n\n## 2. Tests are mandatory for logic changes\n\nEvery behavioral change must be proven by tests.\n\n- Any change to logic requires new tests or adjustments to existing tests\n  that fail without the change and pass with it. Bug fixes must include a\n  regression test that reproduces the original report.\n- CI reports coverage diffs on every PR. The published minimum threshold is\n  low, but that is a floor, not a target: coverage of code you changed\n  should not regress, and new logic (including error paths) should be\n  covered by real assertions.\n- Tests must be **effective and non-duplicated**:\n  - Assert observable behavior, not implementation details.\n  - Do not add tests that merely re-execute existing covered paths to\n    inflate coverage numbers.\n  - Search the existing suites first — extend an existing test group\n    instead of creating a near-duplicate file.\n- Put tests in the right place:\n  - Package-specific behavior → `<package>/test/`.\n  - Behavior that must hold across all adapters/platforms → the shared\n    `dio_test` package.\n- Run the checks locally before claiming they pass:\n\n  ```bash\n  melos run format   # or format:fix\n  melos run analyze\n  melos run test     # or targeted: test:vm / test:web / test:flutter\n  ```\n\n- Never state that tests pass without having run them. Never check a PR\n  checklist item you have not actually done. Misreporting verification\n  status may lead to the PR being closed.\n\n## 3. Compatibility is sacred — avoid breaking changes\n\ndio's public API is a contract with an enormous downstream. Treat every\npublic symbol as frozen unless a maintainer decides otherwise.\n\n- **Default to non-breaking.** Prefer additive changes: new optional named\n  parameters with safe defaults, new classes, new extension points.\n- Do not change public method signatures, remove/rename public symbols,\n  change default behavior, or alter thrown exception types without going\n  through a deprecation cycle. Breaking changes belong in major releases.\n  As dio's own [CHANGELOG](dio/CHANGELOG.md) preamble states, unavoidable\n  breaking changes may occasionally ship in minor releases — those still\n  require maintainer sign-off in advance and an entry in the\n  [Migration Guide](dio/doc/migration_guide.md).\n- If an API must go away, deprecate first and keep it working:\n\n  ```dart\n  @Deprecated('Use XXX instead. This will be removed in X.0.0')\n  ```\n\n  Deprecations must state their replacement and the removal version, and\n  are only removed in the next major release, together with an entry in\n  the Migration Guide. Target the *next* major, not a version beyond that.\n- Do not raise the minimum Dart/Flutter SDK constraint of any package\n  unless required by the [Compatibility Policy](COMPATIBILITY_POLICY.md)\n  or its listed exceptions. CI tests against the minimum supported SDK;\n  do not use language/library features beyond a package's lower bound.\n- Watch for **behavioral** breaking changes too: changing defaults, header\n  normalization, redirect/error semantics, or timing/ordering of\n  interceptors can break downstream even when signatures are untouched.\n- If a breaking change is genuinely unavoidable, stop and raise it in an\n  issue for maintainers to decide. Do not merge-request it unilaterally.\n\n### Extra scrutiny in security- and network-critical areas\n\nSome parts of dio have oversized blast radius when broken. Changes here\nrequire extra care, and the PR description should explicitly call the\nchange out and @-mention a maintainer:\n\n- SSL / TLS handling and certificate pinning (`badCertificateCallback`,\n  `SecurityContext`, adapters' `HttpClient` configuration).\n- Redirect handling and cross-origin behavior (redirect policy, header\n  forwarding, cookie leakage across redirects).\n- Cookie management (`dio_cookie_manager`, domain / path matching).\n- Header handling (`Authorization`, `Content-Type`, casing, duplicates).\n- Timeout, cancellation, and connection pooling.\n- The interceptor pipeline (ordering, error propagation, `next` /\n  `resolve` / `reject` semantics).\n- Request-body encoding: `FormData`, multipart streaming, encoding\n  detection.\n\nRule of thumb: if getting this wrong could leak credentials, hang a\nrequest forever, or change data on the wire, treat it as sensitive.\n\n### Test certificates and keys\n\nSelf-signed certificates and their private keys used only for local\ntest fixtures (TLS, ALPN, pinning, etc.) are **not real secrets** — but\ncommitting static `.key`/`.crt` files still has costs: secret-scanner\nnoise, package-size bloat for published artifacts, and inconsistency\nwith this repo's convention of generating such fixtures at test time\n(see `scripts/prepare_pinning_certs.sh`).\n\n- **Prefer generating certificates at test setup** (via `openssl` in\n  a `setUp`/helper, or a setup script) over committing static files.\n- **If a static fixture is unavoidable**, exclude it from the published\n  package with both:\n  - `false_secrets` in the package's `pubspec.yaml` (suppresses pub's\n    leak-detection warning), and\n  - a `.pubignore` **inside the fixture subdirectory** (e.g.\n    `test/certificates/.pubignore`), never at the package root — a\n    root-level `.pubignore` overrides the root `.gitignore` for the\n    entire directory, silently re-including build artifacts and other\n    git-ignored files in the published package.\n\n### Dependency changes\n\nDo not bundle drive-by dependency bumps into a feature/fix PR. When a\ndependency change is itself the point of the PR:\n\n- State the reason in the description (security fix, required for a new\n  feature, upstream deprecation, etc.). \"Latest is greater\" is not a\n  reason.\n- Verify the change under every supported SDK version declared in the\n  affected `pubspec.yaml`. Do not raise the package's SDK lower bound\n  just to accommodate the new dependency unless the\n  [Compatibility Policy](COMPATIBILITY_POLICY.md) allows it.\n- Prefer the narrowest constraint that solves the problem (patch >\n  minor > major bump).\n- Call out any new transitive dependencies — downstream users care about\n  their lockfile.\n- Use `⬆️ chore` (or `chore(deps)`) as the commit type.\n\n## 4. Understand before you change\n\n- Read the surrounding code and existing patterns before editing. Match\n  the existing style, naming, and module boundaries.\n- Fix root causes, not symptoms. When a symptom is reported, locate the\n  actual defect before patching.\n- Never guess an API — neither dio's internals nor third-party packages.\n  Read the actual source and the package's own tests/examples when\n  unsure. If `dart analyze` says a member does not exist, go back to the\n  source instead of retrying variations. Dependency source locations:\n\n  | Platform | Default location |\n  |---|---|\n  | macOS / Linux | `~/.pub-cache/hosted/pub.dev/<package>-<version>/` |\n  | Windows | `%LOCALAPPDATA%\\Pub\\Cache\\hosted\\pub.dev\\<package>-<version>\\` |\n\n  If the `PUB_CACHE` environment variable is set, use that location\n  instead of the platform default.\n- **Verify every external fact before writing it down.** Agents\n  routinely hallucinate numbers and attach wrong labels to them — RFC\n  numbers, issue/PR numbers, library/API version numbers, CVE\n  identifiers, deprecation timelines, benchmark figures, attributed\n  quotes, platform-behavior claims (\"iOS X.Y and later…\"). A wrong\n  citation in a commit message, changelog, or doc comment is worse\n  than no citation, because it misleads downstream readers and\n  reviewers who trust it. Before writing any external fact:\n  1. Look up the source and confirm it says what you claim. For RFCs,\n     check `https://www.rfc-editor.org/rfc/rfcNNNN` (or\n     `https://datatracker.ietf.org/doc/rfcNNNN/`) and confirm the\n     title matches; for issues/PRs, open the link; for library\n     versions, read the package's own changelog/source.\n  2. Confirm any section anchor, version number, or quoted text you\n     cite actually exists at that source.\n  3. If you cannot verify the fact online, drop the citation and\n     describe the observed behavior in your own words instead. Do not\n     guess a number to make a statement look authoritative.\n  This applies to commit messages, `CHANGELOG.md`, doc comments,\n  README, and any prose in a PR description.\n\n## 5. Production quality only\n\n- No placeholder work: no `TODO`/`FIXME` left behind, no mocked or\n  simplified logic presented as complete, no \"will optimize later\" code.\n- Handle edge cases and error paths explicitly; never swallow errors\n  silently.\n- If you cannot finish something completely, say so explicitly and state\n  the boundary — do not pretend it is done.\n\n## 6. When to stop and ask\n\nAgents default to \"guess and proceed\". Do not. Pause and check with the\noperator (or open a discussion issue) when:\n\n- The task description is ambiguous and multiple reasonable interpretations\n  would produce materially different implementations.\n- Fixing the reported problem would require design changes that go beyond\n  what was asked for.\n- The right fix touches an area not obviously in scope (e.g., renaming a\n  public API to fix an unrelated bug, or restructuring an interceptor\n  pipeline to enable a small feature).\n- You cannot reproduce the reported issue after a reasonable attempt.\n- The request itself seems wrong (e.g., the \"bug\" is intended behavior, or\n  the \"feature\" would violate a rule in this document).\n\nDo **not** stop to ask permission for routine mechanical steps: running\ntests / format / analyze, staging files, opening a draft PR, or choices\nthat are already decided by this document (commit format, changelog,\nattribution).\n\n## 7. Repository layout\n\nThis is a [Melos](https://github.com/invertase/melos/tree/main/docs)\nmono-repo:\n\n| Path | Package |\n|---|---|\n| `dio/` | The core package |\n| `plugins/web_adapter/` | `dio_web_adapter` |\n| `plugins/cookie_manager/` | `dio_cookie_manager` |\n| `plugins/http2_adapter/` | `dio_http2_adapter` |\n| `plugins/native_dio_adapter/` | `native_dio_adapter` |\n| `plugins/compatibility_layer/` | `dio_compatibility_layer` |\n| `dio_test/` | Shared test suites for all adapters |\n| `example_dart/`, `example_flutter_app/` | Examples |\n\nSetup:\n\n```bash\ndart pub global activate melos\nmelos bootstrap\n```\n\nEach package versions and releases independently. Note that packages have\n**different SDK lower bounds** (see each `pubspec.yaml`).\n\n## 8. Commits, changelog, and PR hygiene\n\n### 8.1 Branch naming\n\nWork on a feature branch named `category/ticket-id-or-short-description`:\n\n- `category` matches the Conventional type used in the commit:\n  `feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `chore`, `ci`,\n  `style`.\n- Use the tracked **ticket id** when one exists — the issue or PR\n  number: `fix/2201`, `feat/2555`. Combining both is fine when it aids\n  discoverability: `fix/2201-cookie-domain-match`.\n- Otherwise use a **short description** — 2–5 kebab-case words that\n  describe the change (`docs/agents-guidelines`,\n  `feat/cors-preflight-warning`, `chore/bump-http2-3.0.0`).\n\nRules:\n\n- Never work on `main` directly.\n- One branch per PR; do not reuse a merged branch for a new change.\n- Keep branch names ASCII, lowercase, and short.\n\n### 8.2 Commit message format — Gitmoji or Conventional\n\nEvery commit uses **[gitmoji](https://gitmoji.dev)** at the front or a\n**[Conventional Commits](https://www.conventionalcommits.org)** type\nprefix. Emojis are chosen from the gitmoji specification — do not invent\nnew ones.\n\n```\n<gitmoji> <Short imperative subject>\n(or)\n<type>[(<scope>)]: <short imperative subject>\n\n[optional body — wrap at ~72 chars]\n\n[optional footer, e.g. Closes #1234]\n```\n\nGitmoji commonly used in this repository (see `git log` for the full set).\n**Pick one column — never both.** Each row maps a gitmoji to its\nequivalent Conventional-type prefix; you use the emoji **or** the type,\nnot the two glued together. `🔧 chore: ...` is wrong.\n\n| Gitmoji | Conventional type | Use for |\n|---|---|---|\n| ✨ `:sparkles:` | `feat` | New user-facing feature |\n| 🐛 `:bug:` | `fix` | Bug fix |\n| ⚡️ `:zap:` | `perf` | Performance improvement |\n| ♻️ `:recycle:` | `refactor` | Refactor with no behavior change |\n| 📝 `:memo:` | `docs` | Documentation |\n| ✅ `:white_check_mark:` | `test` | Tests only |\n| 🚨 `:rotating_light:` | `fix` / `style` | Fix linter or analyzer warnings |\n| 🥅 `:goal_net:` | `fix` / `refactor` | Catch errors / improve error handling |\n| 🔧 `:wrench:` | `chore` | Config / tooling |\n| 👷 `:construction_worker:` | `ci` | CI / workflow changes |\n| 💚 `:green_heart:` | `ci` | Fix a failing CI job |\n| ⬆️ `:arrow_up:` | `chore` | Bump a dependency |\n| 🔥 `:fire:` | `chore` / `refactor` | Remove code or files |\n| 🎨 `:art:` | `style` | Formatting / structure only |\n| 🔖 `:bookmark:` | `chore(release)` | Release (**maintainers only**) |\n\nRules:\n\n- Subject is an imperative English sentence. Do not append the PR number —\n  GitHub adds `(#N)` automatically on squash-merge.\n- Use scope when it clarifies (`fix(dio_web_adapter): ...`); omit when it\n  would just repeat the file path.\n- Position 0 is either the emoji or the Conventional prefix plus colon, then a space, then the subject.\n- After a gitmoji the subject starts with a **capital letter**\n  (`🐛 Allow ...`, `📝 Clarify ...`); after a Conventional prefix the\n  subject stays lowercase (`docs: add ...`, `perf(dio): reduce ...`).\n\nExamples (adapted from actual repo history):\n\n```\n🐛 Allow `callFollowingErrorInterceptor` when rejecting in `ErrorInterceptorHandler`\nperf(dio): reduce `FormData.readAsBytes` memory usage for large payloads\ndocs: add agent contribution guidelines\n```\n\nDo **not** combine the two styles:\n\n```\n❌ 🔧 chore: group codeql-action updates      (both gitmoji AND prefix)\n✅ 🔧 Group codeql-action updates              (gitmoji only, capitalized subject)\n✅ chore: group codeql-action updates          (Conventional only, lowercase subject)\n```\n\n### 8.3 AI attribution — mandatory\n\nTransparency about AI involvement is required. Do not hide it, and do not\nskip it \"to keep the commit clean\".\n\n- Add a `Co-Authored-By:` trailer for **every AI agent** that produced\n  code, tests, or docs in the commit:\n\n  ```\n  Co-Authored-By: Claude <noreply@anthropic.com>\n  Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>\n  ```\n\n  Use the identity the agent itself publishes (see its own docs / recent\n  commits from that agent on GitHub). Multiple agents → multiple trailers.\n- Also disclose in the PR description **which agent(s) were used and for\n  what stage** — design, implementation, tests, or review. One line is\n  enough, e.g.:\n\n  > *Implementation and tests by Devin; local review pass by GLM-5.2.*\n\n- AI attribution never shifts accountability. The human submitting the PR\n  owns every line, must understand it, and must respond to review feedback\n  substantively. \"The AI wrote it\" is not an answer to a review question.\n\n### 8.4 CHANGELOG and docs\n\n- Update the `CHANGELOG.md` of **every package you changed**, under\n  `## Unreleased` (replace `*None.*`).\n- One concise bullet per change, written for downstream users, not for\n  reviewers.\n- Do not bump version numbers — releases are handled by maintainers.\n- When public APIs change, also update `README.md`, `README-ZH.md`, API\n  doc comments, and any affected examples.\n\n### 8.5 Self-review your diff before every commit\n\nAlways inspect what you are about to commit:\n\n```bash\ngit diff                          # unstaged\ngit diff --staged                 # staged\ngit diff <base-branch>...HEAD     # full branch diff before opening/updating a PR\n```\n\nRemove before committing:\n\n- Debug output (`print`, `debugPrint`, `console.log`, temporary logs).\n- Commented-out code left from earlier attempts.\n- Reformatting or import re-ordering of files that are not the subject\n  of this change.\n- Unrelated bumps in `pubspec.yaml` / `pubspec.lock`.\n- Whitespace-only changes in unrelated files.\n- Editor/OS junk (`.DS_Store`, `.idea/`, personal scratch files).\n\nIf you cannot explain why a hunk is in the diff, it does not belong in\nthe commit. Never use `git add .` or `git add -A` — stage files by path.\n\n**Also re-read the commit message against the staged diff.** A message\ncarried over from a previous attempt, or auto-completed from an\nunrelated commit, is easy to miss and lands verbatim in history. If the\nmessage and the diff describe different work, one of them is wrong.\n\n### 8.6 Opening the PR\n\n- **Open as a draft PR** (`Create draft pull request`) when the change\n  is large, exploratory, or when you want maintainer direction before\n  polishing. Convert to Ready for Review once local checks pass and the\n  description is complete.\n- Reference the closing issue with `Closes #NNNN` in the description.\n- Follow the AI attribution rules in §8.3: disclose which agent(s)\n  contributed and at which stage.\n- Write PR titles and bodies in English, in the same commit style as\n  §8.2.\n- Only tick a PR checklist item that is genuinely done. For items that\n  do not apply, keep the box unchecked and add *(not applicable —\n  reason)* next to it. Do not check \"done\" as a shortcut.\n- **Describe verification honestly — no boilerplate \"Test plan\"\n  checklist.** In prose, state what you actually confirmed and how, in\n  one or two sentences:\n\n  > *Added 15 unit tests covering method / content-type / custom-header\n  > combinations; `melos run test:vm` and `melos run analyze` clean.*\n\n  Do **not** paste a generic checklist — this is the anti-pattern this\n  section is explicitly rejecting, even if your agent tooling suggests\n  one by default:\n\n  ```\n  ❌  ## Test plan\n      - [ ] Tests pass\n      - [ ] Feature works as expected\n  ```\n\n  Mechanical prerequisites (`dart analyze`, `dart format`) are already\n  covered by the PR template's top-level checklist — do not re-list them\n  as \"tests\". Behavioral verification means checks that would fail if\n  this change regressed.\n\n  If something that ought to be verified genuinely could not be — needs\n  browser CI, a physical device, production load, and so on — list it\n  under a short **Unverified** paragraph explaining why. Unverified\n  items are known risks; this should stay rare, not become routine.\n\n### 8.7 Review iteration workflow\n\nAfter opening the PR:\n\n- **Address feedback with new commits appended to the branch**, not by\n  squash-and-force-push. Maintainers rely on incremental history during\n  review; squashing happens at merge time.\n- **Avoid `git push --force` on a branch that already has review\n  comments** — it detaches those comments from their code position. If a\n  rebase is genuinely required (e.g., conflict resolution against\n  `main`), leave a comment before pushing so reviewers know.\n- **Do not close and reopen the PR** to reset review state, retry CI, or\n  bypass a blocking review. Push a fix instead.\n- **Design-level feedback is a conversation, not an instruction.** If a\n  reviewer's suggestion changes the intent of the PR (not just its\n  implementation), reply first and reach agreement before writing new\n  code. Blindly applying a large suggestion is worse than discussing it.\n- **Mark review threads resolved** only after you have addressed the\n  point in code and left a reply explaining what changed — or after the\n  reviewer explicitly says so. Do not silently resolve.\n- **CI failures**: read the failing job's log, find the root cause, then\n  push a fix. Never re-run CI hoping for a green run. If a test is\n  genuinely flaky, say so in a comment — do not paper over it by\n  disabling the test or adding retries.\n\n## 9. Patterns that may lead to closure\n\nQuick cross-reference — each pattern is a violation of the rules above.\nPRs matching one or more of these may be closed without detailed review\nat the maintainers' discretion.\n\n| Pattern | See |\n|---|---|\n| No motivation or prior maintainer discussion | §1 |\n| Multiple unrelated changes bundled in one PR | §1 |\n| Logic changes without effective, non-duplicated tests | §2 |\n| Public-API break without maintainer sign-off | §3 |\n| Sensitive-area change without maintainer notice | §3 |\n| Drive-by dependency bump in a feature/fix PR | §3 |\n| Guessed / hallucinated API usage | §4 |\n| Unverified or wrong external factual reference | §4 |\n| Drive-by refactors, formatting sweeps, unrelated `.gitignore` / CI edits | §4, §8.5 |\n| Placeholder work (`TODO`/`FIXME`, mocked or simplified logic presented as complete) | §5 |\n| Branch name not following `category/ticket-id-or-short-description` | §8.1 |\n| Non-standard commit message format (missing gitmoji, wrong type, non-English) | §8.2 |\n| Missing or hidden AI attribution | §8.3 |\n| Debug output or commented-out code left in the diff | §8.5 |\n| Falsely checked PR checklist items | §8.6 |\n| Force-pushing or close/reopen to reset review state | §8.7 |\n"},"files":{"AGENTS.md":"# Agent Contribution Guidelines\n\nLanguage: English | [简体中文](AGENTS-ZH.md)\n\nThis document defines the rules for AI agents (and the humans operating them)\nworking on this repository — whether you are contributing a pull request or\nassisting a maintainer locally. It supplements, and never overrides,\n[CONTRIBUTING.md](CONTRIBUTING.md) and the\n[Compatibility Policy](COMPATIBILITY_POLICY.md).\n\ndio is one of the most depended-on packages in the Dart/Flutter ecosystem.\nA single careless change can break tens of thousands of downstream projects.\nContributions here are not a playground: every change must be motivated,\ntested, and compatible.\n\n## 1. Motivation first — no speculative changes\n\n**Do not invent work.** A change is only acceptable when it solves a problem\nthat actually exists.\n\n- Every non-trivial change must be traceable to a concrete motivation:\n  a reproducible bug, an accepted issue/discussion, an RFC-style proposal,\n  or an explicit maintainer request. \"This seems useful\" is not a motivation.\n- Before implementing a feature, answer these questions in the issue or the\n  PR description — if you cannot, do not open the PR:\n  1. What cannot be done (or is done poorly) with the current dio?\n  2. Who needs this, and in which real-world scenario?\n  3. Why does it belong in dio itself, instead of an interceptor, an adapter,\n     a transformer, or a separate package? dio is intentionally extensible;\n     most needs are served by its extension points without core changes.\n  4. What is the cost — API surface, maintenance burden, compatibility risk?\n- One PR, one concern. Do not bundle several unrelated features or fixes\n  into a single PR. Bundled \"improvement packs\" might be closed unreviewed.\n- For any user-facing feature, open an issue for discussion **before**\n  writing code, unless a maintainer has already asked for it. A bare\n  `Closes #NNNN` is not the same as prior discussion: the referenced issue\n  must show that maintainers have expressed interest or accepted the\n  direction. Feature PRs without that grounding waste both your tokens and\n  the maintainers' time, and might be closed.\n\n## 2. Tests are mandatory for logic changes\n\nEvery behavioral change must be proven by tests.\n\n- Any change to logic requires new tests or adjustments to existing tests\n  that fail without the change and pass with it. Bug fixes must include a\n  regression test that reproduces the original report.\n- CI reports coverage diffs on every PR. The published minimum threshold is\n  low, but that is a floor, not a target: coverage of code you changed\n  should not regress, and new logic (including error paths) should be\n  covered by real assertions.\n- Tests must be **effective and non-duplicated**:\n  - Assert observable behavior, not implementation details.\n  - Do not add tests that merely re-execute existing covered paths to\n    inflate coverage numbers.\n  - Search the existing suites first — extend an existing test group\n    instead of creating a near-duplicate file.\n- Put tests in the right place:\n  - Package-specific behavior → `<package>/test/`.\n  - Behavior that must hold across all adapters/platforms → the shared\n    `dio_test` package.\n- Run the checks locally before claiming they pass:\n\n  ```bash\n  melos run format   # or format:fix\n  melos run analyze\n  melos run test     # or targeted: test:vm / test:web / test:flutter\n  ```\n\n- Never state that tests pass without having run them. Never check a PR\n  checklist item you have not actually done. Misreporting verification\n  status may lead to the PR being closed.\n\n## 3. Compatibility is sacred — avoid breaking changes\n\ndio's public API is a contract with an enormous downstream. Treat every\npublic symbol as frozen unless a maintainer decides otherwise.\n\n- **Default to non-breaking.** Prefer additive changes: new optional named\n  parameters with safe defaults, new classes, new extension points.\n- Do not change public method signatures, remove/rename public symbols,\n  change default behavior, or alter thrown exception types without going\n  through a deprecation cycle. Breaking changes belong in major releases.\n  As dio's own [CHANGELOG](dio/CHANGELOG.md) preamble states, unavoidable\n  breaking changes may occasionally ship in minor releases — those still\n  require maintainer sign-off in advance and an entry in the\n  [Migration Guide](dio/doc/migration_guide.md).\n- If an API must go away, deprecate first and keep it working:\n\n  ```dart\n  @Deprecated('Use XXX instead. This will be removed in X.0.0')\n  ```\n\n  Deprecations must state their replacement and the removal version, and\n  are only removed in the next major release, together with an entry in\n  the Migration Guide. Target the *next* major, not a version beyond that.\n- Do not raise the minimum Dart/Flutter SDK constraint of any package\n  unless required by the [Compatibility Policy](COMPATIBILITY_POLICY.md)\n  or its listed exceptions. CI tests against the minimum supported SDK;\n  do not use language/library features beyond a package's lower bound.\n- Watch for **behavioral** breaking changes too: changing defaults, header\n  normalization, redirect/error semantics, or timing/ordering of\n  interceptors can break downstream even when signatures are untouched.\n- If a breaking change is genuinely unavoidable, stop and raise it in an\n  issue for maintainers to decide. Do not merge-request it unilaterally.\n\n### Extra scrutiny in security- and network-critical areas\n\nSome parts of dio have oversized blast radius when broken. Changes here\nrequire extra care, and the PR description should explicitly call the\nchange out and @-mention a maintainer:\n\n- SSL / TLS handling and certificate pinning (`badCertificateCallback`,\n  `SecurityContext`, adapters' `HttpClient` configuration).\n- Redirect handling and cross-origin behavior (redirect policy, header\n  forwarding, cookie leakage across redirects).\n- Cookie management (`dio_cookie_manager`, domain / path matching).\n- Header handling (`Authorization`, `Content-Type`, casing, duplicates).\n- Timeout, cancellation, and connection pooling.\n- The interceptor pipeline (ordering, error propagation, `next` /\n  `resolve` / `reject` semantics).\n- Request-body encoding: `FormData`, multipart streaming, encoding\n  detection.\n\nRule of thumb: if getting this wrong could leak credentials, hang a\nrequest forever, or change data on the wire, treat it as sensitive.\n\n### Test certificates and keys\n\nSelf-signed certificates and their private keys used only for local\ntest fixtures (TLS, ALPN, pinning, etc.) are **not real secrets** — but\ncommitting static `.key`/`.crt` files still has costs: secret-scanner\nnoise, package-size bloat for published artifacts, and inconsistency\nwith this repo's convention of generating such fixtures at test time\n(see `scripts/prepare_pinning_certs.sh`).\n\n- **Prefer generating certificates at test setup** (via `openssl` in\n  a `setUp`/helper, or a setup script) over committing static files.\n- **If a static fixture is unavoidable**, exclude it from the published\n  package with both:\n  - `false_secrets` in the package's `pubspec.yaml` (suppresses pub's\n    leak-detection warning), and\n  - a `.pubignore` **inside the fixture subdirectory** (e.g.\n    `test/certificates/.pubignore`), never at the package root — a\n    root-level `.pubignore` overrides the root `.gitignore` for the\n    entire directory, silently re-including build artifacts and other\n    git-ignored files in the published package.\n\n### Dependency changes\n\nDo not bundle drive-by dependency bumps into a feature/fix PR. When a\ndependency change is itself the point of the PR:\n\n- State the reason in the description (security fix, required for a new\n  feature, upstream deprecation, etc.). \"Latest is greater\" is not a\n  reason.\n- Verify the change under every supported SDK version declared in the\n  affected `pubspec.yaml`. Do not raise the package's SDK lower bound\n  just to accommodate the new dependency unless the\n  [Compatibility Policy](COMPATIBILITY_POLICY.md) allows it.\n- Prefer the narrowest constraint that solves the problem (patch >\n  minor > major bump).\n- Call out any new transitive dependencies — downstream users care about\n  their lockfile.\n- Use `⬆️ chore` (or `chore(deps)`) as the commit type.\n\n## 4. Understand before you change\n\n- Read the surrounding code and existing patterns before editing. Match\n  the existing style, naming, and module boundaries.\n- Fix root causes, not symptoms. When a symptom is reported, locate the\n  actual defect before patching.\n- Never guess an API — neither dio's internals nor third-party packages.\n  Read the actual source and the package's own tests/examples when\n  unsure. If `dart analyze` says a member does not exist, go back to the\n  source instead of retrying variations. Dependency source locations:\n\n  | Platform | Default location |\n  |---|---|\n  | macOS / Linux | `~/.pub-cache/hosted/pub.dev/<package>-<version>/` |\n  | Windows | `%LOCALAPPDATA%\\Pub\\Cache\\hosted\\pub.dev\\<package>-<version>\\` |\n\n  If the `PUB_CACHE` environment variable is set, use that location\n  instead of the platform default.\n- **Verify every external fact before writing it down.** Agents\n  routinely hallucinate numbers and attach wrong labels to them — RFC\n  numbers, issue/PR numbers, library/API version numbers, CVE\n  identifiers, deprecation timelines, benchmark figures, attributed\n  quotes, platform-behavior claims (\"iOS X.Y and later…\"). A wrong\n  citation in a commit message, changelog, or doc comment is worse\n  than no citation, because it misleads downstream readers and\n  reviewers who trust it. Before writing any external fact:\n  1. Look up the source and confirm it says what you claim. For RFCs,\n     check `https://www.rfc-editor.org/rfc/rfcNNNN` (or\n     `https://datatracker.ietf.org/doc/rfcNNNN/`) and confirm the\n     title matches; for issues/PRs, open the link; for library\n     versions, read the package's own changelog/source.\n  2. Confirm any section anchor, version number, or quoted text you\n     cite actually exists at that source.\n  3. If you cannot verify the fact online, drop the citation and\n     describe the observed behavior in your own words instead. Do not\n     guess a number to make a statement look authoritative.\n  This applies to commit messages, `CHANGELOG.md`, doc comments,\n  README, and any prose in a PR description.\n\n## 5. Production quality only\n\n- No placeholder work: no `TODO`/`FIXME` left behind, no mocked or\n  simplified logic presented as complete, no \"will optimize later\" code.\n- Handle edge cases and error paths explicitly; never swallow errors\n  silently.\n- If you cannot finish something completely, say so explicitly and state\n  the boundary — do not pretend it is done.\n\n## 6. When to stop and ask\n\nAgents default to \"guess and proceed\". Do not. Pause and check with the\noperator (or open a discussion issue) when:\n\n- The task description is ambiguous and multiple reasonable interpretations\n  would produce materially different implementations.\n- Fixing the reported problem would require design changes that go beyond\n  what was asked for.\n- The right fix touches an area not obviously in scope (e.g., renaming a\n  public API to fix an unrelated bug, or restructuring an interceptor\n  pipeline to enable a small feature).\n- You cannot reproduce the reported issue after a reasonable attempt.\n- The request itself seems wrong (e.g., the \"bug\" is intended behavior, or\n  the \"feature\" would violate a rule in this document).\n\nDo **not** stop to ask permission for routine mechanical steps: running\ntests / format / analyze, staging files, opening a draft PR, or choices\nthat are already decided by this document (commit format, changelog,\nattribution).\n\n## 7. Repository layout\n\nThis is a [Melos](https://github.com/invertase/melos/tree/main/docs)\nmono-repo:\n\n| Path | Package |\n|---|---|\n| `dio/` | The core package |\n| `plugins/web_adapter/` | `dio_web_adapter` |\n| `plugins/cookie_manager/` | `dio_cookie_manager` |\n| `plugins/http2_adapter/` | `dio_http2_adapter` |\n| `plugins/native_dio_adapter/` | `native_dio_adapter` |\n| `plugins/compatibility_layer/` | `dio_compatibility_layer` |\n| `dio_test/` | Shared test suites for all adapters |\n| `example_dart/`, `example_flutter_app/` | Examples |\n\nSetup:\n\n```bash\ndart pub global activate melos\nmelos bootstrap\n```\n\nEach package versions and releases independently. Note that packages have\n**different SDK lower bounds** (see each `pubspec.yaml`).\n\n## 8. Commits, changelog, and PR hygiene\n\n### 8.1 Branch naming\n\nWork on a feature branch named `category/ticket-id-or-short-description`:\n\n- `category` matches the Conventional type used in the commit:\n  `feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `chore`, `ci`,\n  `style`.\n- Use the tracked **ticket id** when one exists — the issue or PR\n  number: `fix/2201`, `feat/2555`. Combining both is fine when it aids\n  discoverability: `fix/2201-cookie-domain-match`.\n- Otherwise use a **short description** — 2–5 kebab-case words that\n  describe the change (`docs/agents-guidelines`,\n  `feat/cors-preflight-warning`, `chore/bump-http2-3.0.0`).\n\nRules:\n\n- Never work on `main` directly.\n- One branch per PR; do not reuse a merged branch for a new change.\n- Keep branch names ASCII, lowercase, and short.\n\n### 8.2 Commit message format — Gitmoji or Conventional\n\nEvery commit uses **[gitmoji](https://gitmoji.dev)** at the front or a\n**[Conventional Commits](https://www.conventionalcommits.org)** type\nprefix. Emojis are chosen from the gitmoji specification — do not invent\nnew ones.\n\n```\n<gitmoji> <Short imperative subject>\n(or)\n<type>[(<scope>)]: <short imperative subject>\n\n[optional body — wrap at ~72 chars]\n\n[optional footer, e.g. Closes #1234]\n```\n\nGitmoji commonly used in this repository (see `git log` for the full set).\n**Pick one column — never both.** Each row maps a gitmoji to its\nequivalent Conventional-type prefix; you use the emoji **or** the type,\nnot the two glued together. `🔧 chore: ...` is wrong.\n\n| Gitmoji | Conventional type | Use for |\n|---|---|---|\n| ✨ `:sparkles:` | `feat` | New user-facing feature |\n| 🐛 `:bug:` | `fix` | Bug fix |\n| ⚡️ `:zap:` | `perf` | Performance improvement |\n| ♻️ `:recycle:` | `refactor` | Refactor with no behavior change |\n| 📝 `:memo:` | `docs` | Documentation |\n| ✅ `:white_check_mark:` | `test` | Tests only |\n| 🚨 `:rotating_light:` | `fix` / `style` | Fix linter or analyzer warnings |\n| 🥅 `:goal_net:` | `fix` / `refactor` | Catch errors / improve error handling |\n| 🔧 `:wrench:` | `chore` | Config / tooling |\n| 👷 `:construction_worker:` | `ci` | CI / workflow changes |\n| 💚 `:green_heart:` | `ci` | Fix a failing CI job |\n| ⬆️ `:arrow_up:` | `chore` | Bump a dependency |\n| 🔥 `:fire:` | `chore` / `refactor` | Remove code or files |\n| 🎨 `:art:` | `style` | Formatting / structure only |\n| 🔖 `:bookmark:` | `chore(release)` | Release (**maintainers only**) |\n\nRules:\n\n- Subject is an imperative English sentence. Do not append the PR number —\n  GitHub adds `(#N)` automatically on squash-merge.\n- Use scope when it clarifies (`fix(dio_web_adapter): ...`); omit when it\n  would just repeat the file path.\n- Position 0 is either the emoji or the Conventional prefix plus colon, then a space, then the subject.\n- After a gitmoji the subject starts with a **capital letter**\n  (`🐛 Allow ...`, `📝 Clarify ...`); after a Conventional prefix the\n  subject stays lowercase (`docs: add ...`, `perf(dio): reduce ...`).\n\nExamples (adapted from actual repo history):\n\n```\n🐛 Allow `callFollowingErrorInterceptor` when rejecting in `ErrorInterceptorHandler`\nperf(dio): reduce `FormData.readAsBytes` memory usage for large payloads\ndocs: add agent contribution guidelines\n```\n\nDo **not** combine the two styles:\n\n```\n❌ 🔧 chore: group codeql-action updates      (both gitmoji AND prefix)\n✅ 🔧 Group codeql-action updates              (gitmoji only, capitalized subject)\n✅ chore: group codeql-action updates          (Conventional only, lowercase subject)\n```\n\n### 8.3 AI attribution — mandatory\n\nTransparency about AI involvement is required. Do not hide it, and do not\nskip it \"to keep the commit clean\".\n\n- Add a `Co-Authored-By:` trailer for **every AI agent** that produced\n  code, tests, or docs in the commit:\n\n  ```\n  Co-Authored-By: Claude <noreply@anthropic.com>\n  Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>\n  ```\n\n  Use the identity the agent itself publishes (see its own docs / recent\n  commits from that agent on GitHub). Multiple agents → multiple trailers.\n- Also disclose in the PR description **which agent(s) were used and for\n  what stage** — design, implementation, tests, or review. One line is\n  enough, e.g.:\n\n  > *Implementation and tests by Devin; local review pass by GLM-5.2.*\n\n- AI attribution never shifts accountability. The human submitting the PR\n  owns every line, must understand it, and must respond to review feedback\n  substantively. \"The AI wrote it\" is not an answer to a review question.\n\n### 8.4 CHANGELOG and docs\n\n- Update the `CHANGELOG.md` of **every package you changed**, under\n  `## Unreleased` (replace `*None.*`).\n- One concise bullet per change, written for downstream users, not for\n  reviewers.\n- Do not bump version numbers — releases are handled by maintainers.\n- When public APIs change, also update `README.md`, `README-ZH.md`, API\n  doc comments, and any affected examples.\n\n### 8.5 Self-review your diff before every commit\n\nAlways inspect what you are about to commit:\n\n```bash\ngit diff                          # unstaged\ngit diff --staged                 # staged\ngit diff <base-branch>...HEAD     # full branch diff before opening/updating a PR\n```\n\nRemove before committing:\n\n- Debug output (`print`, `debugPrint`, `console.log`, temporary logs).\n- Commented-out code left from earlier attempts.\n- Reformatting or import re-ordering of files that are not the subject\n  of this change.\n- Unrelated bumps in `pubspec.yaml` / `pubspec.lock`.\n- Whitespace-only changes in unrelated files.\n- Editor/OS junk (`.DS_Store`, `.idea/`, personal scratch files).\n\nIf you cannot explain why a hunk is in the diff, it does not belong in\nthe commit. Never use `git add .` or `git add -A` — stage files by path.\n\n**Also re-read the commit message against the staged diff.** A message\ncarried over from a previous attempt, or auto-completed from an\nunrelated commit, is easy to miss and lands verbatim in history. If the\nmessage and the diff describe different work, one of them is wrong.\n\n### 8.6 Opening the PR\n\n- **Open as a draft PR** (`Create draft pull request`) when the change\n  is large, exploratory, or when you want maintainer direction before\n  polishing. Convert to Ready for Review once local checks pass and the\n  description is complete.\n- Reference the closing issue with `Closes #NNNN` in the description.\n- Follow the AI attribution rules in §8.3: disclose which agent(s)\n  contributed and at which stage.\n- Write PR titles and bodies in English, in the same commit style as\n  §8.2.\n- Only tick a PR checklist item that is genuinely done. For items that\n  do not apply, keep the box unchecked and add *(not applicable —\n  reason)* next to it. Do not check \"done\" as a shortcut.\n- **Describe verification honestly — no boilerplate \"Test plan\"\n  checklist.** In prose, state what you actually confirmed and how, in\n  one or two sentences:\n\n  > *Added 15 unit tests covering method / content-type / custom-header\n  > combinations; `melos run test:vm` and `melos run analyze` clean.*\n\n  Do **not** paste a generic checklist — this is the anti-pattern this\n  section is explicitly rejecting, even if your agent tooling suggests\n  one by default:\n\n  ```\n  ❌  ## Test plan\n      - [ ] Tests pass\n      - [ ] Feature works as expected\n  ```\n\n  Mechanical prerequisites (`dart analyze`, `dart format`) are already\n  covered by the PR template's top-level checklist — do not re-list them\n  as \"tests\". Behavioral verification means checks that would fail if\n  this change regressed.\n\n  If something that ought to be verified genuinely could not be — needs\n  browser CI, a physical device, production load, and so on — list it\n  under a short **Unverified** paragraph explaining why. Unverified\n  items are known risks; this should stay rare, not become routine.\n\n### 8.7 Review iteration workflow\n\nAfter opening the PR:\n\n- **Address feedback with new commits appended to the branch**, not by\n  squash-and-force-push. Maintainers rely on incremental history during\n  review; squashing happens at merge time.\n- **Avoid `git push --force` on a branch that already has review\n  comments** — it detaches those comments from their code position. If a\n  rebase is genuinely required (e.g., conflict resolution against\n  `main`), leave a comment before pushing so reviewers know.\n- **Do not close and reopen the PR** to reset review state, retry CI, or\n  bypass a blocking review. Push a fix instead.\n- **Design-level feedback is a conversation, not an instruction.** If a\n  reviewer's suggestion changes the intent of the PR (not just its\n  implementation), reply first and reach agreement before writing new\n  code. Blindly applying a large suggestion is worse than discussing it.\n- **Mark review threads resolved** only after you have addressed the\n  point in code and left a reply explaining what changed — or after the\n  reviewer explicitly says so. Do not silently resolve.\n- **CI failures**: read the failing job's log, find the root cause, then\n  push a fix. Never re-run CI hoping for a green run. If a test is\n  genuinely flaky, say so in a comment — do not paper over it by\n  disabling the test or adding retries.\n\n## 9. Patterns that may lead to closure\n\nQuick cross-reference — each pattern is a violation of the rules above.\nPRs matching one or more of these may be closed without detailed review\nat the maintainers' discretion.\n\n| Pattern | See |\n|---|---|\n| No motivation or prior maintainer discussion | §1 |\n| Multiple unrelated changes bundled in one PR | §1 |\n| Logic changes without effective, non-duplicated tests | §2 |\n| Public-API break without maintainer sign-off | §3 |\n| Sensitive-area change without maintainer notice | §3 |\n| Drive-by dependency bump in a feature/fix PR | §3 |\n| Guessed / hallucinated API usage | §4 |\n| Unverified or wrong external factual reference | §4 |\n| Drive-by refactors, formatting sweeps, unrelated `.gitignore` / CI edits | §4, §8.5 |\n| Placeholder work (`TODO`/`FIXME`, mocked or simplified logic presented as complete) | §5 |\n| Branch name not following `category/ticket-id-or-short-description` | §8.1 |\n| Non-standard commit message format (missing gitmoji, wrong type, non-English) | §8.2 |\n| Missing or hidden AI attribution | §8.3 |\n| Debug output or commented-out code left in the diff | §8.5 |\n| Falsely checked PR checklist items | §8.6 |\n| Force-pushing or close/reopen to reset review state | §8.7 |\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Agent Contribution Guidelines\n\nLanguage: English | [简体中文](AGENTS-ZH.md)\n\nThis document defines the rules for AI agents (and the humans operating them)\nworking on this repository — whether you are contributing a pull request or\nassisting a maintainer locally. It supplements, and never overrides,\n[CONTRIBUTING.md](CONTRIBUTING.md) and the\n[Compatibility Policy](COMPATIBILITY_POLICY.md).\n\ndio is one of the most depended-on packages in the Dart/Flutter ecosystem.\nA single careless change can break tens of thousands of downstream projects.\nContributions here are not a playground: every change must be motivated,\ntested, and compatible.\n\n## 1. Motivation first — no speculative changes\n\n**Do not invent work.** A change is only acceptable when it solves a problem\nthat actually exists.\n\n- Every non-trivial change must be traceable to a concrete motivation:\n  a reproducible bug, an accepted issue/discussion, an RFC-style proposal,\n  or an explicit maintainer request. \"This seems useful\" is not a motivation.\n- Before implementing a feature, answer these questions in the issue or the\n  PR description — if you cannot, do not open the PR:\n  1. What cannot be done (or is done poorly) with the current dio?\n  2. Who needs this, and in which real-world scenario?\n  3. Why does it belong in dio itself, instead of an interceptor, an adapter,\n     a transformer, or a separate package? dio is intentionally extensible;\n     most needs are served by its extension points without core changes.\n  4. What is the cost — API surface, maintenance burden, compatibility risk?\n- One PR, one concern. Do not bundle several unrelated features or fixes\n  into a single PR. Bundled \"improvement packs\" might be closed unreviewed.\n- For any user-facing feature, open an issue for discussion **before**\n  writing code, unless a maintainer has already asked for it. A bare\n  `Closes #NNNN` is not the same as prior discussion: the referenced issue\n  must show that maintainers have expressed interest or accepted the\n  direction. Feature PRs without that grounding waste both your tokens and\n  the maintainers' time, and might be closed.\n\n## 2. Tests are mandatory for logic changes\n\nEvery behavioral change must be proven by tests.\n\n- Any change to logic requires new tests or adjustments to existing tests\n  that fail without the change and pass with it. Bug fixes must include a\n  regression test that reproduces the original report.\n- CI reports coverage diffs on every PR. The published minimum threshold is\n  low, but that is a floor, not a target: coverage of code you changed\n  should not regress, and new logic (including error paths) should be\n  covered by real assertions.\n- Tests must be **effective and non-duplicated**:\n  - Assert observable behavior, not implementation details.\n  - Do not add tests that merely re-execute existing covered paths to\n    inflate coverage numbers.\n  - Search the existing suites first — extend an existing test group\n    instead of creating a near-duplicate file.\n- Put tests in the right place:\n  - Package-specific behavior → `<package>/test/`.\n  - Behavior that must hold across all adapters/platforms → the shared\n    `dio_test` package.\n- Run the checks locally before claiming they pass:\n\n  ```bash\n  melos run format   # or format:fix\n  melos run analyze\n  melos run test     # or targeted: test:vm / test:web / test:flutter\n  ```\n\n- Never state that tests pass without having run them. Never check a PR\n  checklist item you have not actually done. Misreporting verification\n  status may lead to the PR being closed.\n\n## 3. Compatibility is sacred — avoid breaking changes\n\ndio's public API is a contract with an enormous downstream. Treat every\npublic symbol as frozen unless a maintainer decides otherwise.\n\n- **Default to non-breaking.** Prefer additive changes: new optional named\n  parameters with safe defaults, new classes, new extension points.\n- Do not change public method signatures, remove/rename public symbols,\n  change default behavior, or alter thrown exception types without going\n  through a deprecation cycle. Breaking changes belong in major releases.\n  As dio's own [CHANGELOG](dio/CHANGELOG.md) preamble states, unavoidable\n  breaking changes may occasionally ship in minor releases — those still\n  require maintainer sign-off in advance and an entry in the\n  [Migration Guide](dio/doc/migration_guide.md).\n- If an API must go away, deprecate first and keep it working:\n\n  ```dart\n  @Deprecated('Use XXX instead. This will be removed in X.0.0')\n  ```\n\n  Deprecations must state their replacement and the removal version, and\n  are only removed in the next major release, together with an entry in\n  the Migration Guide. Target the *next* major, not a version beyond that.\n- Do not raise the minimum Dart/Flutter SDK constraint of any package\n  unless required by the [Compatibility Policy](COMPATIBILITY_POLICY.md)\n  or its listed exceptions. CI tests against the minimum supported SDK;\n  do not use language/library features beyond a package's lower bound.\n- Watch for **behavioral** breaking changes too: changing defaults, header\n  normalization, redirect/error semantics, or timing/ordering of\n  interceptors can break downstream even when signatures are untouched.\n- If a breaking change is genuinely unavoidable, stop and raise it in an\n  issue for maintainers to decide. Do not merge-request it unilaterally.\n\n### Extra scrutiny in security- and network-critical areas\n\nSome parts of dio have oversized blast radius when broken. Changes here\nrequire extra care, and the PR description should explicitly call the\nchange out and @-mention a maintainer:\n\n- SSL / TLS handling and certificate pinning (`badCertificateCallback`,\n  `SecurityContext`, adapters' `HttpClient` configuration).\n- Redirect handling and cross-origin behavior (redirect policy, header\n  forwarding, cookie leakage across redirects).\n- Cookie management (`dio_cookie_manager`, domain / path matching).\n- Header handling (`Authorization`, `Content-Type`, casing, duplicates).\n- Timeout, cancellation, and connection pooling.\n- The interceptor pipeline (ordering, error propagation, `next` /\n  `resolve` / `reject` semantics).\n- Request-body encoding: `FormData`, multipart streaming, encoding\n  detection.\n\nRule of thumb: if getting this wrong could leak credentials, hang a\nrequest forever, or change data on the wire, treat it as sensitive.\n\n### Test certificates and keys\n\nSelf-signed certificates and their private keys used only for local\ntest fixtures (TLS, ALPN, pinning, etc.) are **not real secrets** — but\ncommitting static `.key`/`.crt` files still has costs: secret-scanner\nnoise, package-size bloat for published artifacts, and inconsistency\nwith this repo's convention of generating such fixtures at test time\n(see `scripts/prepare_pinning_certs.sh`).\n\n- **Prefer generating certificates at test setup** (via `openssl` in\n  a `setUp`/helper, or a setup script) over committing static files.\n- **If a static fixture is unavoidable**, exclude it from the published\n  package with both:\n  - `false_secrets` in the package's `pubspec.yaml` (suppresses pub's\n    leak-detection warning), and\n  - a `.pubignore` **inside the fixture subdirectory** (e.g.\n    `test/certificates/.pubignore`), never at the package root — a\n    root-level `.pubignore` overrides the root `.gitignore` for the\n    entire directory, silently re-including build artifacts and other\n    git-ignored files in the published package.\n\n### Dependency changes\n\nDo not bundle drive-by dependency bumps into a feature/fix PR. When a\ndependency change is itself the point of the PR:\n\n- State the reason in the description (security fix, required for a new\n  feature, upstream deprecation, etc.). \"Latest is greater\" is not a\n  reason.\n- Verify the change under every supported SDK version declared in the\n  affected `pubspec.yaml`. Do not raise the package's SDK lower bound\n  just to accommodate the new dependency unless the\n  [Compatibility Policy](COMPATIBILITY_POLICY.md) allows it.\n- Prefer the narrowest constraint that solves the problem (patch >\n  minor > major bump).\n- Call out any new transitive dependencies — downstream users care about\n  their lockfile.\n- Use `⬆️ chore` (or `chore(deps)`) as the commit type.\n\n## 4. Understand before you change\n\n- Read the surrounding code and existing patterns before editing. Match\n  the existing style, naming, and module boundaries.\n- Fix root causes, not symptoms. When a symptom is reported, locate the\n  actual defect before patching.\n- Never guess an API — neither dio's internals nor third-party packages.\n  Read the actual source and the package's own tests/examples when\n  unsure. If `dart analyze` says a member does not exist, go back to the\n  source instead of retrying variations. Dependency source locations:\n\n  | Platform | Default location |\n  |---|---|\n  | macOS / Linux | `~/.pub-cache/hosted/pub.dev/<package>-<version>/` |\n  | Windows | `%LOCALAPPDATA%\\Pub\\Cache\\hosted\\pub.dev\\<package>-<version>\\` |\n\n  If the `PUB_CACHE` environment variable is set, use that location\n  instead of the platform default.\n- **Verify every external fact before writing it down.** Agents\n  routinely hallucinate numbers and attach wrong labels to them — RFC\n  numbers, issue/PR numbers, library/API version numbers, CVE\n  identifiers, deprecation timelines, benchmark figures, attributed\n  quotes, platform-behavior claims (\"iOS X.Y and later…\"). A wrong\n  citation in a commit message, changelog, or doc comment is worse\n  than no citation, because it misleads downstream readers and\n  reviewers who trust it. Before writing any external fact:\n  1. Look up the source and confirm it says what you claim. For RFCs,\n     check `https://www.rfc-editor.org/rfc/rfcNNNN` (or\n     `https://datatracker.ietf.org/doc/rfcNNNN/`) and confirm the\n     title matches; for issues/PRs, open the link; for library\n     versions, read the package's own changelog/source.\n  2. Confirm any section anchor, version number, or quoted text you\n     cite actually exists at that source.\n  3. If you cannot verify the fact online, drop the citation and\n     describe the observed behavior in your own words instead. Do not\n     guess a number to make a statement look authoritative.\n  This applies to commit messages, `CHANGELOG.md`, doc comments,\n  README, and any prose in a PR description.\n\n## 5. Production quality only\n\n- No placeholder work: no `TODO`/`FIXME` left behind, no mocked or\n  simplified logic presented as complete, no \"will optimize later\" code.\n- Handle edge cases and error paths explicitly; never swallow errors\n  silently.\n- If you cannot finish something completely, say so explicitly and state\n  the boundary — do not pretend it is done.\n\n## 6. When to stop and ask\n\nAgents default to \"guess and proceed\". Do not. Pause and check with the\noperator (or open a discussion issue) when:\n\n- The task description is ambiguous and multiple reasonable interpretations\n  would produce materially different implementations.\n- Fixing the reported problem would require design changes that go beyond\n  what was asked for.\n- The right fix touches an area not obviously in scope (e.g., renaming a\n  public API to fix an unrelated bug, or restructuring an interceptor\n  pipeline to enable a small feature).\n- You cannot reproduce the reported issue after a reasonable attempt.\n- The request itself seems wrong (e.g., the \"bug\" is intended behavior, or\n  the \"feature\" would violate a rule in this document).\n\nDo **not** stop to ask permission for routine mechanical steps: running\ntests / format / analyze, staging files, opening a draft PR, or choices\nthat are already decided by this document (commit format, changelog,\nattribution).\n\n## 7. Repository layout\n\nThis is a [Melos](https://github.com/invertase/melos/tree/main/docs)\nmono-repo:\n\n| Path | Package |\n|---|---|\n| `dio/` | The core package |\n| `plugins/web_adapter/` | `dio_web_adapter` |\n| `plugins/cookie_manager/` | `dio_cookie_manager` |\n| `plugins/http2_adapter/` | `dio_http2_adapter` |\n| `plugins/native_dio_adapter/` | `native_dio_adapter` |\n| `plugins/compatibility_layer/` | `dio_compatibility_layer` |\n| `dio_test/` | Shared test suites for all adapters |\n| `example_dart/`, `example_flutter_app/` | Examples |\n\nSetup:\n\n```bash\ndart pub global activate melos\nmelos bootstrap\n```\n\nEach package versions and releases independently. Note that packages have\n**different SDK lower bounds** (see each `pubspec.yaml`).\n\n## 8. Commits, changelog, and PR hygiene\n\n### 8.1 Branch naming\n\nWork on a feature branch named `category/ticket-id-or-short-description`:\n\n- `category` matches the Conventional type used in the commit:\n  `feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `chore`, `ci`,\n  `style`.\n- Use the tracked **ticket id** when one exists — the issue or PR\n  number: `fix/2201`, `feat/2555`. Combining both is fine when it aids\n  discoverability: `fix/2201-cookie-domain-match`.\n- Otherwise use a **short description** — 2–5 kebab-case words that\n  describe the change (`docs/agents-guidelines`,\n  `feat/cors-preflight-warning`, `chore/bump-http2-3.0.0`).\n\nRules:\n\n- Never work on `main` directly.\n- One branch per PR; do not reuse a merged branch for a new change.\n- Keep branch names ASCII, lowercase, and short.\n\n### 8.2 Commit message format — Gitmoji or Conventional\n\nEvery commit uses **[gitmoji](https://gitmoji.dev)** at the front or a\n**[Conventional Commits](https://www.conventionalcommits.org)** type\nprefix. Emojis are chosen from the gitmoji specification — do not invent\nnew ones.\n\n```\n<gitmoji> <Short imperative subject>\n(or)\n<type>[(<scope>)]: <short imperative subject>\n\n[optional body — wrap at ~72 chars]\n\n[optional footer, e.g. Closes #1234]\n```\n\nGitmoji commonly used in this repository (see `git log` for the full set).\n**Pick one column — never both.** Each row maps a gitmoji to its\nequivalent Conventional-type prefix; you use the emoji **or** the type,\nnot the two glued together. `🔧 chore: ...` is wrong.\n\n| Gitmoji | Conventional type | Use for |\n|---|---|---|\n| ✨ `:sparkles:` | `feat` | New user-facing feature |\n| 🐛 `:bug:` | `fix` | Bug fix |\n| ⚡️ `:zap:` | `perf` | Performance improvement |\n| ♻️ `:recycle:` | `refactor` | Refactor with no behavior change |\n| 📝 `:memo:` | `docs` | Documentation |\n| ✅ `:white_check_mark:` | `test` | Tests only |\n| 🚨 `:rotating_light:` | `fix` / `style` | Fix linter or analyzer warnings |\n| 🥅 `:goal_net:` | `fix` / `refactor` | Catch errors / improve error handling |\n| 🔧 `:wrench:` | `chore` | Config / tooling |\n| 👷 `:construction_worker:` | `ci` | CI / workflow changes |\n| 💚 `:green_heart:` | `ci` | Fix a failing CI job |\n| ⬆️ `:arrow_up:` | `chore` | Bump a dependency |\n| 🔥 `:fire:` | `chore` / `refactor` | Remove code or files |\n| 🎨 `:art:` | `style` | Formatting / structure only |\n| 🔖 `:bookmark:` | `chore(release)` | Release (**maintainers only**) |\n\nRules:\n\n- Subject is an imperative English sentence. Do not append the PR number —\n  GitHub adds `(#N)` automatically on squash-merge.\n- Use scope when it clarifies (`fix(dio_web_adapter): ...`); omit when it\n  would just repeat the file path.\n- Position 0 is either the emoji or the Conventional prefix plus colon, then a space, then the subject.\n- After a gitmoji the subject starts with a **capital letter**\n  (`🐛 Allow ...`, `📝 Clarify ...`); after a Conventional prefix the\n  subject stays lowercase (`docs: add ...`, `perf(dio): reduce ...`).\n\nExamples (adapted from actual repo history):\n\n```\n🐛 Allow `callFollowingErrorInterceptor` when rejecting in `ErrorInterceptorHandler`\nperf(dio): reduce `FormData.readAsBytes` memory usage for large payloads\ndocs: add agent contribution guidelines\n```\n\nDo **not** combine the two styles:\n\n```\n❌ 🔧 chore: group codeql-action updates      (both gitmoji AND prefix)\n✅ 🔧 Group codeql-action updates              (gitmoji only, capitalized subject)\n✅ chore: group codeql-action updates          (Conventional only, lowercase subject)\n```\n\n### 8.3 AI attribution — mandatory\n\nTransparency about AI involvement is required. Do not hide it, and do not\nskip it \"to keep the commit clean\".\n\n- Add a `Co-Authored-By:` trailer for **every AI agent** that produced\n  code, tests, or docs in the commit:\n\n  ```\n  Co-Authored-By: Claude <noreply@anthropic.com>\n  Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>\n  ```\n\n  Use the identity the agent itself publishes (see its own docs / recent\n  commits from that agent on GitHub). Multiple agents → multiple trailers.\n- Also disclose in the PR description **which agent(s) were used and for\n  what stage** — design, implementation, tests, or review. One line is\n  enough, e.g.:\n\n  > *Implementation and tests by Devin; local review pass by GLM-5.2.*\n\n- AI attribution never shifts accountability. The human submitting the PR\n  owns every line, must understand it, and must respond to review feedback\n  substantively. \"The AI wrote it\" is not an answer to a review question.\n\n### 8.4 CHANGELOG and docs\n\n- Update the `CHANGELOG.md` of **every package you changed**, under\n  `## Unreleased` (replace `*None.*`).\n- One concise bullet per change, written for downstream users, not for\n  reviewers.\n- Do not bump version numbers — releases are handled by maintainers.\n- When public APIs change, also update `README.md`, `README-ZH.md`, API\n  doc comments, and any affected examples.\n\n### 8.5 Self-review your diff before every commit\n\nAlways inspect what you are about to commit:\n\n```bash\ngit diff                          # unstaged\ngit diff --staged                 # staged\ngit diff <base-branch>...HEAD     # full branch diff before opening/updating a PR\n```\n\nRemove before committing:\n\n- Debug output (`print`, `debugPrint`, `console.log`, temporary logs).\n- Commented-out code left from earlier attempts.\n- Reformatting or import re-ordering of files that are not the subject\n  of this change.\n- Unrelated bumps in `pubspec.yaml` / `pubspec.lock`.\n- Whitespace-only changes in unrelated files.\n- Editor/OS junk (`.DS_Store`, `.idea/`, personal scratch files).\n\nIf you cannot explain why a hunk is in the diff, it does not belong in\nthe commit. Never use `git add .` or `git add -A` — stage files by path.\n\n**Also re-read the commit message against the staged diff.** A message\ncarried over from a previous attempt, or auto-completed from an\nunrelated commit, is easy to miss and lands verbatim in history. If the\nmessage and the diff describe different work, one of them is wrong.\n\n### 8.6 Opening the PR\n\n- **Open as a draft PR** (`Create draft pull request`) when the change\n  is large, exploratory, or when you want maintainer direction before\n  polishing. Convert to Ready for Review once local checks pass and the\n  description is complete.\n- Reference the closing issue with `Closes #NNNN` in the description.\n- Follow the AI attribution rules in §8.3: disclose which agent(s)\n  contributed and at which stage.\n- Write PR titles and bodies in English, in the same commit style as\n  §8.2.\n- Only tick a PR checklist item that is genuinely done. For items that\n  do not apply, keep the box unchecked and add *(not applicable —\n  reason)* next to it. Do not check \"done\" as a shortcut.\n- **Describe verification honestly — no boilerplate \"Test plan\"\n  checklist.** In prose, state what you actually confirmed and how, in\n  one or two sentences:\n\n  > *Added 15 unit tests covering method / content-type / custom-header\n  > combinations; `melos run test:vm` and `melos run analyze` clean.*\n\n  Do **not** paste a generic checklist — this is the anti-pattern this\n  section is explicitly rejecting, even if your agent tooling suggests\n  one by default:\n\n  ```\n  ❌  ## Test plan\n      - [ ] Tests pass\n      - [ ] Feature works as expected\n  ```\n\n  Mechanical prerequisites (`dart analyze`, `dart format`) are already\n  covered by the PR template's top-level checklist — do not re-list them\n  as \"tests\". Behavioral verification means checks that would fail if\n  this change regressed.\n\n  If something that ought to be verified genuinely could not be — needs\n  browser CI, a physical device, production load, and so on — list it\n  under a short **Unverified** paragraph explaining why. Unverified\n  items are known risks; this should stay rare, not become routine.\n\n### 8.7 Review iteration workflow\n\nAfter opening the PR:\n\n- **Address feedback with new commits appended to the branch**, not by\n  squash-and-force-push. Maintainers rely on incremental history during\n  review; squashing happens at merge time.\n- **Avoid `git push --force` on a branch that already has review\n  comments** — it detaches those comments from their code position. If a\n  rebase is genuinely required (e.g., conflict resolution against\n  `main`), leave a comment before pushing so reviewers know.\n- **Do not close and reopen the PR** to reset review state, retry CI, or\n  bypass a blocking review. Push a fix instead.\n- **Design-level feedback is a conversation, not an instruction.** If a\n  reviewer's suggestion changes the intent of the PR (not just its\n  implementation), reply first and reach agreement before writing new\n  code. Blindly applying a large suggestion is worse than discussing it.\n- **Mark review threads resolved** only after you have addressed the\n  point in code and left a reply explaining what changed — or after the\n  reviewer explicitly says so. Do not silently resolve.\n- **CI failures**: read the failing job's log, find the root cause, then\n  push a fix. Never re-run CI hoping for a green run. If a test is\n  genuinely flaky, say so in a comment — do not paper over it by\n  disabling the test or adding retries.\n\n## 9. Patterns that may lead to closure\n\nQuick cross-reference — each pattern is a violation of the rules above.\nPRs matching one or more of these may be closed without detailed review\nat the maintainers' discretion.\n\n| Pattern | See |\n|---|---|\n| No motivation or prior maintainer discussion | §1 |\n| Multiple unrelated changes bundled in one PR | §1 |\n| Logic changes without effective, non-duplicated tests | §2 |\n| Public-API break without maintainer sign-off | §3 |\n| Sensitive-area change without maintainer notice | §3 |\n| Drive-by dependency bump in a feature/fix PR | §3 |\n| Guessed / hallucinated API usage | §4 |\n| Unverified or wrong external factual reference | §4 |\n| Drive-by refactors, formatting sweeps, unrelated `.gitignore` / CI edits | §4, §8.5 |\n| Placeholder work (`TODO`/`FIXME`, mocked or simplified logic presented as complete) | §5 |\n| Branch name not following `category/ticket-id-or-short-description` | §8.1 |\n| Non-standard commit message format (missing gitmoji, wrong type, non-English) | §8.2 |\n| Missing or hidden AI attribution | §8.3 |\n| Debug output or commented-out code left in the diff | §8.5 |\n| Falsely checked PR checklist items | §8.6 |\n| Force-pushing or close/reopen to reset review state | §8.7 |\n","category":"root","tokens":5717}]}