{"id":51148756,"url":"https://github.com/fluttersdk/wind_diagnostics_contracts","last_synced_at":"2026-06-26T04:30:31.290Z","repository":{"id":359331662,"uuid":"1245640136","full_name":"fluttersdk/wind_diagnostics_contracts","owner":"fluttersdk","description":"Pure abstract contracts for reading Wind UI widget state at runtime without a compile-time dep on fluttersdk_wind. Zero deps. plugin_platform_interface pattern applied to UI framework + debug tooling decoupling (MCP, AI agents, DevTools).","archived":false,"fork":false,"pushed_at":"2026-05-21T12:41:16.000Z","size":18,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-05-21T19:36:12.633Z","etag":null,"topics":["ai-agents","contracts","dart","debug-tooling","diagnostics","e2e-testing","flutter","flutter-package","flutter-testing","llm","mcp","mcp-server","platform-interface","tailwind-flutter","wind","wind-ui"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/fluttersdk_wind_diagnostics_contracts","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fluttersdk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-21T12:14:07.000Z","updated_at":"2026-05-21T12:39:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/fluttersdk/wind_diagnostics_contracts","commit_stats":null,"previous_names":["fluttersdk/wind_diagnostics_contracts"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/fluttersdk/wind_diagnostics_contracts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttersdk%2Fwind_diagnostics_contracts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttersdk%2Fwind_diagnostics_contracts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttersdk%2Fwind_diagnostics_contracts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttersdk%2Fwind_diagnostics_contracts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fluttersdk","download_url":"https://codeload.github.com/fluttersdk/wind_diagnostics_contracts/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttersdk%2Fwind_diagnostics_contracts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34803678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","contracts","dart","debug-tooling","diagnostics","e2e-testing","flutter","flutter-package","flutter-testing","llm","mcp","mcp-server","platform-interface","tailwind-flutter","wind","wind-ui"],"created_at":"2026-06-26T04:30:23.604Z","updated_at":"2026-06-26T04:30:31.252Z","avatar_url":"https://github.com/fluttersdk.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/fluttersdk/wind/v1/.github/wind-logo.svg\" width=\"120\" alt=\"Wind Diagnostics Contracts Logo\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eWind Diagnostics Contracts\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eWind UI widget state contracts for Flutter debug-tooling and AI agents (MCP).\u003c/strong\u003e\u003cbr/\u003e\n  Zero-dep abstract resolver interface plus process-global registry. The \u003ccode\u003eplugin_platform_interface\u003c/code\u003e pattern, applied to UI framework and debug tooling decoupling. ~80 LoC, frozen v1 contract.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pub.dev/packages/fluttersdk_wind_diagnostics_contracts\"\u003e\u003cimg src=\"https://img.shields.io/pub/v/fluttersdk_wind_diagnostics_contracts.svg\" alt=\"pub package\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/fluttersdk/wind_diagnostics_contracts/actions\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/fluttersdk/wind_diagnostics_contracts/ci.yml?branch=develop\u0026label=CI\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pub.dev/packages/fluttersdk_wind_diagnostics_contracts/score\"\u003e\u003cimg src=\"https://img.shields.io/pub/points/fluttersdk_wind_diagnostics_contracts\" alt=\"pub points\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/fluttersdk/wind_diagnostics_contracts/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/fluttersdk/wind_diagnostics_contracts?style=flat\" alt=\"GitHub stars\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://fluttersdk.com/wind\"\u003eDocumentation\u003c/a\u003e ·\n  \u003ca href=\"https://pub.dev/packages/fluttersdk_wind_diagnostics_contracts\"\u003epub.dev\u003c/a\u003e ·\n  \u003ca href=\"https://github.com/fluttersdk/wind_diagnostics_contracts/issues\"\u003eIssues\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Use cases\n\nThis package is the integration seam for any tool that needs runtime Wind UI state without pulling Wind into its compile graph:\n\n- **LLM-agent E2E testing for Flutter**: MCP servers and AI assistants (Claude Code, Cursor, Copilot) that drive a Flutter app need structured widget state (className, breakpoint, brightness, platform, states, colors) per `Element`, not screenshots. This package is the typed contract those tools read.\n- **DevTools extensions**: build a custom Wind inspector tab in Dart DevTools without a hard `fluttersdk_wind` dependency that drags the rendering surface into the extension bundle.\n- **E2E drivers (`fluttersdk_dusk`, `patrol_mcp`, `marionette_mcp`, custom)**: emit a `wind:` block in snapshot YAML / JSON without importing Wind. Tests stop breaking when a className is renamed because the contract surfaces semantic state, not selectors.\n- **Tailwind-on-Flutter authors**: any styling library that follows Wind's className convention can implement this contract to expose its state to the same debug-tooling ecosystem.\n\n---\n\n## Why this package exists\n\n[Wind UI](https://github.com/fluttersdk/wind) ([pub.dev](https://pub.dev/packages/fluttersdk_wind)) exposes runtime widget state (`className`, `breakpoint`, `brightness`, `platform`, `states`, `bgColor`, `textColor`) that debug-tooling packages such as [`fluttersdk_dusk`](https://github.com/fluttersdk/dusk) ([pub.dev](https://pub.dev/packages/fluttersdk_dusk)) embed in their snapshot YAML so LLM agents can reason about the rendered tree.\n\nShipping that handoff through `fluttersdk_wind`'s own surface would force every debug-tool to compile-time depend on Wind, dragging the full rendering surface and bumping debug-tool builds on every Wind release. Shipping it the other way (Wind depending on each debug tool) is even worse.\n\n**This package breaks the loop.** Both sides depend on the abstract contract here; neither side imports the other.\n\n```\n                    fluttersdk_wind_diagnostics_contracts\n                              |\n              +---------------+---------------+\n              |                               |\n       fluttersdk_wind                  fluttersdk_dusk\n       (registers a resolver)         (reads the resolver\n                                       at snapshot time)\n```\n\nThe pattern mirrors Flutter's `*_platform_interface` convention. [`plugin_platform_interface`](https://pub.dev/packages/plugin_platform_interface) (the canonical precedent) sits at 4.97M downloads on pub.dev for exactly this reason.\n\n---\n\n## Install\n\n```bash\nflutter pub add fluttersdk_wind_diagnostics_contracts\n```\n\nMost consumers never add this dep by hand. `fluttersdk_wind` declares it as a direct production dependency, so any app that already depends on Wind picks it up transitively. Add it explicitly when you are authoring a debug-tooling package that reads Wind state without depending on Wind itself.\n\n---\n\n## Usage\n\n### Registering a resolver (in `fluttersdk_wind`)\n\nWind installs its concrete resolver at app boot, gated by `kDebugMode` so release builds tree-shake the entire registration site:\n\n```dart\nimport 'package:flutter/foundation.dart' show kDebugMode;\nimport 'package:fluttersdk_wind/fluttersdk_wind.dart';\n\nvoid main() {\n  if (kDebugMode) {\n    Wind.installDebugResolver();\n  }\n  runApp(const MyApp());\n}\n```\n\n`Wind.installDebugResolver()` is a one-liner inside `fluttersdk_wind` that does:\n\n```dart\nimport 'package:fluttersdk_wind_diagnostics_contracts/fluttersdk_wind_diagnostics_contracts.dart';\n\nWindDebugRegistry.register(const WindDebugResolverImpl());\n```\n\n### Reading the resolver (in a debug-tooling package)\n\nThe consumer looks up the currently-installed resolver and calls `resolve(element)` per `Element` it wants to inspect. The resolver returns `const {}` for non-Wind widgets, so the walk is safe for any element:\n\n```dart\nimport 'package:fluttersdk_wind_diagnostics_contracts/fluttersdk_wind_diagnostics_contracts.dart';\n\nvoid emitWindBlock(StringBuffer buffer, Element element) {\n  final WindDebugResolver? resolver = WindDebugRegistry.current;\n  if (resolver == null) return; // wind not in this app, or release build.\n\n  final Map\u003cString, Object?\u003e data = resolver.resolve(element);\n  if (data.isEmpty) return; // not a Wind widget.\n\n  buffer.writeln('wind:');\n  data.forEach((key, value) {\n    buffer.writeln('  $key: $value');\n  });\n}\n```\n\nThe returned map's key set is documented as the v1 frozen contract (see [CHANGELOG.md](CHANGELOG.md) for the full key list).\n\n### Test seams\n\n`WindDebugRegistry` exposes two `@visibleForTesting` helpers so debug-tool tests can register fake resolvers without going through Wind:\n\n```dart\nimport 'package:flutter_test/flutter_test.dart';\nimport 'package:fluttersdk_wind_diagnostics_contracts/fluttersdk_wind_diagnostics_contracts.dart';\n\nclass _FakeResolver implements WindDebugResolver {\n  @override\n  Map\u003cString, Object?\u003e resolve(Element element) {\n    return const \u003cString, Object?\u003e{\n      'className': 'flex p-4',\n      'breakpoint': 'lg',\n      'brightness': 'light',\n      'platform': 'web',\n      'states': \u003cString\u003e['hover'],\n    };\n  }\n}\n\nvoid main() {\n  setUp(() =\u003e WindDebugRegistry.resetForTesting());\n\n  testWidgets('observe emits wind block from registry', (tester) async {\n    WindDebugRegistry.registerForTesting(_FakeResolver());\n    // ... rest of the test ...\n  });\n}\n```\n\n---\n\n## Versioning\n\nThis package follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). The `WindDebugResolver.resolve` return-map key set is the load-bearing v1 contract: additive changes (new keys in the returned map) are non-breaking; renaming or removing existing keys requires a major bump.\n\n---\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttersdk%2Fwind_diagnostics_contracts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffluttersdk%2Fwind_diagnostics_contracts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttersdk%2Fwind_diagnostics_contracts/lists"}