Skip to content

docs(repo): add STYLE_GUIDE.md and TESTING.md adapted from Flutter's guides#125

Open
xsahil03x wants to merge 25 commits into
mainfrom
docs/style-guide
Open

docs(repo): add STYLE_GUIDE.md and TESTING.md adapted from Flutter's guides#125
xsahil03x wants to merge 25 commits into
mainfrom
docs/style-guide

Conversation

@xsahil03x

@xsahil03x xsahil03x commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds STYLE_GUIDE.md at the repo root — a canonical style guide adapted from Flutter's repo style guide, reshaped for the design-system + LLC-transport structure of this repo.
  • Adds TESTING.md at the repo root — a companion doc on how to write good tests adapted from Flutter's Writing-Effective-Tests.
  • Wires CLAUDE.md to open with a pointer directing AI agents to read STYLE_GUIDE.md before writing or reviewing code, plus a TESTING.md link for test-writing tasks.

Mirrors the equivalent PR in stream-chat-flutter #2793, tuned for this repo's actual conventions.

What's in STYLE_GUIDE

  • Quick rules — a scannable checklist near the top with the hard rules (barrel contract, line width, relative imports inside lib/src/, private-member commenting, changelog labels, no InheritedWidget lookup in initState, named boolean parameters, file_names, directives_ordering).
  • Philosophy — layering (stream_corestream_core_flutter), avoiding secret state, error-message quality, streams as primary reactive primitive for real-time data.
  • Repository structure — monorepo layout, Melos-managed deps, generated code, and — critically — the public barrel contract (core.dart vs chat.dart, melos run check:barrels enforcement).
  • Documentation — dartdoc conventions, plus repo-specific rules (public docs describe the contract not the implementation, no Flutter internals in comments, private members use // not ///).
  • Coding patterns — asserts (no message required here — prefer_asserts_with_message is disabled), dispose lifecycle, equality boilerplates, dot shorthands, strict-inference / strict-raw-types implications, no InheritedWidget lookup in initState, early-return pattern, relative-imports convention.
  • Testing — self-contained tests, mocktail, alchemist golden tests, test/components/<name>/goldens/{ci,macos} layout. Points at TESTING.md for writing-style guidance.
  • Widgets, themes, and design system — the component/theme/golden/Widgetbook 4-artifact rule, the theme hierarchy (primitives → semantics → components → tokens), @themeGen for component themes vs @ThemeExtensions(constructor: 'raw', ...) for the root StreamTheme, defaults in widget build (Flutter's AppBar/TabBar pattern), icon generation from SVGs.
  • Naming, comments, formatting, commits/PRs/changelogs — the usual sections, with rules that match verified repo practice.

What's in TESTING.md

Four principles from Flutter's Writing-Effective-Tests with Stream-Core-flavoured examples using StreamAvatar, StreamAvatarSize, StreamMessageBubble:

  1. Name tests based on the behavior being tested, not the object.
  2. One behavior per test.
  3. Only include relevant details — extract setup into named helpers.
  4. Optimize for comprehension — separate "the thing under test" from "the actions on it".
  5. Bonus: golden tests are behavioural tests too — name them after the variant being pinned, not the widget.

Divergences from Flutter's guide

Called out inline every time; the notable ones:

  • Relative imports inside lib/src/ — this repo has always_use_package_imports: false. Flutter's guide requires package: imports; we prefer relative paths inside a package for refactor safety.
  • Bare // ignore: directives and bare // TODO: (with optional category tag like TODO(localize):, not GitHub handles) match repo practice.
  • Assert messages not requiredprefer_asserts_with_message is disabled here.
  • Streams as the primary reactive primitive for WS/RxDart pipelines. Flutter recommends Listenable; that reasoning doesn't apply to a real-time transport layer.
  • Private members use //, not ///.
  • Line width 120, not 100.

Verified against the repo before merging

  • Root theme class is StreamTheme (extends ThemeExtension<StreamTheme>) — there is no StreamThemeData. Fixed in the guide.
  • Component categories list matches lib/src/components/ (17 categories, not the 10 previously in CLAUDE.md).
  • Widgetbook use-cases live under apps/design_system_gallery/lib/components/, not /use_cases/.
  • StreamAvatarSize enum values (xs, sm, md, lg, xl, xxl) — the switch example uses correct radii.
  • No BetterStreamBuilder reference (that class lives in stream-chat-flutter, not here).
  • TESTING.md examples use only real APIs (StreamAvatar, StreamAvatarSize, StreamMessageBubble, StreamWsClient).
  • Changelog labels (### ✨ Features, ### 🐛 Bug Fixes, ### 🛑 Breaking / Removals) match current package changelogs, with grandfathered ### 🐞 Fixed / ### 💥 BREAKING CHANGES noted.
  • Theming section describes @themeGen for component themes and @ThemeExtensions(constructor: 'raw', ...) for the root — verified against stream_theme.dart and stream_avatar_theme.dart.
  • Extension-methods section distinguishes domain-typed collections (fine) from unconstrained-type extensions (avoid new ones).

Test plan

  • Skim the "Quick rules" section — every bullet links to its full section below.
  • Read TESTING.md end-to-end — it's short (~210 lines).
  • Verify divergences from Flutter's guide match your read of current repo practice.
  • Confirm the barrel-contract wording matches your check_barrels.yaml intent.
  • Suggest anything missing (a rule you rely on that isn't captured, an example that would help).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added a repository style guide covering coding conventions, API boundaries, testing expectations, formatting rules, and component implementation standards.
    • Expanded testing guidance with clearer advice on writing behavior-focused, readable, and maintainable tests.
    • Updated the main contributor guidance to point readers to the style guide as the primary source for repository conventions.

…guides

Adapts Flutter's Style-guide-for-Flutter-repo and Writing-Effective-Tests
for stream-core-flutter, with divergences called out inline. CLAUDE.md now
opens with a pointer directing agents to read both docs before writing or
reviewing code.

Repo-specific rules captured beyond the Flutter guide:
- Public barrel contract (core.dart / chat.dart, check:barrels lint).
- Relative imports inside lib/src/ (always_use_package_imports disabled).
- Component + theme + golden + Widgetbook use-case are all shipped
  together for every new widget.
- Theme system: @themeGen for component themes, @ThemeExtensions for the
  root StreamTheme (which is itself the ThemeExtension, no separate
  StreamThemeData); defaults live in the widget's build via
  null-coalescing, mirroring Flutter's AppBar/TabBar pattern.
- Icons are generated from SVGs; melos run generate:icons.
- CHANGELOG labels: `### ✨ Features`, `### 🐛 Bug Fixes`,
  `### 🛑 Breaking / Removals`.
- Assert messages not required (prefer_asserts_with_message disabled).
- `avoid_print` disabled repo-wide but prefer `debugPrint` in Flutter code.

Divergences from Flutter's guide:
- Line width 120 (not 100).
- Relative imports inside lib/src/ (Flutter's guide requires package: imports).
- Bare `// ignore:` and `// TODO:` (Flutter requires rationale / handle).
- Streams are the primary reactive primitive for real-time data (Flutter
  prefers Listenable inside framework).
- Private members use `//`, not `///`.

Verified against actual repo state before publishing: component category
list matches lib/src/components, Widgetbook use-cases live under
apps/design_system_gallery/lib/components (not /use_cases), root theme is
StreamTheme (not StreamThemeData), StreamAvatarSize values checked, no
BetterStreamBuilder reference (it lives in stream-chat-flutter, not here).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@xsahil03x xsahil03x requested a review from a team as a code owner July 1, 2026 13:48
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@xsahil03x, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 9 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 45835c41-2ca5-463e-b1b4-fef4df74ed1f

📥 Commits

Reviewing files that changed from the base of the PR and between a3de967 and a244a26.

📒 Files selected for processing (1)
  • STYLE_GUIDE.md
📝 Walkthrough

Walkthrough

Adds documentation only: CLAUDE.md gains a pointer to a new STYLE_GUIDE.md; STYLE_GUIDE.md introduces a comprehensive Dart/Flutter/Widgetbook style guide for the monorepo covering API design, coding, testing, naming, formatting, and design-system conventions; TESTING.md adds a guide on writing effective tests.

Changes

Documentation additions

Layer / File(s) Summary
Style guide pointer
CLAUDE.md
Adds an instruction directing readers to consult STYLE_GUIDE.md before writing or reviewing code.
Style guide intro and API design philosophy
STYLE_GUIDE.md
Introduces guide intent/audience, a quick-rules checklist, and API design philosophy (lazy programming, test-first, layering, workarounds, abandonware/deprecation, licensing).
Repo structure, barrels, and dartdoc rules
STYLE_GUIDE.md
Defines monorepo/barrel conventions, Melos dependency management, generated code handling, and dartdoc documentation requirements.
Coding patterns and testing/naming conventions
STYLE_GUIDE.md
Covers lint-enforced coding patterns (asserts, typing, equality, dispose, Result<T> error handling) plus testing and naming/spelling conventions.
Comment style and formatting rules
STYLE_GUIDE.md
Defines comment conventions and formatting/process standards (Melos formatting, member ordering, braces, double literals).
Design-system requirements and PR/changelog process
STYLE_GUIDE.md
Details design-system component/theme/icon requirements, PR title conventions, changelog formatting, and doc navigation pointers.
TESTING.md test-writing guide
TESTING.md
Adds a guide covering test naming by behavior, one-behavior-per-test, extracting setup helpers, readability structuring, and golden test conventions.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed, but it omits required template sections like Linear, GitHub Issue, CLA checkboxes, and Screenshots/Videos. Add the missing template sections and fill in Linear/GitHub Issue, CLA status, testing details, and screenshots/videos if applicable.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the two new documentation files and that they are adapted from Flutter's guides.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/style-guide

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

- Test files live at `test/components/<category>/<name>_test.dart` (or
  `_golden_test.dart` for the golden variant), not `test/components/<name>/`
  as previously claimed. Verified against packages/stream_core_flutter/test.
- Golden config: only `goldens/ci/*.png` gets committed; platform goldens
  (e.g. `goldens/macos/`) are auto-generated locally by alchemist and
  gitignored. Fixed the misleading "for local macOS development" phrasing
  and explained the actual flutter_test_config.dart setup.

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

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 37.26%. Comparing base (31ca84f) to head (a244a26).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #125   +/-   ##
=======================================
  Coverage   37.26%   37.26%           
=======================================
  Files         175      175           
  Lines        6986     6986           
=======================================
  Hits         2603     2603           
  Misses       4383     4383           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Barrel contract: reframe as extensible — chat.dart is one of possibly
  many product barrels (video.dart, feeds.dart, ...) added as new Stream
  products need domain-specific widgets. Adjusts wording and rules to
  cover the general pattern.
- Style vs ThemeData: name the actual convention. Top-level component
  themes use <Component>ThemeData; sub-configurations nested inside them
  use <Component>Style. Grandfathered top-level Style themes exist; don't
  add more.
- Widget essentials: explicitly aspirational for new widgets — some
  earlier components predate parts of the checklist; close gaps
  opportunistically, don't block landings on backfill.
- Component factory: name the concrete reference
  (StreamMessageBubble + StreamComponentFactory.of(context).messageBubble)
  so a contributor has a working example to copy.

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

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
STYLE_GUIDE.md (1)

253-257: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the public logger export in the style guide packages/stream_core/lib/stream_core.dart already exports src/logger.dart, so point readers at package:stream_core/stream_core.dart instead of the internal stream_core/src/logger/ path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@STYLE_GUIDE.md` around lines 253 - 257, The style guide currently points
readers to the internal logger path, but the public export already exists.
Update the guidance in STYLE_GUIDE.md to reference the Logger via
package:stream_core/stream_core.dart instead of stream_core/src/logger/, and
keep the note about using debugPrint in stream_core_flutter where appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@STYLE_GUIDE.md`:
- Around line 1117-1130: The deliverables checklist is inconsistent because it
enumerates five required items but ends with “any of the four.” Update the
summary in STYLE_GUIDE.md to say “any of the five” so it matches the listed
deliverables (Widget file, Theme file, Golden test, Widgetbook use-case, and
Barrel export).

---

Nitpick comments:
In `@STYLE_GUIDE.md`:
- Around line 253-257: The style guide currently points readers to the internal
logger path, but the public export already exists. Update the guidance in
STYLE_GUIDE.md to reference the Logger via package:stream_core/stream_core.dart
instead of stream_core/src/logger/, and keep the note about using debugPrint in
stream_core_flutter where appropriate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 14be598c-ffda-4ad9-8419-54928c9b02a3

📥 Commits

Reviewing files that changed from the base of the PR and between 31ca84f and d70a1da.

📒 Files selected for processing (3)
  • CLAUDE.md
  • STYLE_GUIDE.md
  • TESTING.md

Comment thread STYLE_GUIDE.md Outdated
xsahil03x and others added 15 commits July 1, 2026 16:01
Verified against the SDK: only one extension on a common Dart type exists
(DistanceExtension on num, for units-of-measure ergonomics). BuildContext
extensions for scoped lookups (StreamThemeExtension, StreamComponentFactoryExtension)
also exist and are idiomatic. Rewrote the rule to name both patterns as
accepted, plus the general "avoid" list still stands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l utils

Reviewed packages/stream_core/lib/src/utils/:

- Extensions section: my rule was way off. The repo has an intentional
  standard-library-style extension layer (Standard on T for let/apply/
  takeIf, IterableExtensions, ListExtensions, SortedListExtensions,
  ComparableExtension) exported from stream_core.dart and used in 100+
  files. Rewrote the section to describe the layer, direct new utility
  work into utils/, and keep the "avoid" list narrower.

- Reactive primitives: raw Stream + ValueNotifier framing was wrong. The
  repo uses SharedEmitter (SharedFlow-equivalent) and StateEmitter
  (StateFlow-equivalent) as its primary reactive types — both implement
  Stream<T> under the hood. Rewrote to describe when to reach for each,
  with StateEmitter preferred over ValueNotifier for cross-boundary
  state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The reactive-state and product-SDK guidance was framed around
SharedEmitter/StateEmitter — that's stream_core's transport-layer
internals, not the pattern new product SDKs should follow. Reviewed
stream-feeds-flutter's AGENTS.md (the current reference for "latest
architecture") and refactored the guide:

- Reactive state now has three explicit layers:
  1. Product-SDK state → StateNotifier (from package:state_notifier)
     with @freezed State classes. Points at stream-feeds-flutter as the
     reference. Client → Repository → StateNotifier → State.
  2. Transport-layer state → existing SharedEmitter/StateEmitter (kept
     documented; not deprecated, just scoped to internal WS/connection
     state).
  3. Widget-owned state → ValueNotifier/ChangeNotifier (unchanged).
- New section: "Error handling with Result<T>". Verified this is already
  an established convention here (StreamAttachmentUploader, CdnClient
  already return Future<Result<T>>). Repository/public methods return
  Result; never throw across SDK boundary.
- New section: "Reference architecture: stream-feeds-flutter". Diagrams
  the Client/Repository/StateNotifier/State layering and points at the
  feeds AGENTS.md for the full pattern (freezed 3.0 mixed mode,
  *Data / *Query / *Request naming, public/internal split).
- Testing section adds a note for product-SDK tests: public-API-only,
  typed test helpers (feedsClientTest / feedTest), mock exact requests
  not any(). All mirrors feeds's testing philosophy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The user is going to write a dedicated style guide in the feeds repo
itself. The architectural guidance stays (StateNotifier for new state,
Result pattern, Client/Repository/StateNotifier/State layering, freezed
3.0 mixed mode, *Data/*Query/*Request naming, public-API-only testing,
mock-exact-requests) but is now presented as generic Stream SDK
patterns rather than "the pattern documented in feeds":

- "Reference architecture: stream-feeds-flutter" section renamed to
  "Product-SDK architecture" and no longer links to feeds AGENTS.md.
- Reactive-state section no longer names feeds as the reference
  implementation.
- Testing section no longer names feedsClientTest / feedTest; instead
  says each product SDK ships its own `<Product>ClientTest` /
  `<Product>Test` helper.
- Kept the forward-looking `feeds.dart` mention in the barrel section
  as an example of a possible future product barrel — not a link.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reviewed against Flutter's original style guide, which favours short
rules + code samples over long prose. Applied to the three most verbose
sections:

- Reactive state (was 55 lines of layered prose): collapsed to 20 lines,
  three bullets + a short paragraph. No new information; just tighter.
- Guidelines for extensions (was 45 lines with a bulleted list of every
  helper in utils/): tightened to 20 lines with the utils-layer as a
  single sentence and three positive extension patterns as bullets.
- Theme system (was 60 lines of numbered steps with prose): rewrote
  around two code samples — the theme file skeleton (annotation, mixin,
  InheritedTheme, of() lookup with merge) and the widget consumption
  pattern (null-coalescing defaults in build). Code carries the shape;
  prose only explains what code can't show.

Added code samples where they replaced prose:

- Product-SDK architecture: added a StateNotifier + @freezed State +
  public-wrapper skeleton so a contributor has a copy-paste starting
  point.
- Error handling with Result<T>: added a repository-method sample and a
  consumer switch pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
StateNotifier isn't a divergence from Flutter's Listenable-over-Stream
guidance. It's the pure-Dart equivalent of ValueNotifier, used only
because Listenable lives in package:flutter/foundation.dart and can't
be reached from a pure-Dart LLC. In the Flutter widget layer we still
use ValueNotifier / ChangeNotifier, matching Flutter's own conventions.

Rewrote the Reactive state section to say this explicitly:
- Pure-Dart product SDKs: StateNotifier (= ValueNotifier for pure Dart).
- Flutter widget code: ValueNotifier / ChangeNotifier.
- Transport internals only: SharedEmitter / StateEmitter.

Removed the "This intentionally diverges from Flutter's style guide"
paragraph — Flutter's guide is about avoiding streams inside framework
code, which is different from what we do here.

Also tagged Product-SDK architecture as "pure-Dart product SDKs" so
readers don't apply the Client → Repository → StateNotifier layering
to Flutter UI packages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
stream-core-flutter is transport + design system; it doesn't own a
state layer. The Client → Repository → StateNotifier → State
architecture applies to product SDKs built on top (Chat LLC, Feeds
LLC, ...), not to this repo. Documenting it here bloats the guide with
patterns that belong in each product SDK's own guide.

- Deleted the whole "Product-SDK architecture" section (~55 lines).
- Trimmed the reactive-state section to just what this repo actually
  uses: SharedEmitter/StateEmitter for transport internals and
  ValueNotifier/ChangeNotifier for widget-owned state. StateNotifier
  moved out; it's a product-SDK concern.
- Trimmed the Result<T> section: no more "repositories, clients" —
  just "public methods that can fail". Sample code now uses CdnClient
  (which actually exists here) instead of a fictional User API.
- Removed the product-SDK paragraph from the Testing section for the
  same reason.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tually follow

The Flutter-guide "Each API should be self-contained and should not know
about other features" doesn't describe stream-core-flutter's design
system. Components compose deliberately here — StreamComponentFactory
ties them together, the theme hierarchy (primitives → semantics →
components) is composition-first, and message-layer widgets reference
each other by design.

Renamed the section to "Prefer immutable data", kept the parts that are
actually true (immutable value classes and copyWith, agnostic `child`
parameters), and added a note calling out that inter-component coupling
is intentional in the design system layer, not a violation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous opening warned "misuse pollutes IDE suggestions, reach for a
regular method first" and then celebrated a standard-library-style
extension layer we use freely. The two didn't square. Rewrote to lead
with what we actually do (add to utils/), then list accepted extension
targets outside utils/, then the actual "avoid" list, and finally a
narrower note about static resolution (framed as "when to use an
instance method instead" — not as a blanket caution).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The section was violating the guide's own "docs describe the contract,
not implementation" rule — enumerating internal classes (Standard,
IterableExtensions, ListExtensions, ...), naming specific methods
(let/also/apply/takeIf), citing a "100+ call sites" stat, and giving
concrete examples like AttachmentFile / DioException / DistanceExtension.

Rewrote to state the rule abstractly: new utility extensions go in
utils/, accepted extension targets described by category (domain types,
BuildContext, primitives for units-of-measure), and the avoid list
stays as-is. One file path reference is kept because contributors need
to know where to add code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The `stream_core/lib/src/utils/` path is also implementation detail —
if the layer ever moves, the guide would lie. Refer to it as "the
shared utils layer" and let contributors navigate to it the same way
they'd navigate to any other convention in the repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same treatment as the extensions section: it's a guide, not impl
detail. Removed the internal file path (stream_core/lib/src/utils/),
the internal class enumeration (SharedEmitter, StateEmitter,
MutableSharedEmitter, MutableStateEmitter), the SharedFlow/StateFlow
educational aside, and the internal package reference
(stream_core_flutter).

Kept public Flutter/Dart types (Listenable, ValueNotifier,
ChangeNotifier, StreamSubscription) — those are the contract callers
work against.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ection

Symmetric with how we already name Listenable / ValueNotifier /
ChangeNotifier for the Flutter layer. Both are the exposed contract
for their respective layers; either name both or name neither.

Kept the mutable-flavor types (MutableSharedEmitter,
MutableStateEmitter) out — those are implementation detail; the
read-only interfaces are the contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-types warning

Replaced our reworked extensions section with Flutter's original text
from the style guide. Kept everything up through the collision rule;
dropped the "Avoid creating public extension methods on common types
from the Dart SDK" paragraph, because we intentionally maintain a
shared utils layer that extends common types (Standard on T,
IterableExtensions, etc.), and warning against it would contradict
established practice here.

Also changed "separate Flutter libraries" to "separate libraries" —
the surrounding text is now generic, and the Flutter framing was tied
to the source repo, not to our conventions.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
STYLE_GUIDE.md (1)

1153-1174: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the checklist count to five.

The list now has five required deliverables, so “any of the four” is stale and makes the policy inconsistent.

Suggested fix
- Missing any of the four is a review-blocker.
+ Missing any of the five is a review-blocker.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@STYLE_GUIDE.md` around lines 1153 - 1174, The checklist in STYLE_GUIDE.md is
outdated and still says “any of the four” even though the required deliverables
now total five. Update the closing policy text in the component deliverables
list to reflect five items, and keep the wording consistent with the existing
bullets around Widget file, Theme file, tests, Widgetbook use-case, and Barrel
export so the review-blocker rule matches the current requirements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@STYLE_GUIDE.md`:
- Around line 1153-1174: The checklist in STYLE_GUIDE.md is outdated and still
says “any of the four” even though the required deliverables now total five.
Update the closing policy text in the component deliverables list to reflect
five items, and keep the wording consistent with the existing bullets around
Widget file, Theme file, tests, Widgetbook use-case, and Barrel export so the
review-blocker rule matches the current requirements.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0aaaf98e-d6c5-4eeb-99e8-b167cdc343c1

📥 Commits

Reviewing files that changed from the base of the PR and between d70a1da and a3de967.

📒 Files selected for processing (1)
  • STYLE_GUIDE.md

xsahil03x and others added 6 commits July 1, 2026 17:24
- Renamed "Reactive state" to "Use of streams and Listenables", matching
  Flutter's parallel section shape ("Use of streams in Flutter framework
  code"). The rule is now: at the Flutter widget layer, prefer Listenable
  subclasses over Stream, for the reasons Flutter cites (heavy API, no
  current-value accessor, non-trivial transformers). At the transport
  layer, streams are the natural primitive — SharedEmitter/StateEmitter.
- Removed "we prefer" / "we" phrasing throughout — the guide states
  rules, not preferences.
- Removed the meta trailer about product SDKs choosing their own
  primitives — that's commentary about other guides, not a rule that
  applies to code in this repo.
- Removed the Error handling with Result<T> section entirely. Result is
  used in a few transport-layer places (CDN client, attachment
  uploader) rather than as a repo-wide convention, so it doesn't need
  to be a first-class rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous wording claimed transport-layer state has "no meaningful
current value at every moment", which is wrong: StateEmitter has .value
(Kotlin StateFlow equivalent) and SharedEmitter supports replay for
late subscribers. Fixed the paragraph to describe what each primitive
actually does.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ams section

The bullet came from Flutter's original guide, where it holds because
Flutter only has raw Stream<T>. Here, StateEmitter extends Stream<T>
and exposes .value, so the blanket "streams don't have a current-value
accessor" reads as inconsistent with the transport-layer paragraph
below that names StateEmitter's current-value accessor.

The remaining two bullets (heavy API, non-trivial transformers) still
support the widget-layer preference for Listenable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…m vs Listenable

Rule is: never use raw Stream in this repo, always the emitters. Which
makes the Flutter-style "Stream vs Listenable at widget layer" framing
the wrong shape. Rewrote as "two primitives cover reactive state":

- SharedEmitter / StateEmitter for stream-like reactive data.
- Listenable subclasses for widget-owned state at the Flutter layer.

Ends with the explicit rule: don't use raw Stream directly, reach for
emitters. Section renamed from "Use of streams and Listenables" to
"Reactive primitives" — the previous title was inaccurate since we're
prescribing against raw streams.

Dropped the "streams have heavy API / non-trivial transformers"
justification bullets — they argued for Listenable over raw Stream,
which is no longer the choice a contributor has to make.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reworked the section to mirror Flutter's "Use of streams in Flutter
framework code" structure and cadence: opens with "In general we avoid",
notes streams are fine in general, gives the reasons via "For example:"
bullets, concludes with "We generally prefer" naming the preferred
alternative.

Header changed to "Use of `Stream`s" to match Flutter's title shape.
Body names our two emitter primitives (SharedEmitter for broadcast,
StateEmitter for state with a current value), and adds a short trailing
paragraph for the Flutter widget layer's Listenable preference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ecklists

Final cleanup pass after full-doc review. Three categories:

Philosophy — dropped four Flutter aphorisms that don't guide anyone
reviewing code here (Avoid interleaving multiple concepts together,
Prefer general APIs but use dedicated APIs where there is a reason,
Avoid heuristics and magic, Solve real problems by literally solving a
real problem). Renamed "Getters feel faster than methods" to "Getters
should be cheap" and tightened it around what the rule actually is.

Impl-detail leaks — dropped RxDart/Dio from the Layers and Monorepo
layout diagrams (now say "pure Dart transport layer"). Removed the
internal Logger path and the analysis_options lint-state trivia from
"Only log actionable messages". Component factory section no longer
names specific file paths or the StreamMessageBubble reference —
describes the pattern abstractly. Component structure section no
longer enumerates all 17 category directories (drifts on every new
one). "Where to look" Design tokens bullet drops the internal path.

Redundancy — folded Widget essentials into Component structure. The
two sections were doubling up on tests / Widgetbook / docs. Now one
section covers "each component ships with" (artifacts) and "the widget
itself should" (behavior).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The guide is advice by design — cutting Philosophy sections because they
were "abstract" was the wrong move. Restored:

- Prefer general APIs, but use dedicated APIs where there is a reason.
- Avoid heuristics and magic.
- Solve real problems by literally solving a real problem. (Dropped the
  "internal Stream product team / external integrator" audience-mismatch
  parenthetical; kept the core advice.)

Also added a small "Prefer immutable data" section for the two rules
that lived inside the deleted "Avoid interleaving" section — widgets
agnostic about their `child`'s runtime type, and immutable value
classes via copyWith. The abstract "Each API self-contained, no
knowledge of other features" framing stays deleted (we don't follow
it), but the two concrete rules under it are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant