Files
eryao/apps/AGENTS.md
T
qzl 1e22f27de2 feat: integrate invite API and improve notification handling
- Add invite code display and binding functionality via API
- Fix notification unread count sync on auth state change
- Improve notification mark read with server state validation
- Add auth state listener to trigger notification refresh
- Add YaoCoinConverter for coin-to-yao type conversion
- Remove YaoLegend from divination screens (UI cleanup)
- Abbreviate relation labels in yao detail view
- Add re-register notice to account delete screen
- Update 'coins' terminology to 'points' in localization
- Fix backend points consumption to only run in CHAT mode
- Add HttpxAuthNoiseFilter to suppress auth endpoint logging
- Fix notification static_schema import path
- Add test coverage for notification bloc error handling
- Update AGENTS.md page header rules and image handling
- Delete deprecated run-dev.sh script
2026-04-13 14:52:22 +08:00

10 KiB

Apps Domain Rules

This file governs apps/** (Flutter). Keep rules strict, short, and reusable.

Scope & Precedence

  • Inherits root AGENTS.md and workspace runtime rules.
  • If rules conflict, apply the stricter one.
  • Visual language source of truth: apps/rules/visual_design_language.md.

Flutter Directory Contract (Must)

  • apps/lib only allows these second-level directories: app/, core/, data/, features/, shared/, l10n/.
  • apps/lib/main.dart is the only allowed root entry file.
  • Do not add new second-level directories under apps/lib without explicit approval.

Module Responsibilities (Must)

  • app/: app bootstrap, DI wiring, global lifecycle orchestration, router composition.
  • core/: cross-feature business primitives/protocols/orchestrators (no feature-specific page logic).
  • data/: shared infrastructure only (cache/network/storage/adapters), not feature business repositories/models.
  • features/: user-facing bounded feature modules with clear product ownership.
  • shared/: reusable UI widgets and presentation helpers without feature business orchestration.
  • Cross-cutting capabilities (e.g. notification orchestration, UI schema protocol) must live in core/ + shared/, not under features/.

Placement Rules (Must)

  • Put code in features/ only when it belongs to one bounded product capability/screen flow.
  • Put code in core/ when it is cross-feature protocol, policy, or orchestration that does not belong to one feature.
  • Put reusable UI renderers in shared/widgets/; they must not contain feature-only business orchestration.
  • In feature data layers, use semantic subfolders: data/apis/, data/repositories/, data/services/, data/models/.
  • Avoid deep redundant nesting like models/<same_name>/...; prefer flat by concern.

Shared Data Layer Boundary (Must)

  • Do not place feature business repositories/models under apps/lib/data/.
  • Feature business repositories/models must live under each feature's data/ tree.
  • apps/lib/data/ is only for infrastructure abstractions and implementations (cache/network/storage), reusable by features.

UI Design System (Must)

  • Semantic colors: always use Theme.of(context).colorScheme.* (primary, surface, error, etc.). Never hardcode hex or Colors.*.
  • Brand palette colors (event presets, avatar colors, Eisenhower matrix quadrants): use Theme.of(context).extension<AppColorPalette>()!.*.
  • Spacing / Radius: use AppSpacing / AppRadius from design_tokens.dart. No hardcoded values.
  • AppTheme.light / AppTheme.dark provide complete ColorScheme (light + dark). MaterialApp wires them via theme: / darkTheme:.
  • If a semantic slot is missing from ColorScheme, add it to AppTheme — do not bypass colorScheme with hardcoded values.

Page Header (Must)

All sub-pages (sub-page = any page that is not a home Tab page) AppBar must follow:

  • centerTitle: true — title must be horizontally centered; never left-aligned.
  • backgroundColor and surfaceTintColor should match the page background to avoid visual seams.
  • Example:
appBar: AppBar(
  title: Text('Notifications'),
  centerTitle: true,
  backgroundColor: colors.surfaceContainerLow,
  surfaceTintColor: colors.surfaceContainerLow,
  actions: [...],
),
  • When a repeated pattern emerges, extract a reusable component into shared/widgets/ instead of building AppBar independently in each page.

Divination Terminology (Must)

  • Divination domain terminology must use fixed Chinese terms in code contracts, protocol fields, and UI semantic labels.
  • Do not localize or translate canonical terms such as: 六爻、爻、动爻、静爻、六亲、六神、世爻、应爻、伏神、月建、日辰、月破、日冲、空亡、五行旺衰。
  • Signature level labels (上上签/中上签/中下签) may be localized for UI display only, while protocol/storage values remain canonical Chinese.
  • l10n can translate explanatory copy, but must not alter canonical divination terminology semantics.

Reuse & Composition (Must)

  • Prefer apps/lib/shared/widgets/ before adding new components.
  • Extract repeated page structures/components; do not duplicate sibling-page scaffolds.
  • Detail page top-right actions must use shared action-menu components.
  • Destructive confirmations must use project-consistent shared surfaces.

Interaction & Feedback (Must)

  • User feedback: Toast / AppBanner only.
  • Loading indicators: AppLoadingIndicator only.
  • Form pages should default to keyboard-overlay behavior to avoid full-page layout jumps.
  • ToastType.info should be minimized: do not show informational toast for normal success paths (e.g., login success). Prefer silent success unless user must take action.

Interaction & Feedback (Must)

Agent Chat Protocol (Must)

  • Agent chat must follow AG-UI over SSE.
  • Lifecycle events are mandatory: RUN_STARTED and exactly one of RUN_FINISHED or RUN_ERROR.
  • Current default text delivery is finalized TEXT_MESSAGE_END payloads; do not require token-level TEXT_MESSAGE_CONTENT unless backend protocol explicitly enables it.

HTTP Error Parse Contract (Must)

  • Frontend must parse backend errors as RFC7807: type/title/status/detail/instance + extension code/params.
  • Error code registry single source of truth: docs/protocols/common/http-error-codes.md.
  • Frontend mapping must be based on documented code only (code -> l10n key), not inferred from detail text.
  • Any new/changed code requires protocol doc update first, then frontend mapping update.
  • Unknown code fallback order: status-generic localized message -> safe generic localized message.

High-Risk Modules (Must)

Auth

  • AuthBloc is the single source of truth.
  • 401 invalidation must go through global callback chain; no feature-level token clearing or direct login navigation.

Home Message Viewport

  • Home message auto-scroll/anchor restore must be event-driven.
  • Preserve viewport during history prepend and when user is reading above bottom.

Cache / Repository

  • Reads/writes that affect consistency must go through repository layer.
  • Cache keys and invalidation policy belong to repository, not UI/Bloc.
  • Shared cache infrastructure must live under apps/lib/data/cache/; feature modules must not duplicate low-level cache store logic.
  • Shared cache infrastructure (apps/lib/data/cache/) must remain domain-agnostic: do not import features/** or business model DTOs there.
  • Domain object serialization/deserialization belongs to repository/feature layer via local mappers/codecs; do not centralize feature-specific codecs in shared cache layer.
  • Shared cache layer may only encode/decode primitives, collections, and cache metadata wrappers.
  • Cache strategy default is SWR + TTL + invalidation/reload.
  • Local partial cache patching is allowed only for simple single-entity updates with clear rollback paths; complex cross-list/cross-feature states must invalidate and refetch.
  • Feature TTL policy must be defined in each feature repository; do not add centralized feature TTL registries in shared cache infra.
  • Runtime cache is hybrid (memory + local persistent) managed by DI singletons; do not create per-screen/per-widget cache store instances.
  • Cross-feature data access must go through app-level facade/usecase boundaries; do not import another feature's data implementation directly from UI/Bloc.
  • Repository instances should be resolved from DI singletons to reuse cache and avoid per-feature re-creation.

Reminder / Notification Rewrite Boundary

  • Reminder/notification data-interaction logic is under rewrite. Do not reintroduce local-notification scheduling/callback execution paths in apps/lib/data/services/.
  • During rewrite, keep protocol/orchestration in core/notification/** and reusable rendering in shared/widgets/notification/**.

Testing Policy

  • Prioritize tests for model parsing, service logic, and high-regression interaction flows.
  • Simple static UI changes may skip tests.
  • Auth/Home/Cache changes must include targeted regression tests.

Logging Conventions (Must)

Logger Setup

import 'core/logging/logger.dart';

class SomeBloc extends Cubit<SomeState> {
  final Logger _logger = getLogger('features.<feature>.<component>');
}

Log Level Policy

Level When to Use Noise Level
error All exceptions and failures - MUST log every error site Required, never skip
warning Degraded behavior, retry, fallback, malformed data Minimal, only when action taken
info Key business events (login, logout, send message) Minimal, only milestone events
debug Detailed flow tracing (only in debug builds) High, avoid in release

Error Logging Requirements

Every try-catch that handles an exception MUST log it:

try {
  await _repository.someOperation();
} catch (e, stackTrace) {
  _logger.error(
    message: 'Operation failed: $operationName',
    error: e,
    stackTrace: stackTrace,
    extra: {'context': 'relevant_data'},
  );
  // handle error
}

Info Logging Requirements

Only log these milestone events:

  • User login/logout
  • Message sent/received
  • Data sync completed
  • Important state transitions
_logger.info(
  message: 'User logged in',
  extra: {'user_id': user.id},
);

Warning Logging Requirements

Only log when taking corrective action:

  • Retrying after failure
  • Using fallback data
  • Skipping malformed data
  • Deprecation warnings
_logger.warning(
  message: 'Cache miss, loading from remote',
  extra: {'key': cacheKey},
);

Module Naming Convention

Feature Module Path
auth features.auth
calendar features.calendar
chat features.chat
contacts features.contacts
home features.home
messages features.messages
settings features.settings
todo features.todo

Prohibited Practices

  • Never log sensitive data: passwords, tokens, PII, message content
  • Never log at debug level in production (release mode)
  • Never skip error logging even if you "handle" the error
  • Never log for every iteration in loops - only on failures