Files
social-app/apps/AGENTS.md
T
qzl 524b91f454 docs: update AGENTS.md with new guidelines
- Add ui-ux-pro-max skill reference
- Add keyboard overlay behavior rules for Flutter
- Update testing strategy to prioritize high-regression flows
- Add copy priority rules for auth and form pages
- Update minimal interface copy guidelines
2026-03-19 18:43:23 +08:00

12 KiB

Flutter Mobile Development Constraints

This document defines hard constraints for Flutter mobile development. Treat all items as non-negotiable unless explicitly overridden.

0) Scope and Precedence (MUST)

  • This file applies to all changes under apps/**.
  • It extends root routing rules in AGENTS.md and workspace global runtime rules.
  • It also incorporates the visual design language from apps/rules/visual_design_language.md as a binding constraint.
  • If rules conflict, apply the stricter requirement.
  • Keep Flutter-specific constraints in this file; avoid duplicating them in root AGENTS.md.

1) Design Tokens (MUST)

  • MUST use design tokens from apps/lib/core/theme/design_tokens.dart:
    • Colors: AppColors.*
    • Spacing: AppSpacing.*
    • Radius: AppRadius.*
  • MUST NOT hardcode any visual values.
  • Design tokens are the single source of truth for all visual values. Any missing visual semantics should be added to tokens, not approximated locally.
  • This ensures consistency with the visual design language defined in apps/rules/visual_design_language.md.

2) Component Architecture (MUST)

  • SHOULD extract repeated UI patterns into reusable components.
  • SHOULD prefer existing shared components before creating new ones.
  • SHOULD place reusable components in apps/lib/shared/widgets/ following existing naming conventions.
  • MUST NOT introduce parallel UI systems (e.g., custom button styles, custom loading indicators) that duplicate existing shared components.
  • When creating new UI components, ensure they follow the design tokens and visual design language.

2.1) Navigation/Header Reuse Rules (MUST)

  • For page groups with clear parent-child relationships (e.g., Settings and its subpages), MUST use one shared header pattern: back button + page title.
  • MUST extract shared page scaffolds/header wrappers instead of duplicating SafeArea + header + scroll structures across sibling pages.
  • Detail-page right-side actions (edit/delete/share etc.) MUST use a shared action-menu component, not per-page ad-hoc button groups.
  • Header action menus MUST NOT overlap the trigger button area; menu surfaces should open below/right-aligned to the trigger and preserve title readability.

2.2) Interaction Surface Reuse Rules (MUST)

  • Repeated state-switch controls (toggle/switch UI) MUST be extracted into shared widgets.
  • Destructive confirmations (delete/remove) MUST use shared project-style confirmation surfaces (e.g., unified action sheet), not platform-default dialog styles.
  • MUST NOT use raw platform-default popup/dialog/dropdown visuals when they break project visual language; use token-driven shared components instead.

3) Layout Mapping & Alignment (MUST)

  • MUST explicitly set crossAxisAlignment for every Row / Column (do not rely on defaults).
  • MUST preserve layout semantics from root to leaf:
    • alignment/justification intent must be explicitly represented in Flutter widgets.
  • MUST NOT skip necessary container layers if doing so loses layout meaning or makes mapping non-traceable.

4) Centering & Visual Balance (MUST)

  • MUST evaluate centering within SafeArea usable bounds (not full-screen bounds).
  • MUST NOT rely on Spacer / proportional flex as the only centering mechanism for critical content.
  • If persistent header/footer regions exist, MUST center primary content within the remaining usable region.
  • MUST prioritize visual centering over purely geometric centering when they differ.

4.1) Keyboard Overlay Behavior (MUST)

  • For pages with text input, keyboard appearance MUST prefer overlay behavior and avoid reflowing the whole page.
  • Input pages MUST avoid global layout jump when keyboard opens/closes (including subtle shifts caused by safe-area padding changes).
  • Default strategy for full-screen pages with fixed hierarchy: Scaffold.resizeToAvoidBottomInset = false.
  • If a page truly requires keyboard-driven scrolling to keep focused fields reachable, this must be an explicit opt-in and justified by page structure.
  • When using SafeArea on keyboard-overlay pages, MUST stabilize bottom safe-area behavior (for example, maintain bottom view padding) to prevent center recalculation jitter.

5) Testing Strategy (MUST)

Follow lightweight testing strategy - prioritize value over coverage:

Write tests for:

  • Model / DTO parsing (json → model)
  • Service layer logic (business rules, API call handling)
  • High-regression UI interaction flows only (multi-state/multi-step widgets, viewport/scroll decision logic, route return stability)

Default skip for UI tests:

  • Simple UI pages, regular buttons, basic layouts
  • Pure visual structure/snapshot-like checks without behavior risk
  • Low-risk styling and static rendering changes

UI test policy:

  • UI tests are opt-in, not default; only keep or add them when failure risk is high and there is clear regression value.
  • If a UI test does not protect critical interaction behavior, remove it or avoid adding it.

6) UI Feedback System (MUST)

  • All user-facing feedback MUST use the Toast system.
    • Transient notifications: Toast.show(...)
    • Persistent inline form errors: AppBanner
  • MUST NOT create custom SnackBar/Dialog/Banner feedback components.
  • MUST NOT use raw ScaffoldMessenger for feedback messaging.

6.1) Loading Indicator System (MUST)

  • All loading spinners MUST use AppLoadingIndicator from apps/lib/shared/widgets/app_loading_indicator.dart.
  • MUST NOT use raw CircularProgressIndicator directly in feature/page code.
  • Use variants consistently:
    • page/surface loading: AppLoadingVariant.surface
    • inline small loading (list/search/section): AppLoadingVariant.inline
    • button loading: AppLoadingVariant.button
  • If visual semantics are missing, extend AppLoadingIndicator variant mapping first; do not create ad-hoc loading styles in feature files.

7) Agent Chat (AG-UI Protocol) (MUST)

Agent chat functionality MUST follow the AG-UI protocol. Use the ag-ui skill for protocol reference and implementation guidance.

  • MUST use Server-Sent Events (SSE) for streaming.
  • MUST emit required lifecycle events:
    • RUN_STARTED is required for every run
    • End with exactly one of: RUN_FINISHED or RUN_ERROR
  • MUST follow standard text streaming flow:
    • TEXT_MESSAGE_STARTTEXT_MESSAGE_CONTENT (delta) → TEXT_MESSAGE_END
  • MUST support the standard AG-UI event type set as defined in the spec.
  • MUST NOT return non-streaming responses for agent chat.
  • MUST NOT omit required lifecycle events.
  • MUST NOT use non-AG-UI event formats (except where the spec explicitly allows).

8) Visual Design Language (MUST)

All UI/UX work MUST follow the visual design language defined in apps/rules/visual_design_language.md.

  • MUST ensure screens feel like a premium personal assistant product, not a wireframe, admin console, or document page.
  • MUST apply the surface-based design system (background, primary, secondary, interactive surfaces).
  • MUST follow the motion and interaction feel guidelines (soft, responsive, premium).
  • MUST achieve visual hierarchy through spacing, surface grouping, radius, depth, density, contrast, scale, and motion—not color alone.
  • MUST prioritize compact informational delivery in top bars: when the page purpose can be clearly expressed by a concise header title, avoid repeating equivalent explanatory hints in the body.
  • MUST NOT duplicate page identity text between header and first content block unless the repeated text introduces new decision-critical information.
  • MUST keep interface copy minimal and action-oriented: every text node must justify its presence by either enabling a decision, reducing error risk, or satisfying compliance requirements.
  • MUST NOT stack multiple instructional hints around the same control (for example title + subtitle + placeholder + helper text all repeating the same meaning).
  • MUST follow copy priority for auth and form pages: Primary action > Required input labels > Error/recovery > Compliance. Secondary explanatory copy should be removed when users can complete the task without it.
  • MUST ensure each form field has at most one primary hint source in normal state (prefer placeholder or label, not both with duplicated wording).
  • MUST follow the screen-level decision rules:
    1. What is the primary focus?
    2. What is the surface hierarchy?
    3. What needs strongest emphasis?
    4. What should be grouped?
    5. What should be lightweight/secondary?
    6. Where should motion reinforce understanding?
    7. How can the result feel more like a premium assistant app and less like a document page?
  • MUST NOT create UIs that match the anti-patterns listed in the visual design language document:
    • plain document page, white slab with blue buttons, spreadsheet-like admin panel
    • low-fidelity wireframe, default Flutter demo app, generic template marketplace screen
    • full-screen flat white blocks, arbitrary shadow usage, inconsistent card treatments
    • raw container stacking without surface semantics

Before finalizing any UI, mentally verify:

  • Does this feel like a product, not a page?
  • Is there clear hierarchy?
  • Do surfaces feel intentional?
  • Does the screen feel calm and premium?
  • Is the assistant identity visually present?
  • Would this look plausible in a polished shipping app?

9) Auth Global Module Rules (MUST)

Auth is a global module. All auth/session behavior MUST follow a single state machine.

  • MUST treat AuthBloc as the single source of truth for authentication state.
  • MUST NOT implement ad-hoc auth state in feature modules (no parallel flags, no local auth caches).
  • MUST route all 401 refresh-failure handling through the global callback chain: ApiInterceptor -> ApiClient auth failure callback -> AuthBloc(AuthSessionInvalidated).
  • MUST NOT clear tokens directly inside feature/page code.
  • MUST NOT navigate to login directly from feature code on token errors; rely on router redirect driven by global auth state.
  • MUST distinguish logout semantics:
    • manual logout: revoke server session + clear local session
    • auto expiry/logout on refresh failure: clear local session only
  • MUST ensure startup session recovery has exception fallback and never leaves app stuck in boot/loading state.
  • MUST add/maintain tests for:
    • startup recovery fallback
    • concurrent 401 refresh failure singleflight
    • session invalidation -> unauthenticated redirect path

If a new auth-related requirement cannot fit this model, update this section first, then implement code.

10) Home Message Loading & Scroll Rules (MUST)

Home 首页历史消息加载与滚动策略属于高回归模块,必须遵循以下约束:

  • MUST use event-driven viewport decisions for Home message list behavior.
    • Use HomeMessageViewportController as the decision engine.
    • MUST NOT drive auto-scroll directly from items.length diffs or ad-hoc boolean combinations.
  • MUST distinguish semantic events at minimum:
    • initial history loaded
    • history prepend start/finish
    • new message appended
    • sub-route resume
    • refresh completed
    • user scroll state changed
  • MUST preserve reading position when user is away from bottom.
    • New messages while reading history should show unread indicator instead of forcing bottom jump.
  • MUST preserve viewport anchor during history prepend.
    • MUST NOT mix prepend restore with unconditional bottom auto-scroll.
  • MUST use returnToHomePreserveState for business-subroute returns to Home (calendar/todo/message-related flows).
    • MUST NOT introduce new direct business-route go('/home') shortcuts.
    • Auth entry flows (login/register success) are allowed to navigate to Home directly.
  • MUST add or update tests when touching Home message loading/scroll behavior:
    • controller-level state transition tests
    • widget-level unread indicator and scroll behavior tests
    • route-return stability tests when navigation behavior changes