chore: untrack CLAUDE.md, gitignore AI-tool instruction files

Project-level AI-tool instruction files (CLAUDE.md, AGENTS.md,
GEMINI.md, .cursorrules, .windsurfrules, .aider.conf.yml) are
operator-scoped working notes, not project artifacts. Other
contributors don't need them, and committing them conflates
operator preferences with shared project conventions.

CLAUDE.md remains on the local disk (untracked) so Claude Code
keeps loading it for this checkout; new clones simply won't have
it, which is the desired state.
This commit is contained in:
2026-05-31 23:31:48 -04:00
parent f482d0d2fa
commit 5a502c12c9
2 changed files with 11 additions and 75 deletions
+11 -3
View File
@@ -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/
-72
View File
@@ -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`.