Release: web UX overhaul + Android native port + server polish #59
+11
-3
@@ -38,11 +38,19 @@ go.work.sum
|
|||||||
# canonical record lives in commit messages and the running code).
|
# canonical record lives in commit messages and the running code).
|
||||||
docs/superpowers/
|
docs/superpowers/
|
||||||
|
|
||||||
# Per-machine Claude Code settings + remember-skill memory artifacts.
|
# Per-machine Claude Code settings + remember-skill memory artifacts +
|
||||||
# Both are operator-scoped; the canonical project memory lives under
|
# project-level Claude/AI instruction files. All operator-scoped; the
|
||||||
# ~/.claude/projects/ outside the repo.
|
# canonical project memory lives under ~/.claude/projects/ outside the
|
||||||
|
# repo. CLAUDE.md/AGENTS.md/GEMINI.md stay on the operator's machine
|
||||||
|
# only — they're tool-specific working notes, not project artifacts.
|
||||||
.claude/
|
.claude/
|
||||||
.remember/
|
.remember/
|
||||||
|
CLAUDE.md
|
||||||
|
AGENTS.md
|
||||||
|
GEMINI.md
|
||||||
|
.cursorrules
|
||||||
|
.windsurfrules
|
||||||
|
.aider.conf.yml
|
||||||
|
|
||||||
# Flutter
|
# Flutter
|
||||||
flutter_client/.dart_tool/
|
flutter_client/.dart_tool/
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
# Minstrel — Claude working instructions
|
|
||||||
|
|
||||||
## Porting discipline (HARD RULE — overrides default behavior)
|
|
||||||
|
|
||||||
The Android native client (`android/`) is a **port of the Flutter client**
|
|
||||||
(`flutter_client/`). The Flutter client is the source of truth for behavior,
|
|
||||||
layout, copy, and data flow. When building or fixing any Android feature that
|
|
||||||
exists in Flutter:
|
|
||||||
|
|
||||||
1. **Read the Flutter source FIRST.** Open the actual `flutter_client/lib/...`
|
|
||||||
file(s) for the feature before writing any Kotlin. Do not work from memory,
|
|
||||||
from a summary, or from an assumption about "the shape." If you have not
|
|
||||||
opened the Flutter file in this session, you have not earned the right to
|
|
||||||
write the Android version.
|
|
||||||
|
|
||||||
2. **Replicate the user-visible behavior exactly; implement it idiomatically.**
|
|
||||||
Match what the user sees and feels: layout structure, section order, empty/
|
|
||||||
loading/error states, copy strings, edge cases, and — critically — the
|
|
||||||
**responsiveness** (the app caches to make the UI feel instant; preserve
|
|
||||||
that). But you do NOT have to copy Flutter's *implementation*. Flutter uses
|
|
||||||
drift `watch()` + Riverpod `invalidate`; the well-supported Android idioms
|
|
||||||
are Room + Flow, Compose state, WorkManager, Media3. **Prefer the native
|
|
||||||
mechanism that delivers the same or better UX** over a literal transliteration
|
|
||||||
of the Dart. Exact on behavior + feel; idiomatic on structure. If a more
|
|
||||||
native approach genuinely improves the experience, do that (and note it in
|
|
||||||
the parity map as an intentional, better-supported divergence).
|
|
||||||
|
|
||||||
3. **Never silently substitute a different design.** If the faithful port seems
|
|
||||||
hard, blocked, or impossible, STOP and verify by reading more of the Flutter
|
|
||||||
source + the Android data layer. The blocker is usually wrong — the data or
|
|
||||||
API you think is missing is often already there (e.g. `audio_cache_index`
|
|
||||||
already carried `lastPlayedAt`; the offline pool was never actually blocked).
|
|
||||||
If after reading it is genuinely blocked, **raise it as a question** rather
|
|
||||||
than shipping a scoped-down or alternative design.
|
|
||||||
|
|
||||||
4. **Quote the Flutter file when you start a feature.** Lead the work with
|
|
||||||
"Here's `flutter_client/lib/<path>` — here's what it does — here's the
|
|
||||||
Android port," so divergence is caught before code is written, not after.
|
|
||||||
|
|
||||||
5. **Keep the parity map current.** `docs/superpowers/parity-map.md` maps every
|
|
||||||
feature → Flutter source path → Android target → status. Re-read the relevant
|
|
||||||
row before porting; update it after. This is the durable reference — rely on
|
|
||||||
it, not on session memory, because context gets compacted on long sessions.
|
|
||||||
|
|
||||||
## Repo conventions (already in force)
|
|
||||||
|
|
||||||
- **No GitHub — Gitea only.** PR/issue ops via the gitea MCP (server lives at
|
|
||||||
git.fabledsword.com, migrated from Forgejo); CI runs under `.gitea/workflows/`.
|
|
||||||
Never use `gh` or github.com URLs.
|
|
||||||
- **Git flow:** work on `dev` → PR to protected `main` → tag release. Never push
|
|
||||||
to `main`.
|
|
||||||
- **No in-task tests/builds.** Do not run flutter/gradle/npm `test`/`build`/
|
|
||||||
`analyze` during implementation — CI verifies. Codegen scripts only.
|
|
||||||
- **CI is operator-side.** After `git push origin dev`, the operator reports the
|
|
||||||
result; don't poll Gitea.
|
|
||||||
- **Specs/plans/audits/parity-map live local.** `docs/superpowers/` is
|
|
||||||
`.gitignored` — save there for operator review; never commit those.
|
|
||||||
- **detekt gates CI.** Watch the recurring ones: 60-line `LongMethod`,
|
|
||||||
11-function-per-file `TooManyFunctions` (use `@file:Suppress` with a one-line
|
|
||||||
rationale for Compose-helper density), `ReturnCount` ≤ 2, `MagicNumber`,
|
|
||||||
`MatchingDeclarationName`. Keep lines ≤ 100 chars.
|
|
||||||
|
|
||||||
## Android port shape (quick reference)
|
|
||||||
|
|
||||||
- Screens: `*Screen.kt` with the `@HiltViewModel` inline at the top of the file.
|
|
||||||
- Repositories: `*/data/*Repository.kt`. Wire models: `models/wire/*Wire.kt`.
|
|
||||||
Domain models: `models/*.kt`.
|
|
||||||
- App-lifetime singletons start via the "construct-the-singleton trick" — an
|
|
||||||
`@Inject lateinit var` in `MinstrelApplication` whose `init {}` wires up.
|
|
||||||
- Server errors are `{"error":{"code":"...","message":"..."}}`; surface them
|
|
||||||
through `ErrorCopy.fromThrowable(e)`, never raw `e.message`.
|
|
||||||
- Cross-device reactivity: collect `EventsStream.events` filtered by `kind`.
|
|
||||||
Reference in New Issue
Block a user