- All hand-written code files under
lib,go, andmacos/Runnermust stay under 500 lines. - If a file approaches the limit, split it by feature or responsibility before adding more logic.
- Generated files are excluded from this rule:
.dart_tool,build,macos/Flutter/ephemeral,linux/flutter/ephemeral,windows/flutter/ephemeral. - Every hand-written code file under
lib,go, andmacos/Runnermust include at least one meaningful comment. - Prefer file-level comments that explain the file responsibility, plus short section comments where logic is non-obvious.
- Organize Flutter code by type first, then by feature:
lib/pages,lib/widgets,lib/services,lib/state,lib/utils,lib/windows,lib/theme. - Keep entry files thin. They should wire modules together, not hold page logic inline.
- Large widget trees should be moved into page/widget modules instead of one oversized
build()method. - Large visual themes should be split by page or component responsibility.
- Match legacy Wails copy and layout exactly unless the task explicitly asks for copy or layout changes.
- Standalone child windows should follow the compact native-dialog style used by the previous close-confirm window.
- User-facing frontend failure notifications should prefer a shared message-dialog flow instead of ad-hoc alerts so failure reasons stay consistent.
- Collection-mode terminology should stay consistent across frontend and backend:
offline= 本地歌单 / 本地我喜欢,online= 直接使用酷狗云端歌单 / 云端我喜欢,hybrid= 云歌单 fork 到本地并尽量回写云端,失败时保留本地。 - Keep child windows simple: no decorative app icon, no extra explanatory copy unless the flow truly needs it.
- Titles should be visually centered, while leaving safe space for macOS traffic lights and Windows title-bar controls.
- Child window content should be horizontally centered inside the native window, rather than stretched to fill the viewport.
- Reserve a platform-safe top inset for title-bar controls: macOS needs extra space for traffic lights, Windows needs space for the right-side close controls.
- Avoid nested white modal shells inside child windows. Prefer one transparent or near-transparent content surface and let the actual content define the visual weight.
- Layout child windows in three clear zones: title at top, primary actions in the middle area, secondary controls at the bottom.
- Secondary controls such as
取消or记住这次选择should stay pinned to the bottom edge of the content area. - Primary actions should use compact button sizing consistent with the main app, not large card-like blocks.
- Split Go files by responsibility within a package, for example:
download_enqueue.go,service_playlists.go,bridge_settings.go. - Keep bridge exports grouped by feature instead of one large bridge file.
- Shared parsing, normalization, and transport helpers should live in dedicated helper files.
- Prefer a narrow C ABI plus JSON payloads for Flutter FFI when it avoids duplicating backend structs in Dart.
- Do not write compiled binaries or build artifacts to the repository root.
- Route local Go and Flutter build outputs to
bin/,build/, or tool-managed build directories. - For ad-hoc Go smoke validation from the repository root, do not run bare
go build .. - Use
go build -o bin/...for manual bridge smoke tests, and remove temporary one-off outputs if they were created. - Do not add ignore rules that broadly match source package directory names such as
cloudplayer. - If a root-level build artifact must be ignored, use an anchored path rule that cannot match source directories.
- When installing local development toolchains, SDKs, package managers, emulators, or large third-party dependencies for this repository, prefer domestic mirror sources first when they are available and trustworthy.
- Before starting any large environment download, check whether Homebrew, Flutter, Android, Dart, or other required tooling can be pointed at an existing domestic mirror.
- Do not default to long official-source downloads for environment setup if a suitable domestic mirror path exists; prefer the mirror-backed path and document any unavoidable exceptions.
- If a dependency cannot practically use a domestic mirror because the upstream does not expose a supported mirrorable repository, state that constraint explicitly before continuing with the download.
- Keep machine-specific network proxy settings in the repository root
.env.localfile and do not commit that file. - Before Android or Flutter commands that may need network access, load the local shell environment and then export values from
.env.localinto the current shell:source ~/.zshrcset -asource ./.env.localset +a - Before Android validation, load shell environment with
source ~/.zshrcsoJAVA_HOME,ANDROID_HOME,ANDROID_SDK_ROOT,adb,emulator, andflutterall resolve consistently. - Use the existing Android emulator named
CloudPlayer_API_36for local validation unless the task explicitly requires another device profile. - Prefer repository Make targets over ad-hoc Android launch commands so
.env.localand shell initialization are loaded consistently. - Preferred Android local run path:
make android-emulatormake android-run - Use
make android-runinstead of bareflutter run -d android; the scripted path must rebuild the Android Go bridge, syncjniLibs, and then launch the emulator session with.env.localloaded. - If Flutter or Gradle needs artifacts that are unavailable from domestic mirrors, keep the mirror-first repository configuration in the Android Gradle files and fall back to the shell proxy for the remaining official upstream downloads.
- After completing the requested implementation and validation successfully, create a normal non-amended commit unless the user explicitly says not to commit.
- When the user explicitly asks for a commit, stage the relevant changes and create a normal non-amended commit.
- Do not include compiled binaries or other transient build artifacts in commits.
- Every time a new feature is added, update
README.mdin the same change set before committing. - Maintain release note drafts in
CHANGELOG.mdunder## Unreleasedas work lands when the change is relevant to an upcoming release.
- After each meaningful refactor batch, run the narrowest useful validation first.
- For macOS launch and integrated smoke validation, prefer repository scripts over ad-hoc commands.
- Use
make runas the default macOS app launch path because it rebuilds the Go bridge before invoking Flutter. - Do not bypass the scripted startup path with bare
flutter run -d macosunless the task explicitly requires isolating Flutter-only startup behavior. - Before finishing, run the full macOS regression path through
flutter run -d macossmoke validation. - Treat
flutter run -d macosas the final integrated build-and-run check for this repository. - The final validation must confirm the app launches and renders correctly on macOS.
flutter analyzeorflutter build macosalone is not sufficient.