)]}'
{
  "log": [
    {
      "commit": "70473568c3cc93b3332bd3f7dc59c1cb7195a5d5",
      "tree": "b4cb6ffabebe9ec4dad53455c1a0e4bbaf0a3b50",
      "parents": [
        "5b54cbc9a4dece28727c542b4cc7fe21849a7c03"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Nov 06 09:49:23 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Nov 06 09:49:23 2026 -0800"
      },
      "message": "[dart_mcp_server] Tighten input and path validation in package tools (#740)\n\n## Summary\n\nTightens argument and path validation for the package dependency tools (`rip_grep_packages` and `read_package_uris`):\n\n- Ensure `rip_grep_packages` arguments include at least one `-e`/`--regexp` pattern flag, disallow inline values on boolean flags, and make `_runRipGrep` private.\n- Pass `--no-config` and `--no-follow` to `rg` for consistent behavior across user environments, and set `additionalProperties: false` on the `rip_grep_packages` input schema.\n- Normalize and resolve paths when checking package root bounds in `rip_grep_packages` and `read_package_uris`.\n- Use `-NoProfile`, `-NonInteractive`, and single-quoted `-LiteralPath` arguments when extracting ripgrep archives via PowerShell on Windows.\n- Bump version to `1.2.3-wip` and update `CHANGELOG.md`.\n\n## Tests\n\n- Added unit tests in `test/tools/grep_test.dart` and `test/tools/package_uri_reader_test.dart` covering pattern flag validation, inline boolean flag values, NUL character rejection, and symlink path handling."
    },
    {
      "commit": "5b54cbc9a4dece28727c542b4cc7fe21849a7c03",
      "tree": "33b57a2995ce8c585af830d7e399e0324f04d361",
      "parents": [
        "be01628e4c477428292017fa822a4b5566b4e25f"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Nov 05 14:48:07 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Nov 05 14:48:07 2026 -0800"
      },
      "message": "fix tests for new dtd output (#743)"
    },
    {
      "commit": "be01628e4c477428292017fa822a4b5566b4e25f",
      "tree": "94bf0dc302169bdce57ffa69c3a48fbe54b4fbbc",
      "parents": [
        "4d2e4e87b5d1dfb8caa6b180829d86a76702946e"
      ],
      "author": {
        "name": "Keerti Parthasarathy",
        "email": "keertip@users.noreply.github.com",
        "time": "Thu Nov 05 21:45:39 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Nov 05 13:45:39 2026 -0800"
      },
      "message": "[skills] Report skills_cli as the leaf tool in analytics (#742)\n\nFixes #709.\n\npackage:unified_analytics 8.4.0 now records two tool dimensions on every event:\n\n- root_tool: the user\u0027s entry point, resolved from DASH__TOOL.\n- leaf_tool: the logical tool passed to Analytics.\n\nIt also turns analytics off when a shared component has no root tool. This PR moves the skills CLI over to that model.\n\nChanges\n- bin/skills.dart no longer reads DASH__TOOL. It always creates Analytics(tool: DashTool.skillsCli, ...), and unified_analytics:\nresolves root_tool from DASH__TOOL. Standalone runs go through dart run, so they get dart-tool; runs started by another tool get that tool;\n- records skills-cli as leaf_tool;\n- keeps sending the deprecated tool user property with its current value (the root tool), so existing dashboards are unaffected;\n- returns a no-op Analytics when DASH__TOOL isn\u0027t set to a valid root tool. This replaces the CLI\u0027s own \"no DASH__TOOL, no analytics\" check."
    },
    {
      "commit": "4d2e4e87b5d1dfb8caa6b180829d86a76702946e",
      "tree": "ccef0b4aa5c15a078c07c24109228c22dbb7ae50",
      "parents": [
        "e1d9de8e03a569fe599b49eaef9275b8d7fb28ac"
      ],
      "author": {
        "name": "Keerti Parthasarathy",
        "email": "keertip@users.noreply.github.com",
        "time": "Thu Nov 05 21:35:52 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Nov 05 13:35:52 2026 -0800"
      },
      "message": "[dart-mcp-server]Analytics: Report dart_mcp_server as leaf tool (#741)\n\nFixes #708.\n\npackage:unified_analytics 8.4.0 now records two tool dimensions on every event:\n\nroot_tool: the user\u0027s entry point, resolved from DASH__TOOL.\nleaf_tool: the logical tool passed to Analytics.\n\nIt also turns analytics off when a shared component has no root tool. This PR moves the MCP server over to that model. The behavior of `tool` remains the same."
    },
    {
      "commit": "e1d9de8e03a569fe599b49eaef9275b8d7fb28ac",
      "tree": "5d4f2618158ba411011baab028202505cae09ec3",
      "parents": [
        "fbfc4ff6bd9fab23102394e80e89678380b8c4e6"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Nov 05 09:48:18 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Nov 05 09:48:18 2026 -0800"
      },
      "message": "[dart_mcp_server] Update generated files in counter_app test fixture (#739)\n\n[Agent] Commit the `analysis_options.yaml` and generated plugin registrant updates produced by `flutter pub get` in `pkgs/dart_mcp_server/test_fixtures/counter_app` so running `flutter pub get` locally doesn\u0027t dirty the working tree."
    },
    {
      "commit": "fbfc4ff6bd9fab23102394e80e89678380b8c4e6",
      "tree": "af50999bacb88e5b9cec56ec2d2a293e3f11d793",
      "parents": [
        "c4ca430a338c37a58cbc9983767f57ded0bd4e85"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Wed Nov 04 07:59:04 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Nov 04 07:59:04 2026 -0800"
      },
      "message": "sort ignores (#737)"
    },
    {
      "commit": "c4ca430a338c37a58cbc9983767f57ded0bd4e85",
      "tree": "bb1ca49c019090d3744a67ca81b32294ed794899",
      "parents": [
        "d24d7baf4e877f1e088c552226e95486004b8a0b"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Tue Nov 03 23:33:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 15:33:22 2026 -0800"
      },
      "message": "[manual_evals] Add the manual-evals-token-usage skill (#735)"
    },
    {
      "commit": "d24d7baf4e877f1e088c552226e95486004b8a0b",
      "tree": "800836647ca810f78643d1f67a7320c3b8753f16",
      "parents": [
        "ee5a0dcf1501dd711ec13559f5fe607a0ef1d7c3"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Nov 03 14:24:15 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 14:24:15 2026 -0800"
      },
      "message": "update gitignore to ignore all but the allow listed skills under .agents/skills (#736)\n\nIgnore the `.config` dir (where package:skills puts its config), and all but the explicitly checked in skills under `.agents/skills`.\n\nThis allows you to locally add skills for yourself, without polluting your git tree."
    },
    {
      "commit": "ee5a0dcf1501dd711ec13559f5fe607a0ef1d7c3",
      "tree": "1a19246b2ac04c1f8e8053fbbc674d2313242346",
      "parents": [
        "36623f6ae9a6497697d438e8e032320d13eb1167"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Nov 04 00:33:34 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 13:33:34 2026 -0800"
      },
      "message": "Correct elicitation and contribution descriptions in GEMINI.md (#727)\n\nDescribe ElicitationRequestSupport capability checks and completion notifications. Update the CONTRIBUTING.md description to reflect its existing guidance.\n\nPart of #720."
    },
    {
      "commit": "36623f6ae9a6497697d438e8e032320d13eb1167",
      "tree": "ca57904efb69e89874940c7d00882129c3780181",
      "parents": [
        "0b617ace2c5317be8e4747fbbeac015af9e623d8"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Tue Nov 03 17:40:53 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 09:40:53 2026 -0800"
      },
      "message": "[manual_evals] Add transcript loading APIs (#728)"
    },
    {
      "commit": "0b617ace2c5317be8e4747fbbeac015af9e623d8",
      "tree": "dba84ab6ce6e6279047349ed2572a17bd6449bef",
      "parents": [
        "2ae1c189a64372386ee44b37d97b056517bbf30c"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Tue Nov 03 17:19:19 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 09:19:19 2026 -0800"
      },
      "message": "[manual_evals] Add CI job that checks each skill as a standalone package (#733)"
    },
    {
      "commit": "2ae1c189a64372386ee44b37d97b056517bbf30c",
      "tree": "8d4dfb77b16320a7de7893f51e91bfa7d4c88a5c",
      "parents": [
        "129f2c340cc3a91d4748a79f2c7480026f3a61b9"
      ],
      "author": {
        "name": "Moritz",
        "email": "27859082+mosuem@users.noreply.github.com",
        "time": "Tue Nov 03 18:18:01 2026 +0100"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 09:18:01 2026 -0800"
      },
      "message": "Migrate to ecosystem health publish check and setup-dart publish workflow (#729)"
    },
    {
      "commit": "129f2c340cc3a91d4748a79f2c7480026f3a61b9",
      "tree": "886bb175baff7b3a6340452d0ebf4f6aa6f7a887",
      "parents": [
        "7cd1fc950ce9ceee1c49b3fea41caf610890202e"
      ],
      "author": {
        "name": "John Ryan",
        "email": "ryjohn@google.com",
        "time": "Tue Nov 03 17:17:01 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Nov 03 09:17:01 2026 -0800"
      },
      "message": "Add package:skills_lint to manual_evals (#734)"
    },
    {
      "commit": "7cd1fc950ce9ceee1c49b3fea41caf610890202e",
      "tree": "670a463c6f798e0c2b6e467b9b322cca5b8e1eca",
      "parents": [
        "e14a55effe59621c316dc3b9de044702902c7121"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Mon Nov 02 17:01:25 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Nov 02 09:01:25 2026 -0800"
      },
      "message": "[manual_evals] Bump SDK constraint to ^3.13.0 (#725)"
    },
    {
      "commit": "e14a55effe59621c316dc3b9de044702902c7121",
      "tree": "2ecb0ffa7c5d09443a9c77744567dba9dfa6b720",
      "parents": [
        "31b179a7ef0211858853a12f6a7f607a6124a370"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Nov 02 08:14:02 2026 -0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Nov 02 08:14:02 2026 -0800"
      },
      "message": "Bump the github-actions group with 3 updates (#730)\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "31b179a7ef0211858853a12f6a7f607a6124a370",
      "tree": "1b6ce5792f05de9ebb5df281a40f9188cb96676b",
      "parents": [
        "bdf8ad8f6a343064bb03812a8a34ac1347e1b763"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Fri Oct 30 16:02:11 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 30 09:02:11 2026 -0700"
      },
      "message": "[manual_evals] Mark package as publish_to: none (#726)"
    },
    {
      "commit": "bdf8ad8f6a343064bb03812a8a34ac1347e1b763",
      "tree": "307cb5210b0b3ab4ad0eeb9ee7439a4fe45a7d5b",
      "parents": [
        "441dfc6d4ebd574f83216716e4ab80959f638fcd"
      ],
      "author": {
        "name": "John Ryan",
        "email": "ryjohn@google.com",
        "time": "Thu Oct 29 13:49:38 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 29 13:49:38 2026 -0700"
      },
      "message": "Add manual_evals package with example skill (#723)"
    },
    {
      "commit": "441dfc6d4ebd574f83216716e4ab80959f638fcd",
      "tree": "41a6564496a4a78897e5021139556e25561461f2",
      "parents": [
        "4581da98f69afa3b1d15c0559392134d03986cf5"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Oct 27 14:02:57 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 27 14:02:57 2026 -0700"
      },
      "message": "[dart_mcp_server] Make DTD connection flow easier for agents to follow (#722)\n\n## Why\n\nWe\u0027ve been seeing a growing number of `dtd` tool failures with the `noActiveDebugSession` failure reason, mostly from the `listConnectedApps` command. There were two causes:\n\n1. **A real bug:** `listConnectedApps` returned `noActiveDebugSession` whenever the local cache of VM services was empty. It checked this *before* refreshing the app list from DTD. So an agent that followed the documented flow (`listDtdUris` → `connect` → `listConnectedApps`) still got an error if it connected before the app was running, or to a DTD instance that had no apps.\n2. **Vague guidance:** when no DTD was connected, the error only said \"use the `dtd` tool… read the schema\". It didn\u0027t tell the agent the exact calls to make.\n\nLive testing also showed that the MCP server is often **shared across agent conversations**. So DTD connections made in one conversation stay active in the next. Agents tend to call `connect` on every DTD instance in parallel, and then hit `dtdAlreadyConnected` errors for instances that an earlier session had already connected to.\n\n## Changes\n\n- **`listConnectedApps`**: it only errors if no DTD is connected and there are no standalone apps. Otherwise it always refreshes from DTD. An empty app list is now a successful result, with guidance: start the app, or find and connect to the DTD instance it\u0027s on.\n- **\"Not connected\" errors** (from `listConnectedApps`, `hot_reload`, `get_runtime_errors`, `widget_inspector`, etc.):\n  - When no DTD is connected, the error gives numbered steps, including the literal `connect` call.\n  - It **includes the `dart tooling-daemon --list` output inline**, so the agent can connect on its next call without a separate `listDtdUris` round trip.\n  - This case now reports `dtdNotConnected` instead of `noActiveDebugSession`, so analytics can tell \"never connected\" apart from \"connected but no app\".\n- **`connect` is idempotent**: connecting to an already connected DTD instance succeeds and returns its current apps. `listDtdUris` notes which instances are already connected.\n- **`dtd` tool description and server instructions**:\n  - Both now spell out the required workflow as numbered steps, and say that a DTD connection is required for all app tools.\n  - The command enum is now ordered `listDtdUris`, `connect`, `listConnectedApps`, `disconnect`.\n- **`launch_app` result**: it tells the agent to connect to the DTD URI it printed.\n- Bumped the version to `1.2.2-wip` and added a CHANGELOG entry. Fixed a stale entrypoint path in `GEMINI.md`.\n\nNo new tool was needed.\n\n## Evals\n\nI compiled the server to an AOT executable, pointed an agent MCP config at it, and ran fresh agents (each with no prior context) against a real `food_analyzer` Flutter app on a Pixel 10a. There were 2–4 DTD instances running: a few IDE/code-server instances and a `flutter test` run. The server is shared across conversations, so I reset its DTD connections before each run to control the starting state. Each agent was asked to report a trace of its tool calls.\n\n| Run | Starting state | Prompt | Tool calls | Errors |\n|---|---|---|---|---|\n| A | No DTD connected | \"I have a Flutter app running. Which app is it, and does it have runtime errors?\" | `listDtdUris` → `connect` ×4 → `listConnectedApps` → `get_runtime_errors` ×2 | none |\n| B | No DTD connected | \"Hot reload my running flutter app please.\" | `listDtdUris` → `connect` ×4 → `hot_reload` | none |\n| C | No DTD connected | Told to call `listConnectedApps` **first**, then inspect the widget tree | `listConnectedApps` (error) → `connect` ×2 using URIs from the error → `widget_inspector` | only the expected first call |\n| D | Connected only to a DTD with no apps | \"Check my running Flutter app for any runtime errors.\" | `listDtdUris` → `connect` ×4 → `listConnectedApps` → `get_runtime_errors` ×2 | **`dtdAlreadyConnected`** (before the idempotent `connect` change) |\n| D2 | Same as D, with the idempotent `connect` change | Same as D | `listDtdUris` (noted the existing connection) → `listConnectedApps` (empty, not an error) → `connect` to the right DTD → `get_runtime_errors` | none |\n\nTakeaways:\n- With the new description and instructions, every agent called `listDtdUris` before trying anything else, unless told not to.\n- When an agent did skip ahead (C), the new error message got it on track in a single step, because the DTD list was included inline.\n- Run D found the `dtdAlreadyConnected` problem caused by the shared server. Run D2 confirmed the fix.\n- None of the runs hit `noActiveDebugSession`.\n\n## Tests\n\n- New tests:\n  - `listConnectedApps` with no running apps returns a non-error result with guidance.\n  - `connect` to an already connected DTD succeeds, and `listDtdUris` reports the existing connection.\n  - With no DTD connected, `listConnectedApps` and `hot_reload` return the connect steps and include the available DTD URIs.\n- Updated the expected messages in existing tests: the VM service disconnect test and the `launch_app` output tests."
    },
    {
      "commit": "4581da98f69afa3b1d15c0559392134d03986cf5",
      "tree": "470efe03cac5a72d13a9f785f3f87ca2d6d69a35",
      "parents": [
        "43507d4e336cbc3aa3e3fb33a9c1d162022a4c32"
      ],
      "author": {
        "name": "Kevin Moore",
        "email": "kevmoo@users.noreply.github.com",
        "time": "Fri Oct 23 11:13:31 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 23 11:13:31 2026 -0700"
      },
      "message": "Tighten pull_request_label workflow permissions (#711)"
    },
    {
      "commit": "43507d4e336cbc3aa3e3fb33a9c1d162022a4c32",
      "tree": "6b7e9073806c498d51139cb0063c21e262cdb167",
      "parents": [
        "af5923ec0d4a2edee90adb1c1567fb0af94fc84f"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Oct 20 14:52:32 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 20 14:52:32 2026 -0700"
      },
      "message": "Add repository-specific review rules to the Gemini style guide (#707)\n\n## Summary\n\nAdds a \"Repository-specific review rules\" section to the Gemini style guide, built from what human reviewers repeatedly asked for (or pushed back on) in this repo\u0027s PRs over the last 90 days (124 PRs, 216 human review comments, 122 bot inline comments). Also drops \"import violations\" from the `[MUST-FIX]` definition, since no import rules are defined anywhere.\n\n- **Spec grounding:** check constants, defaults, optionality and version-specific behavior against the MCP spec; ask for spec links. *Medium; replay: helps.*\n- **Configurable limits:** hard-coded limits that aren\u0027t from the spec should be configurable. *Medium; replay: helps.*\n- **Documentation:** doc comments on new public API; high-level comments on complex private code; explain examples. *Medium; replay: helps.*\n- **Extension types:** `as`/`is` on `dart_mcp` API types aren\u0027t safety checks. *Medium; replay: no effect (couldn\u0027t reproduce the bot\u0027s mistake).*\n- **JSON typing:** `Map\u003cString, Object?\u003e`, `Object?` over `dynamic`, promotion over `as` + `!`. *Medium; replay: helps (weak).*\n- **Copies and lookups:** avoid needless map copies and full scans; don\u0027t drop unknown fields. *Medium; replay: helps.*\n- **LLM-facing text:** don\u0027t ask to pad tool descriptions or skill bodies. *Medium; replay: no effect (couldn\u0027t reproduce the bot\u0027s mistake).*\n- **`TestEnvironment` teardown:** it already registers `addTearDown(shutdown)`. *Low; replay: helps.*\n\n**Confidence: Medium overall** (evidence-based; replays on motivating PRs only, apart from one evaluation noted below) · Affects: bot (`.gemini/styleguide.md`) · Type: edit\n\n## Change\n\nRemoves \"import violations\" from `[MUST-FIX]` and appends section 4 with the eight rules above. Rules are inlined (not linked) because the review bot most likely reads only its guidance files\u0027 text.\n\n## Evidence\n\n| Rule | Source | What it shows | Who (role) |\n|---|---|---|---|\n| Spec grounding | #580, #596, #629, #632, #635, #636, #679 (14 comments, 12 PRs) | asks for spec links; checks optionality/nullability against the schema. Bot also made wrong spec claims on #627, #629 | jakemac53 (maintainer), single-reviewer |\n| Configurable limits | #632, #635, #655 | \"make this configurable, keep the default\" | jakemac53 (maintainer), single-reviewer |\n| Documentation | #632, #638, #655, #676, #678, #679 (~11 comments) | asks for API docs and high-level comments | jakemac53 (maintainer), single-reviewer |\n| Extension types | #699, #676, #654 (bot rebutted); #655 | casts to extension types never fail; `is` can\u0027t split unions; examples shouldn\u0027t use `is` checks | jakemac53 (maintainer), Yusufihsangorgel (PR author) |\n| JSON typing | #528, #531, #655 (9 comments) | `Object?` not `dynamic`, `Map\u003cString, Object?\u003e`, promotion over casts | jakemac53 (maintainer), single-reviewer |\n| Copies and lookups | #531, #568, #604, #655, #678, #679, #682 (9 comments, 2 reviewers) | needless copies and full scans; rebuilding drops fields | jakemac53, kenzieschmoll (maintainers) |\n| LLM-facing text | #615; #578 (bot rebutted) | padding skill bodies/tool descriptions wastes tokens | jakemac53 (maintainer) |\n| TestEnvironment | #637, #652 (5 bot comments rebutted) | bot asked for teardown `TestEnvironment` already does | Yusufihsangorgel (PR author) |\n\n## Replay results\n\nSimulated reviews of each PR diff with the current style guide and with the rule added (model: agent default, 1 run per version, motivating PRs plus 1-2 unrelated or near-miss PRs):\n\n| Rule | Motivating PRs: current → with rule | Unrelated PRs (false flags) |\n|---|---|---|\n| Spec grounding | 0/2 → 2/2 | 0/2 → 0/2 |\n| Documentation | 1/2 → 2/2 | 0/2 → 0/2 |\n| Extension types | 0/2 → 0/2 (simulator didn\u0027t repeat the mistake) | 0/1 → 0/1 |\n| JSON typing | 0/2 → 1/2 | 0/2 → 0/2 |\n| Copies and lookups | 1/3 → 3/3 | 0/2 → 0/2 |\n| Configurable limits | 0/3 → 3/3 (#571, whose spec-defined constants shouldn\u0027t be configurable, wasn\u0027t flagged) | 0/2 → 0/2 |\n| LLM-facing text | 0/1 → 0/1 (simulator didn\u0027t repeat the mistake) | 0/1 → 0/1 |\n| TestEnvironment | 1/2 → 0/2 wrong teardown requests | 0/1 → 0/1 |\n\nA broader change narrowing `[MUST-FIX]` to \"verified, concrete failures\" was also evaluated (3 runs × 10 PRs, blind judge). It showed no effect, because the simulator never reproduced the bot\u0027s wrong MUST-FIX claims, so it isn\u0027t included. Only the undefined \"import violations\" wording is removed.\n\n## Limitations\n\n- Replays simulate the review bot with a fixed prompt; they aren\u0027t Gemini Code Assist itself.\n- Small samples (1 run per version on 3-5 PRs per rule); motivating PRs were used to write the rules.\n- Most evidence comes from one maintainer\u0027s reviews (labeled single-reviewer above).\n\n---\n*Prepared with `review-tuner` (agent-assisted evidence and replay workflow) and reviewed by @jakemac53.*"
    },
    {
      "commit": "af5923ec0d4a2edee90adb1c1567fb0af94fc84f",
      "tree": "6d80183e20fe0f3bed1e870aa8ce7270899306cd",
      "parents": [
        "7cca3a120d404c942754db4e6baeefda6768d925"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Fri Oct 16 21:42:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 14:42:57 2026 -0700"
      },
      "message": "[dart_mcp_server] Prepare to release 1.2.1 (#704)\n\nPrepare for new release:\n\n## 1.2.1\n\n- When the Flutter SDK cannot be found, the error now says which Dart SDK the\n  server is using and where that path came from (an explicit path such as\n  `--dart-sdk`, `DART_ROOT`, `DART_SDK`, or the running executable), and\n  mentions `--flutter-sdk`.\n- Fix the `--enable` help text, which incorrectly said that all features are\n  enabled by default. Document how to enable tools that are disabled by default\n  in the README.\n- Require `package:unified_analytics` `^8.1.0`."
    },
    {
      "commit": "7cca3a120d404c942754db4e6baeefda6768d925",
      "tree": "5c3efa0a61bc173770079f4d357156012189ae29",
      "parents": [
        "de6b4727771988d5c885dcebbffa5367a0bea16c"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Fri Oct 16 20:03:30 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 13:03:30 2026 -0700"
      },
      "message": "[skills] Prepare to release 1.0.4 (#705)\n\n- Require `package:unified_analytics` `^8.1.0`."
    },
    {
      "commit": "de6b4727771988d5c885dcebbffa5367a0bea16c",
      "tree": "bcc062830cbd07e317783fd81450d1f01f102c55",
      "parents": [
        "daeee1e116d689dab4ce63ad023d424e1d297615"
      ],
      "author": {
        "name": "Phil Quitslund",
        "email": "pq@users.noreply.github.com",
        "time": "Fri Oct 16 20:01:55 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 13:01:55 2026 -0700"
      },
      "message": "[dart_mcp_server] Ignore material.dart deprecation in counter_app fixture (#706)\n\nFlutter 3.47+ deprecates `package:flutter/material.dart` in favor of `package:material_ui`, which fails \u0027dart analyze --fatal-infos\u0027 on the beta and master channels. Migrating isn\u0027t possible yet because f`lutter_driver`\u0027s `ByTooltipMessage` finder only matches the framework\u0027s `Tooltip` class, which breaks the dtd_test Flutter driver test.\n\nUnblocks: #704 \n\n\n---\n\n- [x] I’ve reviewed the contributor guide and applied the relevant portions to this PR.\n\n\u003cdetails\u003e\n  \u003csummary\u003eContribution guidelines:\u003c/summary\u003e\u003cbr\u003e\n\n- See our [contributor guide](https://github.com/dart-lang/.github/blob/main/CONTRIBUTING.md) for general expectations for PRs.\n- Larger or significant changes should be discussed in an issue before creating a PR.\n- Contributions to our repos should follow the [Dart style guide](https://dart.dev/guides/language/effective-dart) and use `dart format`.\n- Most changes should add an entry to the changelog and may need to [rev the pubspec package version](https://github.com/dart-lang/sdk/blob/main/docs/External-Package-Maintenance.md#making-a-change).\n- Changes to packages require [corresponding tests](https://github.com/dart-lang/.github/blob/main/CONTRIBUTING.md#Testing).\n\nMany Dart repos have a weekly cadence for reviewing PRs - please allow for some latency before initial review feedback.\n\n**Note**: The Dart team is trialing Gemini Code Assist. Don\u0027t take its comments as final Dart team feedback. Use the suggestions if they\u0027re helpful; otherwise, wait for a human reviewer.\n\n\u003c/details\u003e"
    },
    {
      "commit": "daeee1e116d689dab4ce63ad023d424e1d297615",
      "tree": "998797ce54b98f013daa0f7d83c82751d5d582b6",
      "parents": [
        "29be0e4a0830de673c9169e34a3906270fa1be78"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Wed Oct 14 13:45:33 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:45:33 2026 +0000"
      },
      "message": "Fix broken GEMINI.md link in the Gemini style guide (#703)\n\n## Summary\n\n- **Fix the style guide\u0027s broken `GEMINI.md` link.** `.gemini/styleguide.md` links `[GEMINI.md](GEMINI.md)`, which resolves relative to `.gemini/` and points at the nonexistent `.gemini/GEMINI.md`. The file is at the repo root.\n\n**Confidence: High (by inspection)** · Affects: bot (`.gemini/styleguide.md`) · Type: fix\n\n## Change\n\nPoints the link at `../GEMINI.md` and also links `pkgs/skills/AGENTS.md`, the other agent guidance file. It drops the \"for additional rules\" wording: the review bot most likely reads only the text of its guidance files and doesn\u0027t follow links, so rules that live only in linked files are invisible to it. Follow-up PRs will propose inlining specific review rules into the style guide itself, each backed by review evidence.\n\n## Evidence\n\n| Source | What it shows | Who (role) |\n|---|---|---|\n| `.gemini/styleguide.md:35` | Relative link `GEMINI.md` resolves to `.gemini/GEMINI.md`, which doesn\u0027t exist; `GEMINI.md` is at the repo root | deterministic check |\n\n## Replay results\n\nNot replayed (propose mode); confidence is evidence-only.\n\n## Limitations\n\n- The link change doesn\u0027t change what the bot sees if it doesn\u0027t follow links; the review rules it needs have to be inlined (follow-up PRs).\n\n---\n*Prepared with `review-tuner` (agent-assisted evidence and replay workflow) and reviewed by @jakemac53.*"
    },
    {
      "commit": "29be0e4a0830de673c9169e34a3906270fa1be78",
      "tree": "aec52f2e71c7c640044bb49b243cfa6c371522b8",
      "parents": [
        "4a9333404c996b57b2b076eb4cf0856cb7a212b4"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Oct 14 17:41:06 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 07:41:06 2026 -0700"
      },
      "message": "add a client helper for subscription streams (#679)\n\nAdds `ServerConnection.listen`, the client half of the subscription streams the server has served since #636. A handle comes back right away, reports the filter the server agreed to, and routes each notification to the subscription that opened it. Closing one subscription ends only that stream. Over stdio it sends `notifications/cancelled` for that request, over Streamable HTTP it drops the SSE response. A cancellation arriving for one subscription ends that one and leaves the connection alone.\n\nThree helper names here are this package\u0027s own and not the schema\u0027s. Reading the outgoing request ID off the channel sink leaves `package:json_rpc_2` untouched.\n\nTracked in #668."
    },
    {
      "commit": "4a9333404c996b57b2b076eb4cf0856cb7a212b4",
      "tree": "3bd46d3ada21f82498f273e6d9985c90e627ee4c",
      "parents": [
        "60a4b185d52e9f9cb59dc1a05ef636556a539d85"
      ],
      "author": {
        "name": "Manveer Singh",
        "email": "64741771+Manveer1999@users.noreply.github.com",
        "time": "Wed Oct 14 03:00:14 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 13 14:30:14 2026 -0700"
      },
      "message": "[dart_mcp_server] Say which Dart SDK was used when Flutter is not found (#702)\n\nFixes #701.\n\nWhen the Flutter SDK cannot be found, the error now says which Dart SDK the server is using and where that path came from, as suggested in the issue. Example, for a server started with a standalone Dart SDK:\n\n```\nFlutter SDK location unknown. The server is using the Dart SDK at /opt/dart-sdk, from the executable running the server (/opt/dart-sdk/bin/dart), which is not inside a Flutter SDK. To work on Flutter projects, start the server with the `dart` executable from a Flutter SDK (\u003cflutter\u003e/bin/dart), pass --flutter-sdk, or set the FLUTTER_SDK environment variable.\n```\n\n- `Sdk` gains an optional `dartSdkSource`, set by `Sdk.find`: the `--dart-sdk` argument, `DART_ROOT`, `DART_SDK`, or the running executable.\n- The message also mentions `--flutter-sdk`, which the old text did not.\n- Tests for each source and for an `Sdk` with nothing known. CHANGELOG entry under 1.2.1-wip.\n\nI used Claude Code while writing this change and reviewed and tested it myself."
    },
    {
      "commit": "60a4b185d52e9f9cb59dc1a05ef636556a539d85",
      "tree": "dcf95e52dc5b6c0905f166bfedc2846556a6aa90",
      "parents": [
        "d55ba6eab216a0411dd4802f983bf1d1fd06e22a"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Oct 07 21:26:41 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 11:26:41 2026 -0700"
      },
      "message": "add a client helper that initializes a server across versions (#690)\n\nPart of #688.\n\nThis adds `ServerConnection.initializeAcrossVersions` for the\n[compatibility procedure](https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning#backward-compatibility-with-initialization-based-versions).\nIt takes the existing `MCPServerInitialization`, moved into `api/`, and returns\na new `InitializedServer` in case `DiscoverResult` later gains required fields.\nIts probe waits 10 seconds by default.\n\nBoth `discover` and `initialize` now document what they do on a version\nmismatch. Deprecating them is left for a follow-up."
    },
    {
      "commit": "d55ba6eab216a0411dd4802f983bf1d1fd06e22a",
      "tree": "dd86d08132ae5303781bd4abda0d78707281e5e1",
      "parents": [
        "c9b806dc55f7128654fdc0ffa523f22ed69dafa0"
      ],
      "author": {
        "name": "Nate Bosch",
        "email": "nbosch1@gmail.com",
        "time": "Wed Oct 07 10:32:39 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 10:32:39 2026 -0700"
      },
      "message": "[dart_mcp_server] Fix docs claiming all features are enabled by default (#700)\n\nThe `--enable` help text said \"All features are always enabled by default\",\nbut several tools set `enabledByDefault \u003d false` and are only registered when\nenabled explicitly by name or category. Since `--help` also lists every tool\nname as an allowed value, this made it look like those tools were available\nwithout any configuration.\n\n- Reword the `--enable` help text to say that some features are disabled by\n  default and must be enabled by name or category, and point to the README.\n- Add a section to the README Tools docs describing `--enable` and\n  `--disable`, with an example enabling the `flutter_app_lifecycle` category,\n  and a summary of the precedence rules.\n- Rename the generated tools table column from \"Enabled\" to \"Enabled by\n  default\" in both `tool/update_readme.dart` and the README.\n- Bump to 1.2.1-wip and add a changelog entry."
    },
    {
      "commit": "c9b806dc55f7128654fdc0ffa523f22ed69dafa0",
      "tree": "7bf93b16879ef8a1c0a5e90c878df9ceac9a98b9",
      "parents": [
        "9492b5c81f7a5ad5eab8ea0ade6bf18fe0f5422f"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Wed Oct 07 08:30:39 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 07 08:30:39 2026 -0700"
      },
      "message": "[dart_mcp_server] Resolve and list services registered by VM service clients (#697)\n\nServices registered by VM service clients (via `registerService`) can only be called by their namespaced method name, e.g. `s1.myRegisteredMethod`, which is announced in the `ServiceRegistered` event and depends on the order clients connected. Agents had no way to discover that name through the `vm_service` tool.\n\n### Changes\n\n- Track every `ServiceRegistered` registration per service name (method + human readable alias), including multiple clients registering the same name, and only drop them on the matching `ServiceUnregistered` event.\n- `vm_service` `callMethod` now accepts the name a service was registered with and calls its namespaced method. If more than one client registered that name, the call fails with a list of the method names and their aliases to choose from. Namespaced names and other methods are passed through unchanged.\n- Add a `listRegisteredServices` command to the `vm_service` tool that returns `{service, method, alias}` for each registration.\n- Prepare release 1.2.0 (pubspec, server version, CHANGELOG, generated README).\n\n### Testing\n\nAdded an integration test in `dtd_test.dart` with two real VM service clients registering the same service: calls by service name, listing, the ambiguity error, calling a specific client by method name, and resolution after one client disconnects."
    },
    {
      "commit": "9492b5c81f7a5ad5eab8ea0ade6bf18fe0f5422f",
      "tree": "18f1d894eb45e9f071d8ab4a2015262d0e3598e6",
      "parents": [
        "d060543c913e417dca2c4ad0f96b62bbb0770ae2"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Oct 06 11:08:34 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 06 11:08:34 2026 -0700"
      },
      "message": "[dart_mcp_server] Stop sending untrusted client strings to analytics (#699)\n\nFixes #698\n\nTool names, prompt names, `command` arguments, and the client info all come directly from the MCP client. Bad values in them can break our analytics dashboards or cause other undesirable effects.\n\n### Unknown tool names\n\nThese are already dropped as of 1.1.0 (#539): `dart_mcp` rejects calls to unregistered tools before our analytics wrapper ever runs. Versions \u003c\u003d 1.0.2 logged the raw name of every call, so we will keep seeing some of these from older installs. This PR adds a regression test for it.\n\n### Changes\n\n- **Tool commands**: the `command` argument is only appended to the tool name when it is one of the values in the tool\u0027s `enum`. Otherwise we log the bare tool name, and invalid commands are reported as `failureReason: noSuchCommand`.\n- **Prompt names**: only names from `PromptNames` (the prompts this server sets up) are logged. Requests for any other prompt omit `name` and report `failureReason: noSuchPrompt`.\n- **Client info**: `client`, `clientVersion`, and `agentPlugin` are sanitized. `${...}` interpolations and any remaining `$` characters are removed, control characters are collapsed to spaces, and values are trimmed and capped at 100 characters. All events, including the DTD `readResource` event, are now created through a shared `createDartMCPEvent` helper.\n- Guard tests make sure every tool with a `command` parameter declares an `enum`, and every registered prompt is listed in `PromptNames`.\n- Bumps the version to `1.1.3-dev`.\n\n### Dashboard-visible changes\n\n- Invalid commands now report `noSuchCommand` instead of `argumentError`.\n- `getPrompt` events may omit `name`, and can include a `failureReason`."
    },
    {
      "commit": "d060543c913e417dca2c4ad0f96b62bbb0770ae2",
      "tree": "1c4d79a5ed5efb1006b1aa121225baedf09d81ec",
      "parents": [
        "d590da805908dd6c0f7051a15ec564207284f65d"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Oct 02 10:01:21 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 02 10:01:21 2026 -0700"
      },
      "message": "[skills] Don\u0027t require running from a package root (#694)\n\nSkills from git repos don\u0027t depend on any Dart packages, so the CLI shouldn\u0027t require running from a directory with a `pubspec.yaml`. This matters for `add`, and also for `get`, which is used to update skills from git repos.\n\n- `WorkspaceResolver.resolve` now returns a `WorkspaceLayout` with no packages, rooted at the target directory, when no Dart packages are found. Previously it threw a `StateError`.\n- `getSkills` (used by `add` and `get`) skips package resolution when there are no packages. It logs `No Dart or Flutter project found in \u003cdir\u003e, only installing skills from git repos.` unless only git sources were requested anyway, as with `add`.\n- `create` still needs a package, so it now throws a clear `UsageException` instead of a `firstWhere` `StateError`.\n- `list`, `remove` and `prune` also work outside a project without other changes. Outside a project, `prune` treats every package-based skill as unused, since there are no dependencies.\n- Tests: `add` (local and `--global`) and `get` from a directory with no pubspec, the `create` error, and an updated resolver test.\n- Updates `AGENTS.md` and bumps the version to 1.0.3 with a changelog entry.\n\nFixes #693"
    },
    {
      "commit": "d590da805908dd6c0f7051a15ec564207284f65d",
      "tree": "e4d36b4328c5fd2fa89dedded7358ff3839b7c5d",
      "parents": [
        "cdf9ad1cb50f148f8dd332eaea765e79e5d9b475"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 01 10:33:52 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 01 10:33:52 2026 -0700"
      },
      "message": "Bump the github-actions group with 3 updates (#695)\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "cdf9ad1cb50f148f8dd332eaea765e79e5d9b475",
      "tree": "af2dfece972eabef2be7b114aa25f7969ac9790f",
      "parents": [
        "4ea9e774b687d7292fd89aa340e622d67dc082c8"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 23 23:24:00 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 23 13:24:00 2026 -0700"
      },
      "message": "keep a cancelled request off the wire (#678)\n\nA `notifications/cancelled` for a request in flight here takes it off the wire. Its response, its progress and its handler\u0027s notifications all stop. Handlers run to the end, since stopping early is a SHOULD. A handler that wants to return early reads `MCPBase.captureIncomingRequestActivity`. Every valid notification reaches `MCPBase.cancellations` for a subclass to log.\n\nA cancelled `subscriptions/listen` ends its subscription and releases the resource updates it armed. Progress goes out only for a token that a request still in flight declared.\n\nPart of #37. A follow-up carries the listen half."
    },
    {
      "commit": "4ea9e774b687d7292fd89aa340e622d67dc082c8",
      "tree": "ce0867ce0bd5b01f500c9090f8d1ab5c677f2827",
      "parents": [
        "79a86be8e3664cf120a1df40b14244e2e1e22f8e"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 22 22:38:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 22 12:38:35 2026 -0700"
      },
      "message": "name the field when sampling content is missing (#689)\n\nFollow-up to [this thread](https://github.com/dart-lang/ai/pull/685#discussion_r4063946725) on #685.\n\nA `SamplingMessage` without `content` now throws an `ArgumentError` naming the field, instead of a `TypeError` from the cast. Its wording follows the other missing-field checks under `lib/src/api/`."
    },
    {
      "commit": "79a86be8e3664cf120a1df40b14244e2e1e22f8e",
      "tree": "c6b75be3eb89e40136cb21c6744cc76530b1b084",
      "parents": [
        "842af85689ca1f6ddd092a76998c4cb54d820c46"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 22 20:53:45 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 22 10:53:45 2026 -0700"
      },
      "message": "add a streamable http client example (#671)\n\nAdds a client to pair with `example/streamable_http_server.dart`. It takes the URL the server prints, discovers the server, lists its tools, calls `greet` and prints the progress notification. The example readme now describes the pair instead of the curl command.\n\nPart of https://github.com/dart-lang/ai/issues/668"
    },
    {
      "commit": "842af85689ca1f6ddd092a76998c4cb54d820c46",
      "tree": "7b329ad22cdb88cfafa864ae1bd5e3d6254232aa",
      "parents": [
        "681799ef3bd2944c689fa0bea612ddafa4e1db3f"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Mon Sep 21 15:21:11 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 15:21:11 2026 -0700"
      },
      "message": "minor cleanup of internal skills, mark them internal and fix them to follow the spec for names (#687)"
    },
    {
      "commit": "681799ef3bd2944c689fa0bea612ddafa4e1db3f",
      "tree": "aa4acc592f8f2d49d646ec1cf3340c9893d76288",
      "parents": [
        "43e1047ecc4a9e763de1516963878e9c1b598cf5"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Mon Sep 21 15:15:45 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 15:15:45 2026 -0700"
      },
      "message": "[skills] Fix pub.dev score issues and prepare 1.0.2 (#686)\n\n`skills` 1.0.1 is at **140/160** on [pub.dev](https://pub.dev/packages/skills/score), losing 10 points in each of two checks. This fixes both and bumps to 1.0.2.\n\n### Package has an example (0/10)\n\nThere was no `example/` directory. Added `example/README.md` walking through the common invocations, split into \"using skills in your project\" and \"shipping skills with your own package\".\n\nA markdown example is the right shape here — `skills` is a CLI with no meaningful Dart API to demo — and `example/README.md` is the first entry in pana\u0027s [candidate list](https://github.com/dart-lang/pana/blob/master/lib/src/maintenance.dart).\n\n### All of the package dependencies are supported in the latest version (0/10)\n\n`cli_util: ^0.5.1` excluded the latest `0.6.0`. Widened to `\u003e\u003d0.5.1 \u003c0.7.0` rather than bumping to `^0.6.0`: the sole breaking change in 0.6.0 was `sdkPath` becoming nullable, which this package never touches (it only uses `BaseDirectories`, `cli_components`, and `windows_compatibility`), so keeping the 0.5.1 lower bound costs nothing and preserves the \"compatible with dependency constraint lower bounds\" points.\n\n### Verification\n\n- `dart pub upgrade` resolves to `cli_util 0.6.0`; `dart format` and `dart analyze --fatal-infos` are clean; all 242 tests pass.\n- Local `pana --no-dartdoc` reports **150/150**, all five sections passed. That flag skips the dartdoc section, which already scores 10/10 on pub.dev — so this should land at 160/160.\n- `dart pub publish --dry-run` confirms `example/README.md` is included in the archive.\n\n### Note\n\n`dart_mcp_server` pins `cli_util: ^0.5.0` and will have the same \"not latest\" deduction. Left alone here to keep this PR scoped to `skills`."
    },
    {
      "commit": "43e1047ecc4a9e763de1516963878e9c1b598cf5",
      "tree": "9bc2a8af84a3fa2d88d093d62194521cbbb91d45",
      "parents": [
        "06a2c23210817ba0c3dea44dd3029fcaf5ee4c86"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 22 00:25:09 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 14:25:09 2026 -0700"
      },
      "message": "walk the pages of each list request (#682)\n\nA client that wants every tool from a server that pages its list has to thread the cursor by hand. The fixture under `tool/` drops `nextCursor` today. Methods named `listAllTools`, `listAllResources`, `listAllResourceTemplates` and `listAllPrompts` now walk the pages and yield the items as a `Stream`. Each single-page method stays byte-identical. A default 64-page bound throws instead of walking forever, while passing `null` lifts it. Tests cover the cursor threading, the bound, the argument check and an empty page.\n\nPart of #28."
    },
    {
      "commit": "06a2c23210817ba0c3dea44dd3029fcaf5ee4c86",
      "tree": "6edef525af32d9d4c61722e0ef2f6da710a6ec97",
      "parents": [
        "4844972077e88e20243fd86f026bd10baadc70e6"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 23:39:21 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 13:39:21 2026 -0700"
      },
      "message": "add a multi-version client and server (#676)\n\nAdds paired client and server examples around a single `greet` tool. Its server uses stdio by default and serves the tool over Streamable HTTP with `--http`. Each path asks for a name before returning a greeting, and the stdio path translates that request for an older revision. The shim #655 landed does that translation. Over `--http` the result goes out as it is.\n\nPart of #668"
    },
    {
      "commit": "4844972077e88e20243fd86f026bd10baadc70e6",
      "tree": "f01e6d497a8eecff73637cc4bbe85899134565a7",
      "parents": [
        "9d53c186ae2400c5122a3115145e55af801331ce"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 19:01:42 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 09:01:42 2026 -0700"
      },
      "message": "read one block or a list under sampling content (#685)\n\n#672 said array-valued message content wanted its own change. This is it. In the schema both `SamplingMessage.content` and `CreateMessageResult.content` take five block types or an array of them. The getter cast straight to one block, and a list on the wire threw. Both shapes now read as a list, with one block still going out as that block."
    },
    {
      "commit": "9d53c186ae2400c5122a3115145e55af801331ce",
      "tree": "ec6974dca29d0cab2ee35ed0dde7e894f2e4a582",
      "parents": [
        "6166c86f19124a9c217c6266559e98395ee9c023"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 19:01:21 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 09:01:21 2026 -0700"
      },
      "message": "answer 415 with an invalid request error (#684)\n\nIn the schema, `HeaderMismatch` carries `400 Bad Request`. This branch answers 415. A revision that requires `Mcp-Method`, `Mcp-Name` and `MCP-Protocol-Version` does not count a media type among them. Elsewhere in this file that code always pairs with 400. An oversized body already gets a generic invalid request error with its own 413, and this branch now matches it. Since this handler landed after 0.5.2, its changelog line states behaviour instead of a change."
    },
    {
      "commit": "6166c86f19124a9c217c6266559e98395ee9c023",
      "tree": "793a4304b700cc61aebd61eca5009d719a6fa540",
      "parents": [
        "47f4e3146bec18651d6a950ca041f95c0ed7d70d"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 21 18:18:12 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 21 08:18:12 2026 -0700"
      },
      "message": "add DEVELOPING.md for package:dart_mcp (#673)\n\nA short guide for working on the package. It covers where the schema files live, the checks CI runs, the SDK the format check needs, the conformance fixtures and the changelog convention. I named it DEVELOPING.md, not a second CONTRIBUTING.md, since the root already has one, and it links there. The library comment in api.dart still pointed at the 2025-06-18 schema file. It points at the schema directory now.\n\nCloses #20."
    },
    {
      "commit": "47f4e3146bec18651d6a950ca041f95c0ed7d70d",
      "tree": "6b55e6252c4fb04132e5d4533ae127f8cec9c61f",
      "parents": [
        "6c1647673bc75ded46a9bdbf500b05a9c3483169"
      ],
      "author": {
        "name": "Keerti Parthasarathy",
        "email": "keertip@users.noreply.github.com",
        "time": "Fri Sep 18 11:13:59 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 18 11:13:59 2026 -0700"
      },
      "message": "[dart_mcp_server] Publish version 1.1.2 (#683)\n\nFor publish update version string in\n - CHANGELOG.md\n - pubspec.yaml\n - lib/src/server.dart"
    },
    {
      "commit": "6c1647673bc75ded46a9bdbf500b05a9c3483169",
      "tree": "fe75d1fb6abb1efc7b078754301e21de3e68e1ea",
      "parents": [
        "7cb4308ee241e35309777eb31e5346f88789d75c"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 18 20:59:11 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 18 10:59:11 2026 -0700"
      },
      "message": "give the conformance client step a timeout (#681)\n\nThe default limit is thirty seconds per scenario. This workflow\u0027s own run stayed inside it on every non-auth scenario, and its timeouts were auth scenarios that `conformance_expected_failures.yaml` already expects. A slower machine gives a different result. Thirty-two scenarios time out on the laptop I measured on, leaving the baseline check to report unexpected failures that are not conformance gaps. Two minutes finishes with no timeouts. One minute does too. This change takes machine speed out of a weekly result.\n\nFollow-up to #675."
    },
    {
      "commit": "7cb4308ee241e35309777eb31e5346f88789d75c",
      "tree": "35d857cf1ab1de2b3a35dac7a2cb4c49f052eedf",
      "parents": [
        "53fa7718daa76f4d314c65c430d582a3bd16c972"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Sep 17 22:42:11 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Sep 17 12:42:11 2026 -0700"
      },
      "message": "add tool content types and a tools list for sampling (#672)\n\nThe 2025-11-25 revision added tool use and tool result content to sampling messages, plus a tools list on the request. Both content types now sit under `SamplingMessageContentBlock`, the union the schema gives `SamplingMessage.content`. Plain `Content` keeps the arms a `tools/call` result can carry, while text, image and audio blocks implement both unions. Retyping `SamplingMessage.content` is breaking. A tool map read through `Content.fromMap` now trips an assert, since the static types alone cannot refuse one off the wire. I left `@Deprecated` off these types, because 2026-07-28 deprecates the sampling feature and the schema keeps them. Array-valued message content wants its own change."
    },
    {
      "commit": "53fa7718daa76f4d314c65c430d582a3bd16c972",
      "tree": "a13f260c776bb7054546ac1311399669a31f1c75",
      "parents": [
        "0dc0cf64efc6c589779447ab08f5aa107d85ecdc"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 16 17:34:10 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 16 07:34:10 2026 -0700"
      },
      "message": "document input requests and mark Streamable HTTP supported (#677)\n\nRemoving elicitation, sampling and roots from the server left a readme section describing a call pattern that no longer exists. It now describes answering with an `InputRequiredResult`. That answer serves every revision. Streamable HTTP moves from :construction: to supported. Neither the handler nor the client channel carries an unfinished piece, and the row\u0027s note already names what the revision removed."
    },
    {
      "commit": "0dc0cf64efc6c589779447ab08f5aa107d85ecdc",
      "tree": "0b47828882e2ca8253faefd3d2e6ef08f433477b",
      "parents": [
        "b8c6e3e424cf0eea4a7f1a8a75c1ab0bf01414fc"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 15 23:19:20 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 15 13:19:20 2026 -0700"
      },
      "message": "follow up on the review comments on #636 (#674)"
    },
    {
      "commit": "b8c6e3e424cf0eea4a7f1a8a75c1ab0bf01414fc",
      "tree": "6f88ac67d6a40cc661807cef86914402cb401184",
      "parents": [
        "ca61d27849cd0c90ad5dfb5972b5cd9010dc6b7b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 15 22:49:16 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 15 12:49:16 2026 -0700"
      },
      "message": "run the mcp conformance suite weekly (#675)"
    },
    {
      "commit": "ca61d27849cd0c90ad5dfb5972b5cd9010dc6b7b",
      "tree": "c46f1aa454fdffdea393d389f726faf4b2d838bb",
      "parents": [
        "22944448afdd3947050c5308e026553981636b41"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 15 20:01:59 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 15 10:01:59 2026 -0700"
      },
      "message": "remove elicit, listRoots and createMessage from the server (#655)\n\nThe server request methods do not fit with how InputRequiredResult works, because handlers return input requirements as results. I removed elicit, listRoots and createMessage, a breaking API change.\n\nHandlers return an InputRequiredResult instead. On revisions before 2026-07-28 a shim wraps tools/call, prompts/get and resources/read at registration, sends each InputRequest as that revision\u0027s own request and reruns the handler with the answers, up to MCPServer.maxInputRequiredRounds rounds (8 by default). WithInputResponses gained elicitResponse, sampleResponse and listRootsResponse, and a handler reads an answer as the type it asked for.\n\nPart of dart-lang/ai#668."
    },
    {
      "commit": "22944448afdd3947050c5308e026553981636b41",
      "tree": "a806b47e507d85bf81bd8a151c62acdc1b04f462",
      "parents": [
        "4a5f1acb4d3f5d3106f774f349c4e6a4bd386dea"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Sep 14 20:47:54 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Sep 14 10:47:54 2026 -0700"
      },
      "message": "cancel a request when its SSE response closes (#663)\n\nAnswering a request on an SSE response means a disconnect should cancel it. This\nwatches `response.done`, then shuts the server down once the response has\nstarted. A request still on its JSON body keeps running, and a test pins that.\n\nWidening keep-alive to every SSE response also exposed the suite\u0027s `events`\nhelper. A `: keep-alive` frame carries no field lines, so `frame[\u0027data\u0027]!` threw\n`Null check operator used on a null value` whenever a handler parked past the\n50ms interval these tests use. I left comment frames out of `events` and added a\ntest that reads a stream across one."
    },
    {
      "commit": "4a5f1acb4d3f5d3106f774f349c4e6a4bd386dea",
      "tree": "147482a341d7a5e0d967de6b715b38205ee61a1c",
      "parents": [
        "b6e03bc33e3e3a5308832c1560fd38cf860cbda4"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 11 23:25:02 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 11 13:25:02 2026 -0700"
      },
      "message": "list the 2026-07-28 revision and the elicitation capability in the readme (#670)\n\nThe readme did not list 2026-07-28 under supported protocol versions, and the client capabilities table had no row for elicitation.\n\nPart of https://github.com/dart-lang/ai/issues/668"
    },
    {
      "commit": "b6e03bc33e3e3a5308832c1560fd38cf860cbda4",
      "tree": "5843f491d2de5a9cfa7c1d9edf6b83cdbba314fb",
      "parents": [
        "42ac7d9fd6ffbfc68bb7be237e4c431be561be39"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 11 23:06:49 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 11 13:06:49 2026 -0700"
      },
      "message": "add optional origin validation for Streamable HTTP (#669)\n\nAdds optional `allowedOrigins` to `handleStreamableHttpRequest`, leaving default behavior unchanged. With it set, absent or allowed origins pass, while unlisted or repeated Origin headers return an empty 403 response.\n\nI chose opt-in validation, as in TypeScript middleware and the Go handler. This is just the Origin half I said was ready in #162, and closing it is an answer if validation belongs outside the package.\n\nPart of dart-lang/ai#162"
    },
    {
      "commit": "42ac7d9fd6ffbfc68bb7be237e4c431be561be39",
      "tree": "6a5a3dd94b4064bb1beb64acb4074a10e7ddcac5",
      "parents": [
        "2f376a031bfa78b9537a84c44b47486b005aadc7"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 09 23:24:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 09 13:24:35 2026 -0700"
      },
      "message": "validate capability extension identifiers (#661)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe revision says an extension identifier has to follow the `_meta` key naming rules and carry a prefix. Nothing checked that, so a server could advertise `foo` and a client would take it.\n\nI check those keys now on every surface that writes, reads or forwards them, and the check reads without rewriting anything. The Streamable HTTP client hands each request the caller\u0027s own capabilities, so a capability set after the channel opens still arrives.\n\nAn empty name is legal under those rules, so `example/` passes, and the changelog lists the rejection under breaking."
    },
    {
      "commit": "2f376a031bfa78b9537a84c44b47486b005aadc7",
      "tree": "9c5863e542a8b0f151f239647f900b0ebb3088d9",
      "parents": [
        "e07b1727fe0beb603324dfe5ccdcff625411d4ab"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Wed Sep 09 23:03:41 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Sep 09 13:03:41 2026 -0700"
      },
      "message": "add a client fixture for the conformance suite (#665)\n\nThe suite tests clients as well as servers, but `tool/` only carried the server fixture, so there was nothing to run the client leg against.\n\nThis one just branches on the scenario name the suite passes in the environment, and drives the traffic it scores. Tests run it against a server on the wire, and cover the retry when that server turns its version down. Non-auth scenarios pass 63 checks, run one at a time. The suite\u0027s parallel mode starts a client per scenario and they fall over each other here. I left `auth/*` out, since the package has no OAuth client.\n\n    npx @modelcontextprotocol/conformance@0.2.0-alpha.11 \\\n      client --command \"dart run tool/conformance_client.dart\" \\\n      --spec-version 2026-07-28 --scenario tools_call"
    },
    {
      "commit": "e07b1727fe0beb603324dfe5ccdcff625411d4ab",
      "tree": "8ebbd2cf0d6e5baa082a84c47cf11ba3d8dd30fb",
      "parents": [
        "c58d9477b8a83e3400815289c2feb82bd83c3520"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 20:45:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 10:45:07 2026 -0700"
      },
      "message": "name the transports in the package description (#666)\n\nThe pubspec report asks for 50 characters and this one is 45, so `dart_mcp` loses the pubspec points on its listing. Naming the transports carries it past the minimum without saying anything new about the package."
    },
    {
      "commit": "c58d9477b8a83e3400815289c2feb82bd83c3520",
      "tree": "b2b0ea71dc166155e3d0e5bd55681441a4b78b2b",
      "parents": [
        "42e3db2d4093ca2d454a5003812c32ecb9e162d1"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 19:23:12 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 09:23:12 2026 -0700"
      },
      "message": "pin the header walk past a matching property (#662)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe revision has a server reject a request when any mirrored header disagrees with the body. The check walks every annotated property, and nothing held it to that. On main I stopped the loop after the first property that matches its header and the suite stayed green.\n\nNothing fixes the order the properties are walked in, so the test sends both arrangements. One pairs a matching `Mcp-Param-Region` with a mismatched `Mcp-Param-Count`, the other reverses them, and both expect 400, `-32020`, and a message naming the header and the body value."
    },
    {
      "commit": "42e3db2d4093ca2d454a5003812c32ecb9e162d1",
      "tree": "2343124724808b05959169b2532251f257b65042",
      "parents": [
        "2fe3dd58c19ac755bd29104e7186787865d524de"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 19:23:06 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 09:23:06 2026 -0700"
      },
      "message": "add a padded request state to five write paths (#664)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThese tests wrote no padded request states. Trimming any of the five writes changed nothing they could see. Padded values run through all five now.\n\nThe old test name said `across JSON`, but it just decoded. I narrowed it to what the test checks."
    },
    {
      "commit": "2fe3dd58c19ac755bd29104e7186787865d524de",
      "tree": "65a4265cd29a1a8971c5e8e206b56e79f13cdd38",
      "parents": [
        "41f5a1af2e956924efb7cafe642c11ec874f8720"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 18:18:15 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 08:18:15 2026 -0700"
      },
      "message": "cap request bodies in the Streamable HTTP handler (#657)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nNothing capped a request body here. On a chunked one `contentLength` is -1, so the handler counts the bytes as they arrive. The TypeScript and Go SDKs both stop at 4 MiB with a 413, so I just did the same, as a `maxRequestBodyBytes` argument with that default. Reading past the cap stops at another `maxRequestBodyBytes`, so a body a little over still finishes and sees the response.\n\nThe error body carries `-32600`, the code this handler already uses when it refuses a batch before parsing. TypeScript answers `-32000` there."
    },
    {
      "commit": "41f5a1af2e956924efb7cafe642c11ec874f8720",
      "tree": "5d78b1b9bbbf77fe943f46b90acec9afd6c6604c",
      "parents": [
        "ce5785c044c922259142b409991c5030039f5db3"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 18:17:53 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 08:17:53 2026 -0700"
      },
      "message": "let a caller add headers to the client channel (#667)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe server handler leaves authentication to the embedding server. On the client side there was no way to send any. The channel builds its own `HttpClient`, and there was no way to hand it an `Authorization` header.\n\nIt takes a map now. The protocol\u0027s own headers are written after it, so a caller cannot replace the version, the method or a mirrored parameter."
    },
    {
      "commit": "ce5785c044c922259142b409991c5030039f5db3",
      "tree": "8e4262bb8547bf6cc571ff40a0814c6e0457592c",
      "parents": [
        "55fdf48ccf2581a68e3f54a50ddd18c51d1b50f2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 08 17:51:48 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 08 07:51:48 2026 -0700"
      },
      "message": "route server-to-client requests on older revisions (#654)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nOn revisions before 2026-07-28 the dispatcher answered a server-originated request with `-32603`, since a single-message exchange had nowhere to send it. It now takes an optional router and writes the matching response back, so the waiting peer completes.\n\nOnly those exchanges route, and the guard is explicit because a `ping` can produce a request before the version is read. Without a router I just kept the old fail-fast. A response with the wrong shape or id becomes an internal error, and one arriving after the exchange closes is dropped.\n\nThis is what the `#162` TODO in the dispatcher was waiting on."
    },
    {
      "commit": "55fdf48ccf2581a68e3f54a50ddd18c51d1b50f2",
      "tree": "e640e9047492ff14531e1e235d9c3061e1419174",
      "parents": [
        "a3fd9eb1a48079d74288a44998b372ada61f310b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 23:55:23 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 13:55:23 2026 -0700"
      },
      "message": "pin the retry and request state contracts (#658)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nTwo things the revision asks of a server held here but had no test. Nothing carried `requestState` through a round trip to show it comes back untouched, and nothing exercised a client that answers an `InputRequiredResult` without retrying.\n\nThree tests cover both now. I just left the integrity half of that paragraph alone, since this package never authorizes on the field."
    },
    {
      "commit": "a3fd9eb1a48079d74288a44998b372ada61f310b",
      "tree": "eb3c64ccb604ce4b80bec8f50810bbe6867e6886",
      "parents": [
        "93fff610865fcc080541f1c5b20b5fe9108b2cd0"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 23:03:55 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 13:03:55 2026 -0700"
      },
      "message": "answer an unsupported media type with 415 (#659)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nA POST that isn\u0027t JSON got a 400 here. The revision doesn\u0027t name a status for that, so I just followed the three SDKs that do. TypeScript answers 415 in `streamableHttp.ts:770`, Go in `mcp/streamable.go:389`, Rust in `server_side_http.rs:258`. Python stays on 400 and marks its own 415 path unreachable.\n\nThe JSON-RPC code stays `-32020`. This path calls `_reject` directly, so the status table is untouched."
    },
    {
      "commit": "93fff610865fcc080541f1c5b20b5fe9108b2cd0",
      "tree": "63624f39914c56c3f175e958f3aa9ccb2ec0ce08",
      "parents": [
        "2cccf7c07259cc7a1ee07de8a13018b96ba90c4e"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Sep 04 12:26:40 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 12:26:40 2026 -0700"
      },
      "message": "publish package:skills v1.0.1 (#660)"
    },
    {
      "commit": "2cccf7c07259cc7a1ee07de8a13018b96ba90c4e",
      "tree": "d1fb978a113a146606c710c4c44ef409f229eee5",
      "parents": [
        "ce3cfc5a1355674a3d9cb9c1b3a222f42c1e0634"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 21:40:29 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 11:40:29 2026 -0700"
      },
      "message": "accept the multi-select answers this package asks for (#656)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe two multi-select enum shapes landed in #357, and the validator from #193 turned down every array, so a client answering one of our own schemas got refused.\n\nThe check now sits on `EnumSchema` and takes a JSON array, like the rest of the package does. A `Set` would just pass here and then fail at encoding. I built the fixture from the published schema instead of the package\u0027s own builders."
    },
    {
      "commit": "ce3cfc5a1355674a3d9cb9c1b3a222f42c1e0634",
      "tree": "b4ce12a68a902286f66008246b68d4f5a293f5fa",
      "parents": [
        "ef0d8f6ae1aa47f0c41d3d1d8c4d80b76cc3248b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 19:22:50 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 09:22:50 2026 -0700"
      },
      "message": "stop telling a 2026-07-28 server the roots list changed (#652)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe 2026-07-28 revision removed `notifications/roots/list_changed`, and https://github.com/dart-lang/ai/pull/631 stopped the server sending the three input requests it removed. But `RootsSupport` just kept sending this one from the client side. I added the check inside the loop that sends it.\n\nUntil a connection settles on a revision, it still gets the notification. This does not drop the client\u0027s `roots.listChanged`."
    },
    {
      "commit": "ef0d8f6ae1aa47f0c41d3d1d8c4d80b76cc3248b",
      "tree": "d01ce6899f074985663e1fa7a7b21e1c4ca011c7",
      "parents": [
        "0fdae224e3abd1bde1678847d3bed9c9be403c93"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Sep 04 19:21:47 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 09:21:47 2026 -0700"
      },
      "message": "exercise listen streams from the conformance probe (#653)\n\nWithout `SubscriptionsSupport`, the probe that #640 added answered `server/discover` with the four subscription bits stripped, and the suite skipped five server-stateless checks. I mixed it in and added the two tools that the scenario calls to change a list. The transport now gets the broadcast stream that its docs already describe.\n\nAgainst 2026-07-28 the server-stateless checks go from 25 passed with five skipped to 30 passed with none. The stream has a test in the package too, since CI does not run the suite."
    },
    {
      "commit": "0fdae224e3abd1bde1678847d3bed9c9be403c93",
      "tree": "f5d5cb61233cd3fdb90566a057cb3b9c79127188",
      "parents": [
        "7d84254f836af12369e2c5d0f67c0f028f5c5728"
      ],
      "author": {
        "name": "Nate Bosch",
        "email": "nbosch1@gmail.com",
        "time": "Thu Sep 03 19:38:34 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Sep 03 19:38:34 2026 -0700"
      },
      "message": "Use latest package:test (#626)\n\nCloses https://github.com/dart-lang/test/issues/2688\n\nThe deadlock was caused by an interaction between chrome and exe tests where the chrome process was inheriting the socket server bound to communicate with the exe test.\n\nWorkaround landed in https://github.com/dart-lang/test/pull/2740"
    },
    {
      "commit": "7d84254f836af12369e2c5d0f67c0f028f5c5728",
      "tree": "cdda2bb4f571ace4fff230180e28a4ea2b6c2c84",
      "parents": [
        "f03fe1a1e3935fceccc323575ab325ef54df13e2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 22:30:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 12:30:35 2026 -0700"
      },
      "message": "serve the subscriptions/listen notification stream (#636)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe `subscriptions/listen` types landed without a handler. I put the acknowledgement contract on the mixin instead of the Streamable HTTP dispatcher, since the spec states it for every transport. It stamps the subscription id on the first message, holds the request until shutdown, and refuses a listen the transport did not name. Matching list and resource notifications go onto the open response, and closing it just ends the subscription without a final result.\n\nAn embedder can feed a shared notification stream so a change from one request reaches another listen. Public factories, the subscription-id shape, and the `discover` advertisement change with this wire."
    },
    {
      "commit": "f03fe1a1e3935fceccc323575ab325ef54df13e2",
      "tree": "e9f6f109d42d96f51f5e19e55410417208c2d1f3",
      "parents": [
        "c4de9ff82b3f833a0ea13fe6bf6784d55e8cf120"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 22:30:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 12:30:07 2026 -0700"
      },
      "message": "cache client responses from server hints (#635)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe client reuses complete results for the six 2026-07-28 operations that\ncarry caching hints, keyed by the parameters and the request metadata. I\nwrapped `sendRequestKeepingProgress` so `sendRequestWithInputs` still hits\nthe cache. Entries drop on change notifications, a stale cursor, and\n`shutdown`. The cache belongs to one `ServerConnection`. A `private` result\nnever leaves the authorization context it came from.\n\nThe multi round-trip page never mentions caching. The caching utilities page\n(https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching)\nsays an `input_required` result is not cacheable, and a retry carrying\n`inputResponses` or `requestState` MUST NOT be cached. I kept both out even\nwhen a `resources/read` payload also sends the hints."
    },
    {
      "commit": "c4de9ff82b3f833a0ea13fe6bf6784d55e8cf120",
      "tree": "ef2f979127e3ad2477a814396b0a5b1757ae0c28",
      "parents": [
        "e85bf1c9bee8b650deece8276647a6ffca2c6a5d"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 19:24:19 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 09:24:19 2026 -0700"
      },
      "message": "add a local mcp conformance probe (#640)\n\nCloses https://github.com/dart-lang/ai/issues/491\n\n#572 shipped Streamable HTTP. The blocker named in that issue is gone. I added a local HTTP probe under tool/ as development tooling, not package API.\n\ncrypto is a dev_dependency used only to HMAC opaque requestState. The suite runs from Node, and the integration guide offers a reusable Action instead of requiring one. I left the bots alone.\n\nAgainst `@modelcontextprotocol/conformance@0.2.0-alpha.11`, `--requirements 2026-07-28` is 37/37 and `--suite all --spec-version 2026-07-28` is 40/40. Thirteen more scenarios run without scoring, ten of them the tasks extension this package does not implement. The other three are pending and pass."
    },
    {
      "commit": "e85bf1c9bee8b650deece8276647a6ffca2c6a5d",
      "tree": "eb31466f1fa8364e950632fdc5980b12cf584608",
      "parents": [
        "035eca55321ccae020b5b49309d7861d49c0680a"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 19:23:52 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 09:23:52 2026 -0700"
      },
      "message": "make schema iterables JSON encodable (#644)\n\nSets and lazy iterables in seven schema fields made `jsonEncode` fail. This follows up on [the issue I noted in #603](https://github.com/dart-lang/ai/pull/603#discussion_r3792311104) now that it has landed.\n\nWith no matching package precedent, I think the constructor is the natural boundary for converting each value to a fixed-length list. A compact table test covers all seven fields through `jsonEncode`."
    },
    {
      "commit": "035eca55321ccae020b5b49309d7861d49c0680a",
      "tree": "6c89fc1143c39d44f254509b3258dc93b216870e",
      "parents": [
        "135dd698e35748fce55e71bb9f11bede4eee9d2b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 19:12:36 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 09:12:36 2026 -0700"
      },
      "message": "let the create tool target the project root (#642)\n\nThe create tool rejected a `directory` of `.`. The check leans on `p.isWithin`,\nand that is strict enough to call `isWithin(\u0027.\u0027, \u0027.\u0027)` false, reading it as an\nescape from the project root.\n\nI let the root through for Flutter, where `flutter create .` works. A Dart\nproject still needs a subdirectory, because the Dart CLI wants an empty target\nunless it is forced, and forcing is not something this tool does. The error says\nthat now. An empty string lands in the same place as `.`, and it is rejected on\nits own."
    },
    {
      "commit": "135dd698e35748fce55e71bb9f11bede4eee9d2b",
      "tree": "2e3b68cf6a4d1b5df679517e7775e208fffece6d",
      "parents": [
        "db510a3a9d3cbb748c315fa442f62eca9f4996f6"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Tue Sep 01 08:53:28 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Sep 01 08:53:28 2026 -0700"
      },
      "message": "Bump the github-actions group with 4 updates (#645)\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "db510a3a9d3cbb748c315fa442f62eca9f4996f6",
      "tree": "46f78cfbf6de54b7b2f47eda842f4bb898d86e11",
      "parents": [
        "91107a55f74d834c913baa5e6e8ad4fff1f5541e"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 01:07:29 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 15:07:29 2026 -0700"
      },
      "message": "let tool, prompt and resource handlers answer with an input-required result (#637)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nhttps://github.com/dart-lang/ai/pull/622 left the handler return types alone. A server still cannot answer `tools/call`, `prompts/get` or `resources/read` with an `InputRequiredResult`. This widens the three of them to `CallToolResponse`, `GetPromptResponse` and `ReadResourceResponse`, which the completed result and `InputRequiredResult` both implement.\n\nRust names the same three. I kept the supertypes constructorless so `_fromMap` stays private. Extension types cannot be told apart by `is`, so `Result.isInputRequired` reads the result type instead.\n\nIt is a breaking change, and the handler parameters widen with it. Callers on 2025-11-25 see no difference, because what they already return satisfies the wider type. The `dart_mcp_server` package resolves the published 0.5.x, so its six sites move when 0.6.0 lands."
    },
    {
      "commit": "91107a55f74d834c913baa5e6e8ad4fff1f5541e",
      "tree": "467d43958fb0d1d02118cb258a5df44c387fad24",
      "parents": [
        "db457476e44ccceba0983a711242a92683ba876f"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Tue Sep 01 00:03:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 14:03:07 2026 -0700"
      },
      "message": "add a Streamable HTTP client channel (#638)\n\nStreamable HTTP still lacked a client channel. I put `streamableHttpClientChannel` next to the server handler so the header names stay one definition.\n\nFailures come back on the id that asked for them. A notification has none, so it only hears about a POST that already went out.\n\nThe helper requires a protocol version up front, since it never sends `initialize`. The Tools page requires Streamable HTTP clients to exclude invalid `tools/list` entries (https://modelcontextprotocol.io/specification/2026-07-28/server/tools#x-mcp-header)."
    },
    {
      "commit": "db457476e44ccceba0983a711242a92683ba876f",
      "tree": "14cc83e0b87cff054a488340689b3aee9b45813c",
      "parents": [
        "a106f3f568878652277021fac96358584d1c5368"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 31 20:01:08 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 10:01:08 2026 -0700"
      },
      "message": "wait before a retry that carries no input requests (#639)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nNothing paced the leg the TODO named, so the client could retry the moment the server answered. `ServerConnection.inputRequiredRetryDelay` now holds it off for 250 ms, and `null` disables that. An empty map waits too, since it asks for nothing. Where the server does hand back work, resolving it already costs time, so those rounds are untouched.\n\nThe number comes from `packages/core-internal/src/shared/inputRequiredDriver.ts` in the TypeScript SDK, which sleeps a flat 250 ms there. Python caps a backoff at the same figure. I took the flat wait, since a constant pause on each of these rounds keeps the loop off the wire."
    },
    {
      "commit": "a106f3f568878652277021fac96358584d1c5368",
      "tree": "e14307556804b7b7885f280b9a67fa1935407f44",
      "parents": [
        "e630be7f2a2c86b66f8da34c14c1c12ec869057b"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 31 20:00:45 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 31 10:00:45 2026 -0700"
      },
      "message": "reject real whitespace in a create template (#643)\n\nThe create tool accepted a template carrying a newline or a tab. The check\nlooked for a literal backslash-n. Only a space was caught, and the message\nalready promised more than that.\n\nI just swapped both string checks for one whitespace pattern. The message now\nmatches what the code does. A template carrying a literal backslash-n gets\nthrough now, and one carrying a non-breaking space does not."
    },
    {
      "commit": "e630be7f2a2c86b66f8da34c14c1c12ec869057b",
      "tree": "f33930ba587605e8ba27ffd7aea5086c42f4c4be",
      "parents": [
        "ba495eebdb133e35ac59669a5cc6b9f3adab9b07"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Fri Aug 28 14:26:17 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 14:26:17 2026 -0700"
      },
      "message": "pin ecosystem workflow actions to hashes (#634)"
    },
    {
      "commit": "ba495eebdb133e35ac59669a5cc6b9f3adab9b07",
      "tree": "6abd41bdb0c9ac8ff81105ce72ec84f6b891f12c",
      "parents": [
        "7c01a0d32e10147285d54d06693125d55ab14c0e"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 23:37:52 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 13:37:52 2026 -0700"
      },
      "message": "answer the input requests in an input_required result (#632)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe client half of MRTR. On an `input_required` result the connection fills in\nwhat the server asked for and sends the call again. A request it cannot build\nfails the call instead of answering the rest.\n\nThe handshake stops at 2025-11-25, so only a transport setting the version\nitself reaches 2026-07-28. I made `protocolVersion` nullable. Nothing fills in\n`serverInfo` there either, and both sampling paths name it.\n\n`ServerConnection` gains `sendRequestWithInputs` for a mixin adding an\nextension method. `maxInputRequiredRounds` moves the cap off ten. `MCPBase`\ngains `@protected` `sendRequestKeepingProgress` and `closeProgress`. A retry\nholds one progress token across its rounds."
    },
    {
      "commit": "7c01a0d32e10147285d54d06693125d55ab14c0e",
      "tree": "ecfce6f58ca2fbb1a7f25b416c6475a1fb92b4f2",
      "parents": [
        "6dd5be9af2777ce16ad9a24b1d7c51985ffbb9d3"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 23:00:54 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 13:00:54 2026 -0700"
      },
      "message": "validate x-mcp-header params in the Streamable HTTP handler (#627)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe server never read the `Mcp-Param-*` headers this revision defines. A header that contradicted the body was ignored. The spec asks for a 400 and -32020 there.\n\nValidating one needs the tool\u0027s input schema, so I put a `beforeDispatch` hook on the request-scoped entry point and the transport hands it the initialized server. Reading a schema from there needed `ToolsSupport.registeredTools`, a read-only view. I did not want to run someone\u0027s `listTools` override on every call.\n\nOn #580 you preferred an error, or an assert if it had to be masked. Here the invalid thing is the tool definition, not the server: the 2026-07-28 page says clients \"MUST reject tool definitions where any `x-mcp-header` value violates these constraints\". An out-of-spec annotation goes unread instead."
    },
    {
      "commit": "6dd5be9af2777ce16ad9a24b1d7c51985ffbb9d3",
      "tree": "9b6a639cc9fdf7e725bb48c26b8de9fca5088f02",
      "parents": [
        "edb9c1c04b5b0ed7e0eaae5c020d04532eea8375"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:58:27 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:58:27 2026 -0700"
      },
      "message": "decode SSE response bodies on the client (#629)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe client side has no SSE reader yet, so I added `sseMessageStream`. A frame that fails to decode arrives as an error while the stream keeps reading, since one bad frame probably should not cost the whole response. A truncated frame never arrives and bad bytes become the replacement character. The HTML specification asks for both.\n\nThe decoder sits under `src/utils` because it needs nothing from `dart:io`. The `events` helper in the transport tests reads a whole string. It stays for now. I want this for the client transport, the next slice."
    },
    {
      "commit": "edb9c1c04b5b0ed7e0eaae5c020d04532eea8375",
      "tree": "b3d958d0b245ecf5823c6872e7dfe8fceb5cbc79",
      "parents": [
        "9f4196b59b8b49c266b25bb227bb708cc9075540"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:50:10 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:50:10 2026 -0700"
      },
      "message": "Set client serverInfo only when version negotiation succeeds (#633)\n\n`ServerConnection.serverInfo` already documented that it is only non-null once\n`initialize` succeeds, but `initialize` assigned it before looking at the\nversion. A connection shut down over an unsupported version still held the\nrejected server\u0027s implementation.\n\nI moved the assignment next to `protocolVersion`, so it just lands in the\nbranch that runs when the version is one we support. `ServerConnection.name`\nreads through it. A rejected connection now logs as `unknown`."
    },
    {
      "commit": "9f4196b59b8b49c266b25bb227bb708cc9075540",
      "tree": "8561976fd5d36b8ce1d2174fbdfc22520563344f",
      "parents": [
        "9e1e64fa916989b0c23078ceb87cd386c83ed4c1"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:49:53 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:49:53 2026 -0700"
      },
      "message": "add the client side of server/discover (#630)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe package answers `server/discover`, but a client sending one had to build\nthe request itself. On this revision the whole request is reserved `_meta`\nkeys.\n\nI added `ServerConnection.discover`. It takes the two required keys as\narguments instead of a `DiscoverRequest`, so a probe cannot go out without\nthem, while `MCPServer.discover` still takes one. Client info, a log level and\na progress token go in when they are given. The result just comes back as it\narrived. A probe leaves the connection\u0027s own state alone.\n\nThe envelope keys get their own type, `MetaWithRequestEnvelope`, extending\n`MetaWithProgressToken`."
    },
    {
      "commit": "9e1e64fa916989b0c23078ceb87cd386c83ed4c1",
      "tree": "dc006b70e8d690724751383aebaf64452c9e1a48",
      "parents": [
        "d320d70fbc8e6e582746bb536b6696c1b6b0d488"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 22:49:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 12:49:35 2026 -0700"
      },
      "message": "reject server-to-client requests the revision does not have (#631)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nOn 2026-07-28 a server could still send the three requests that ask a client\nfor input. That revision keeps their types for the `InputRequiredResult` that\ncarries them, but drops the `ServerRequest` union they went out through, and\n`removedMethods` never picked that up.\n\nI listed them there and had the senders read that check first. It also refuses\n`elicit` on the two revisions that predate `elicitation/create`.\n\nThe other senders still go out unchecked, `resources/subscribe`,\n`resources/unsubscribe`, `logging/setLevel` and `ping` among them."
    },
    {
      "commit": "d320d70fbc8e6e582746bb536b6696c1b6b0d488",
      "tree": "62135b1ca832edcb86b28e4f0c0f02c68c0dd213",
      "parents": [
        "6248d08f0267b15e22bd369e4222078612aadb28"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 28 21:28:48 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 28 11:28:48 2026 -0700"
      },
      "message": "refuse input_required results a client cannot act on (#628)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe dispatcher passed an `input_required` result straight through. A server could answer tools/list that way, or ask for an elicitation the client never declared. 2026-07-28 allows neither.\n\nAnswering that way on a method outside prompts/get, resources/read and tools/call is now an internal error, as is a malformed input request. I send an undeclared capability through `_missingClientCapability`, just the -32021 a live connection raises. I pulled those refusals out for the dispatcher and the server methods to share. Tool use is the one check that goes further, needing `sampling.tools` where `createMessage` looks only for `sampling`."
    },
    {
      "commit": "6248d08f0267b15e22bd369e4222078612aadb28",
      "tree": "53d74dd09a62daad9e576316a069719589ea145b",
      "parents": [
        "8240e23a02eb4f9b8d5a9c6937305432526e5974"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Aug 27 15:21:13 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 15:21:13 2026 -0700"
      },
      "message": "Bump the github-actions group across 1 directory with 3 updates (#625)\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "8240e23a02eb4f9b8d5a9c6937305432526e5974",
      "tree": "bc11358d6b9090e8d09047f35cfa0a7a9b0ced16",
      "parents": [
        "879efce376183bcf10a55f89da0fd46f1d5711fd"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 27 14:24:10 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 14:24:10 2026 -0700"
      },
      "message": "Add missing license headers (#624)\n\nAdds missing license/copyright headers to files flagged during open source review.\n\n- Add BSD-style copyright headers across repository config, workflows, `dart_mcp`, `dart_mcp_server`, and `counter_app` test fixture files.\n- Update `CHANGELOG.md` for `dart_mcp` and `dart_mcp_server`."
    },
    {
      "commit": "879efce376183bcf10a55f89da0fd46f1d5711fd",
      "tree": "c34c1e944a5d2bdea202f3afc94aee6f4d898683",
      "parents": [
        "5c336fad18dae8ff761d003000b530500ffa2d8b"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 27 14:21:15 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 14:21:15 2026 -0700"
      },
      "message": "Clean up skills CLI tests (#623)\n\nThis PR fixes tests breaking in non-TTY environments due to ANSI output injection by explicitly wrapping tests evaluating multi-select dialogs in `overrideAnsiOutput(false, ...)`. Additionally, changes `GitSync` raw `stderr.writeln` to use `package:logging` so that clone warnings are correctly swallowed by test suites.\n\nIt also fixes one test that was running the CLI in the current working directory instead of the temp directory, which was leaving artifacts on disk."
    },
    {
      "commit": "5c336fad18dae8ff761d003000b530500ffa2d8b",
      "tree": "fde96443f081d2bb3d0a354ca7b56747919a98bf",
      "parents": [
        "37ede8afc1790006c883baa434be0c0575e0df29"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Thu Aug 27 08:02:53 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 08:02:53 2026 -0700"
      },
      "message": "Ignore uninstalled and missing skills in skills list (#617)\n\nFixes #607\n\n- Filter out skills with `isInstalled: false` in `ListCommand`\n- Filter out skills that no longer exist on disk in `ListCommand`\n- Filter out empty packages and agents with no installed skills in `ListCommand`\n- Filter out `isInstalled: false` in `SkillManifest.allSkills` and `allSkillsForAgent`\n- Add changelog entry for package:skills\n- Add regression tests in `list_command_test.dart` and `skill_manifest_test.dart`"
    },
    {
      "commit": "37ede8afc1790006c883baa434be0c0575e0df29",
      "tree": "ea3d9cdcb304c613c4ec0b1f57c74c8645985160",
      "parents": [
        "1bf21ac740ff045aa63e54f5575cac52bd39aa43"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 27 17:59:35 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 07:59:35 2026 -0700"
      },
      "message": "add input-response request fields (#622)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThis adds the request side of https://github.com/dart-lang/ai/pull/602. The three requests a server can answer with an `InputRequiredResult` now take an `inputResponses` map and a `requestState`, which is what a retry carries back.\n\nI left the handler return types alone for now. Nothing sends or reads these yet, and widening those three signatures would be a breaking change."
    },
    {
      "commit": "1bf21ac740ff045aa63e54f5575cac52bd39aa43",
      "tree": "c32e608607915f3225307e01b557ef4c4146b691",
      "parents": [
        "fa55c819d66c70f9ebde2af27a421f4415d391a2"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Thu Aug 27 00:48:02 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 26 14:48:02 2026 -0700"
      },
      "message": "finish a changelog merge that kept both sides (#621)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nA merge in #610 hit a conflict in the unreleased notes and kept both sides. The sentence saying the server does not answer `server/discover` yet came back from before its removal in #596, and that PR\u0027s replacement ending landed seven lines lower with nothing above it.\n\nI kept the #596 side."
    },
    {
      "commit": "fa55c819d66c70f9ebde2af27a421f4415d391a2",
      "tree": "1ec58c2cd635790c8e6c7ab787ffaf2f7860f4f6",
      "parents": [
        "17ecdc963fc30ac473e84f6206793a8e1e9bf2df"
      ],
      "author": {
        "name": "Jacob MacDonald",
        "email": "jakemac@google.com",
        "time": "Tue Aug 25 14:23:02 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 25 14:23:02 2026 -0700"
      },
      "message": "add a package:skills issue template (#619)"
    },
    {
      "commit": "17ecdc963fc30ac473e84f6206793a8e1e9bf2df",
      "tree": "cea2355a72b3eb24faecb9ce60e7d5392441a5b3",
      "parents": [
        "94aca951c5ad779847e6ec28b77afc36428c4ce6"
      ],
      "author": {
        "name": "Eric Windmill",
        "email": "ewindmill@google.com",
        "time": "Mon Aug 24 10:01:46 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 24 10:01:46 2026 -0700"
      },
      "message": "Add detail to instructions for creating a skill (#615)\n\nI\u0027m 0th customer-ing package:skills. This PR adds a bit more detail to the skill template and clarifies some documentation."
    },
    {
      "commit": "94aca951c5ad779847e6ec28b77afc36428c4ce6",
      "tree": "bf83455c823abf04fd27122b3a0b8c8fb3506c0d",
      "parents": [
        "33fcb6610db74aa6589fa41f113127d212528d42"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Mon Aug 24 17:55:28 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 24 07:55:28 2026 -0700"
      },
      "message": "check the elicitation mode at both ends (#614)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe server side only asked whether the client had `elicitation`, but a client declares which modes it takes and the [spec](https://modelcontextprotocol.io/specification/2026-07-28/client/elicitation#capabilities) says a server must not send one it did not. A url-only client saw form requests and declined them as if the user had.\n\nI split that guard into `supportsFormElicitation` and `supportsUrlElicitation`, and both ends now answer an unknown mode with invalid params. Auto-handling a `-32042` only runs when the request inside it names url. Both are breaking. The resolved getter throws on an unknown one, so the guards read a new `rawMode`."
    },
    {
      "commit": "33fcb6610db74aa6589fa41f113127d212528d42",
      "tree": "9a36da85d25e60b63795dbe3fae981e40662fb25",
      "parents": [
        "bfbcab2fe39f22453027d4d37021d10430c310f3"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 22 00:23:34 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:23:34 2026 -0700"
      },
      "message": "answer a notifying request on an SSE response stream (#610)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nNotifications a handler emits while it works now reach the caller on an SSE response stream instead of being dropped. The first one commits the response to `text/event-stream`, so a call that never notifies keeps its JSON body. Progress and log messages ride their own request\u0027s stream. The four list-changed and resource-updated notifications stay off it, since a `subscriptions/listen` request owns those.\n\nThe README row and the dartdoc that named response streams as missing now describe this. A client closing the stream is not treated as cancellation yet, which the specification requires once a server streams."
    },
    {
      "commit": "bfbcab2fe39f22453027d4d37021d10430c310f3",
      "tree": "7318939f85b0106d0470bc01d0fce71cbf029b4d",
      "parents": [
        "1e2cc7a6fe049f3adc62b443d19bf7c7162a432d"
      ],
      "author": {
        "name": "Keerti Parthasarathy",
        "email": "keertip@users.noreply.github.com",
        "time": "Fri Aug 21 14:19:16 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:19:16 2026 -0700"
      },
      "message": "[dart_mcp_server] Add a field to capture the agent plugin information in analytics (#612)\n\nThis PR \n- pulls in unified_analytics v 8.0.17\n- reads the plugin info from env\n- adds the plugin information to the MCP analytics events\n- added test to verify the changes"
    },
    {
      "commit": "1e2cc7a6fe049f3adc62b443d19bf7c7162a432d",
      "tree": "829690f6ec7836d98d1a30de597c401d42b62fcf",
      "parents": [
        "977a139b7cb6ae7549c593937c71ab5b3f0933be"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 22 00:09:06 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:09:06 2026 -0700"
      },
      "message": "fix the thisService spelling and the number field casts (#613)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe `IncludeContext` enum has spelled one value `thisService` since 0.1.0. No schema revision spells it that way, and the factory puts the enum name straight on the wire. I kept the old name as a deprecated alias, the same way `ElicitationAction` keeps `reject`. A client on 0.5.2 or earlier throws on the corrected name.\n\nFive getters cast the schema\u0027s number fields to a `double`. A whole number arriving from a peer throws except on the JavaScript platforms. They read `num` now. The `temperature` parameter only took an integer, which ruled out the `0.1` the spec\u0027s own `sampling/createMessage` request sends."
    },
    {
      "commit": "977a139b7cb6ae7549c593937c71ab5b3f0933be",
      "tree": "eb46255b324a455a795a860acead277719036591",
      "parents": [
        "7471b6e6778a721273c401a289419f9271764607"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Sat Aug 22 00:05:00 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 14:05:00 2026 -0700"
      },
      "message": "update the spec links to modelcontextprotocol.io and 2025-11-25 (#611)\n\nThe package has 42 spec links and 28 of them do not load. They sit in the readme and five source files. Most point at spec.modelcontextprotocol.io, which no longer serves HTTPS. Most also use revision 2025-11-05, never published. The same typo got fixed in `ProtocolVersion` in https://github.com/dart-lang/ai/pull/366, and that change moved the changelog link onto the canonical host too, so I followed it here. I kept 2025-11-25, since that is what `latestSupported` still points to."
    },
    {
      "commit": "7471b6e6778a721273c401a289419f9271764607",
      "tree": "aa39fdfee106e7560b02c93cef3a7a641a473546",
      "parents": [
        "9c1356d85c8939c666e41f1965013df776f30e4c"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:50:09 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:50:09 2026 -0700"
      },
      "message": "serve server/discover from MCPServer (#596)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nThe discover types landed without a dispatcher, so `server/discover` answered -32601 on a revision that requires it. I put the handler on the server, registered only from 2026-07-28 on, since answering is itself the claim to that lifecycle and the [stdio probe](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio#backward-compatibility) keys on it. TypeScript and Python gate it to the same revision.\n\nCapabilities are a public final field now and `initialize` no longer returns them. That is breaking. Mixins edit the object in place. The capabilities constructor was also skipping `completions`, just a missing line, fixed here."
    },
    {
      "commit": "9c1356d85c8939c666e41f1965013df776f30e4c",
      "tree": "3266f16abed97a57e48262ab6b0e0ee7e3eccd26",
      "parents": [
        "d81cf26a9ba025afe3f42fb85bb28462778f7e50"
      ],
      "author": {
        "name": "Yusuf İhsan Görgel",
        "email": "developeryusuf@icloud.com",
        "time": "Fri Aug 21 23:45:28 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 13:45:28 2026 -0700"
      },
      "message": "fix four schema types in tools.dart against the spec (#603)\n\nPart of https://github.com/dart-lang/ai/issues/162\n\nFour of the schema types in `tools.dart` disagree with the JSON Schema the spec points at.\n\nInteger bounds were typed as ints. JSON Schema types them as numbers, and the spec gives integers and numbers one definition. A valid `minimum: 0.5` threw on read. Number, integer and boolean schemas could not carry a default at all, leaving a server able to pre-fill a text field but not a checkbox. Two equal maps decoded from JSON got past `uniqueItems` on a list schema, since it compared them with `Set`. I picked up the enum factories spelling their own keys while I was in there."
    }
  ],
  "next": "d81cf26a9ba025afe3f42fb85bb28462778f7e50"
}
