@michaelbel/cuckcoder-mcp 1.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/rules/architecture.md +15 -0
- package/assets/rules/bottom-sheet.md +20 -0
- package/assets/rules/compose-color.md +22 -0
- package/assets/rules/compose-constraintlayout.md +18 -0
- package/assets/rules/compose-screen.md +33 -0
- package/assets/rules/compose-spacing.md +39 -0
- package/assets/rules/compose.md +54 -0
- package/assets/rules/dialog.md +33 -0
- package/assets/rules/domain.md +36 -0
- package/assets/rules/filesystem.md +3 -0
- package/assets/rules/git.md +11 -0
- package/assets/rules/github-readme.md +97 -0
- package/assets/rules/github-repo.md +65 -0
- package/assets/rules/kmp.md +14 -0
- package/assets/rules/kotlin.md +48 -0
- package/assets/rules/lazylist.md +36 -0
- package/assets/rules/mvi-error-handling.md +19 -0
- package/assets/rules/mvi-state.md +31 -0
- package/assets/rules/mvi.md +39 -0
- package/assets/rules/navigation.md +20 -0
- package/assets/rules/network.md +36 -0
- package/assets/rules/preview.md +31 -0
- package/assets/rules/realtime.md +39 -0
- package/assets/rules/resource.md +18 -0
- package/assets/rules/room.md +33 -0
- package/assets/rules/scaffold.md +25 -0
- package/assets/rules/shimmer.md +34 -0
- package/assets/rules/textfield.md +31 -0
- package/assets/rules/typography.md +32 -0
- package/assets/rules/usecase.md +60 -0
- package/assets/rules/workflow.md +17 -0
- package/assets/rules/workmanager.md +44 -0
- package/assets/skills/create-data-layer/SKILL.md +60 -0
- package/assets/skills/create-datastore-preference/SKILL.md +80 -0
- package/assets/skills/create-domain-mapper/SKILL.md +30 -0
- package/assets/skills/create-feature-alert-dialog/SKILL.md +549 -0
- package/assets/skills/create-feature-bottom-sheet/SKILL.md +300 -0
- package/assets/skills/create-feature-scaffold-screen/SKILL.md +74 -0
- package/assets/skills/create-feature-scaffold-screen/references/form-screen.md +20 -0
- package/assets/skills/create-feature-scaffold-screen/references/network-only-screen.md +20 -0
- package/assets/skills/create-feature-scaffold-screen/references/paginated-screen.md +29 -0
- package/assets/skills/create-feature-scaffold-screen/references/room-backed-screen.md +23 -0
- package/assets/skills/create-feature-scaffold-screen/references/static-screen.md +13 -0
- package/assets/skills/create-guide/SKILL.md +169 -0
- package/assets/skills/create-guide/references/android-project.md +120 -0
- package/assets/skills/create-guide/references/androidx.md +49 -0
- package/assets/skills/create-guide/references/existing-guides.yaml +60 -0
- package/assets/skills/create-guide/references/github.md +71 -0
- package/assets/skills/create-guide/references/guide-defaults.yaml +51 -0
- package/assets/skills/create-guide/references/notion.md +121 -0
- package/assets/skills/create-guide/references/output-contract.md +79 -0
- package/assets/skills/create-guide/references/research.md +64 -0
- package/assets/skills/create-guide/references/validation.md +59 -0
- package/assets/skills/create-guide/scripts/validate_guide.py +167 -0
- package/assets/skills/create-guide/templates/guide-manifest.yaml +67 -0
- package/assets/skills/create-guide/templates/implementation-plan.md +30 -0
- package/assets/skills/create-guide/templates/notion-page.md +46 -0
- package/assets/skills/create-guide/templates/repository/AGENTS.md +7 -0
- package/assets/skills/create-guide/templates/repository/README.md +32 -0
- package/assets/skills/create-guide/templates/repository/SOURCES.md +32 -0
- package/assets/skills/create-guide/templates/validation-report.md +30 -0
- package/assets/skills/create-guide/tests/test_validate_guide.py +97 -0
- package/assets/skills/create-ktor-endpoint/SKILL.md +33 -0
- package/assets/skills/create-notification-flow/SKILL.md +103 -0
- package/assets/skills/create-offline-outbox/SKILL.md +110 -0
- package/assets/skills/create-paging-flow/SKILL.md +96 -0
- package/assets/skills/create-project-from-template/SKILL.md +91 -0
- package/assets/skills/create-project-from-template/assets/icons/android.svg +12 -0
- package/assets/skills/create-project-from-template/assets/icons/compose.svg +34 -0
- package/assets/skills/create-project-from-template/assets/icons/jetpack.svg +10 -0
- package/assets/skills/create-project-from-template/references/myapplication-checklist.md +92 -0
- package/assets/skills/create-room-storage/SKILL.md +39 -0
- package/assets/skills/create-shared-component/SKILL.md +160 -0
- package/assets/skills/create-signalr-channel/SKILL.md +39 -0
- package/assets/skills/create-usecase/SKILL.md +142 -0
- package/assets/skills/create-workmanager-task/SKILL.md +41 -0
- package/assets/skills/github-repo-settings/SKILL.md +152 -0
- package/assets/skills/interview-me/SKILL.md +150 -0
- package/dist/errors.js +49 -0
- package/dist/frontmatter.js +44 -0
- package/dist/github.js +23 -0
- package/dist/index.js +6 -0
- package/dist/server.js +131 -0
- package/dist/source/bundled.js +78 -0
- package/dist/source/cache.js +61 -0
- package/dist/source/github-source.js +68 -0
- package/dist/source/github.js +185 -0
- package/dist/source/index.js +36 -0
- package/dist/source/types.js +1 -0
- package/dist/validation.js +33 -0
- package/dist/version.js +26 -0
- package/package.json +38 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-notification-flow
|
|
3
|
+
description: >-
|
|
4
|
+
Use when пользователь просит реализовать Android local или push notification flow: routing
|
|
5
|
+
входящего push, notification channels, runtime permission, стабильные tag/id, отображение,
|
|
6
|
+
deep link/PendingIntent или обработку push token. Не используй для in-app списка уведомлений без
|
|
7
|
+
системных Android notifications и не добавляй WorkManager только потому, что событие приходит в
|
|
8
|
+
фоне; подключай его лишь когда работа действительно должна быть durable, отложенной или
|
|
9
|
+
ограниченной constraints.
|
|
10
|
+
metadata:
|
|
11
|
+
author: michaelbel
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Поток Android-уведомлений
|
|
15
|
+
|
|
16
|
+
Создаёт цельный путь от локального события или push payload до корректного системного уведомления и
|
|
17
|
+
целевого экрана. Сохраняй push service тонким: он маршрутизирует событие, делегирует специализированным
|
|
18
|
+
handlers и показывает fallback notification, но не выполняет тяжёлую бизнес-операцию сам.
|
|
19
|
+
|
|
20
|
+
## Определи маршрутизацию
|
|
21
|
+
|
|
22
|
+
Для каждого типа события зафиксируй:
|
|
23
|
+
|
|
24
|
+
- источник: local domain event, FCM notification payload, FCM data payload или сторонний push SDK;
|
|
25
|
+
- нужно ли только обновить локальные данные, показать notification или сделать оба действия;
|
|
26
|
+
- целевой route и минимальные валидируемые аргументы;
|
|
27
|
+
- deduplication identity и поведение повторной доставки;
|
|
28
|
+
- channel, importance, звук/badge и видимость чувствительных данных на lock screen.
|
|
29
|
+
|
|
30
|
+
Считай push payload недоверенным вводом. Валидируй type, идентификаторы и route arguments; неизвестный
|
|
31
|
+
тип не должен открывать произвольный экран или падать. Сначала отдавай SDK-owned сообщения его SDK,
|
|
32
|
+
затем проверяй специализированные handlers, после них используй общий display fallback.
|
|
33
|
+
|
|
34
|
+
Перед открытием account-scoped route проверь активную сессию и принадлежность объекта текущему
|
|
35
|
+
пользователю. Используй allowlist разрешённых route; старое или чужое notification направляй в
|
|
36
|
+
безопасный стартовый/auth flow без передачи непроверенного идентификатора.
|
|
37
|
+
|
|
38
|
+
## Channels и ресурсы
|
|
39
|
+
|
|
40
|
+
- Создай стабильный channel ID и пользовательские name/description через строковые ресурсы и фасад
|
|
41
|
+
строк проекта. Channel можно зарегистрировать при старте приложения или непосредственно перед
|
|
42
|
+
первым показом.
|
|
43
|
+
- Не меняй значение channel ID между запусками. Android сохраняет пользовательские настройки канала;
|
|
44
|
+
если продукту действительно нужна несовместимая новая importance/behavior, создай новый versioned
|
|
45
|
+
ID и продумай судьбу старого канала.
|
|
46
|
+
- Выбери importance и category по смыслу уведомления, не повышай их ради заметности. Small icon
|
|
47
|
+
должен быть валидным monochrome notification asset.
|
|
48
|
+
|
|
49
|
+
## Permission
|
|
50
|
+
|
|
51
|
+
Добавь manifest permission и runtime flow для `POST_NOTIFICATIONS`, когда приложение поддерживает
|
|
52
|
+
API 33+. Проверяй API числовым уровнем. Запрашивай permission из UI после понятного пользовательского
|
|
53
|
+
контекста, не из service/manager и не автоматически при получении push.
|
|
54
|
+
|
|
55
|
+
Перед `notify` снова проверь permission/notification availability. При отказе не вызывай `notify` и
|
|
56
|
+
не считай это исключением доставки; выполни только ту domain-часть события, которая не зависит от
|
|
57
|
+
системного уведомления. Политику повторного prompt храни отдельно от факта permission, например в
|
|
58
|
+
DataStore, если продукт действительно её задаёт.
|
|
59
|
+
|
|
60
|
+
## Stable identity и PendingIntent
|
|
61
|
+
|
|
62
|
+
- Используй стабильный tag/id из message ID или domain entity ID, чтобы повтор того же события
|
|
63
|
+
обновлял ожидаемое notification. Для независимых уведомлений не используй один общий ID.
|
|
64
|
+
- Hash допустим только при принятом риске коллизии; tag с namespace помогает разделить категории.
|
|
65
|
+
- Создай explicit `Intent`/type-safe deep link к приложению, восстанови ожидаемый back stack и
|
|
66
|
+
передай только необходимые аргументы.
|
|
67
|
+
- Request code должен различать PendingIntent разных целей. Используй `FLAG_IMMUTABLE` и
|
|
68
|
+
`FLAG_UPDATE_CURRENT`, когда требуется обновить extras существующей цели; не делай mutable
|
|
69
|
+
PendingIntent без API, которому это действительно необходимо.
|
|
70
|
+
- Добавь `setAutoCancel(true)` и content intent для открываемого уведомления. Action intents должны
|
|
71
|
+
иметь собственную identity и безопасную проверку входных данных.
|
|
72
|
+
|
|
73
|
+
## Local и push paths
|
|
74
|
+
|
|
75
|
+
Для local notification Android adapter/handler/worker вызывает общий notification builder/manager;
|
|
76
|
+
domain use case только сообщает о событии и не зависит от Android notification API. Для push
|
|
77
|
+
реализуй `FirebaseMessagingService` или существующий service проекта:
|
|
78
|
+
|
|
79
|
+
1. Нормализуй title/body/data из payload.
|
|
80
|
+
2. Передай SDK-related сообщение соответствующему SDK.
|
|
81
|
+
3. Дай feature handler обработать data-only команду, если она не должна показывать общий fallback.
|
|
82
|
+
4. Иначе вызови общий manager с normalized payload и stable identity.
|
|
83
|
+
5. В `onNewToken` делегируй регистрацию токена существующему use case/SDK. Не логируй полный токен и
|
|
84
|
+
не блокируй callback долгой синхронной работой.
|
|
85
|
+
|
|
86
|
+
Для бизнес-данных data-only push является invalidation-сигналом к обычному server sync, а не
|
|
87
|
+
единственным источником полного состояния. Добавь recovery sync при старте авторизованной сессии
|
|
88
|
+
или resume, потому что доставка push может быть пропущена или задержана.
|
|
89
|
+
|
|
90
|
+
Не добавляй WorkManager для обычного немедленного `notify`. Используй его, только если обработка
|
|
91
|
+
должна пережить process death, требует сети/зарядки, может превысить допустимое время callback или
|
|
92
|
+
должна быть отложена; тогда worker выполняет domain work, а общий manager остаётся владельцем показа.
|
|
93
|
+
|
|
94
|
+
## Отображение и проверка
|
|
95
|
+
|
|
96
|
+
Title/body получают безопасные defaults, blank body не создаёт пустой стиль, длинный body использует
|
|
97
|
+
`BigTextStyle`. Не помещай секреты, токены или лишние персональные данные в extras и видимый текст.
|
|
98
|
+
|
|
99
|
+
Проверь API ниже 33 и 33+, granted/denied permission, отключённые уведомления и channel, foreground и
|
|
100
|
+
background data payload, повтор message ID, два разных сообщения, cold-start deep link, смену
|
|
101
|
+
аккаунта перед открытием, уже открытое приложение, некорректный payload, пропущенный push с recovery
|
|
102
|
+
sync и token refresh. Отдельно проверь, что специализированный handler и общий fallback не показывают
|
|
103
|
+
два уведомления для одного сообщения.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-offline-outbox
|
|
3
|
+
description: >-
|
|
4
|
+
Use when пользователь просит реализовать offline-first очередь исходящих мутаций, outbox или
|
|
5
|
+
гарантированную последующую отправку локально сохранённых действий через Room, WorkManager и
|
|
6
|
+
Ktor. Не используй для обычной фоновой загрузки, периодического refresh, fire-and-forget telemetry
|
|
7
|
+
или запроса, который можно безопасно повторить напрямую без durable queue; для них достаточно
|
|
8
|
+
WorkManager- или Ktor-workflow. Этот skill требует серверной либо protocol-level стратегии
|
|
9
|
+
идемпотентности.
|
|
10
|
+
metadata:
|
|
11
|
+
author: michaelbel
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Offline outbox
|
|
15
|
+
|
|
16
|
+
Создаёт durable pipeline `local mutation -> Room outbox -> unique WorkManager job -> Ktor ->
|
|
17
|
+
acknowledged removal`. Пользовательское действие считается поставленным в очередь только после
|
|
18
|
+
успешной записи Room; запись удаляется только после подтверждённого сервером успеха этой операции.
|
|
19
|
+
|
|
20
|
+
## Сначала определи контракт доставки
|
|
21
|
+
|
|
22
|
+
Зафиксируй до реализации:
|
|
23
|
+
|
|
24
|
+
- какие мутации разрешено выполнять offline и какой payload нужен для точного replay;
|
|
25
|
+
- стабильный `operationId` / idempotency key и как сервер дедуплицирует повторную отправку;
|
|
26
|
+
- scope порядка: глобальный, на пользователя, заказ, маршрут или другую aggregate-сущность;
|
|
27
|
+
- какие HTTP/domain ошибки retryable, а какие permanent;
|
|
28
|
+
- что происходит с permanently failed первой операцией: блокировка очереди, явный dead-letter или
|
|
29
|
+
показ ошибки пользователю;
|
|
30
|
+
- срок жизни операции при logout и смене аккаунта.
|
|
31
|
+
|
|
32
|
+
Если endpoint не поддерживает идемпотентность и повтор может применить мутацию дважды, не называй
|
|
33
|
+
pipeline гарантированным. Остановись на проектировании protocol change или явно согласованной
|
|
34
|
+
компенсации.
|
|
35
|
+
|
|
36
|
+
## Room-модель очереди
|
|
37
|
+
|
|
38
|
+
Храни минимум stable operation id, owner/aggregate scope, монотонную последовательность, operation
|
|
39
|
+
type/endpoint, сериализованный request payload и диагностическое состояние попытки. Payload должен
|
|
40
|
+
быть самодостаточным для replay после process death и обновления access token; не сохраняй transient
|
|
41
|
+
UI state или секреты, которые можно получить в момент отправки.
|
|
42
|
+
|
|
43
|
+
- Обеспечь уникальность `operationId` и детерминированный `ORDER BY` внутри ordering scope.
|
|
44
|
+
- Добавь DAO для вставки, чтения следующей порции, обновления retry metadata и удаления
|
|
45
|
+
подтверждённой записи.
|
|
46
|
+
- Регистрируй entity/DAO в `AppDatabase` и увеличивай `DATABASE_VERSION`.
|
|
47
|
+
- Если локальное optimistic-изменение и outbox-запись должны появиться вместе, выполни оба DAO-вызова
|
|
48
|
+
в одной `AppDatabase.withTransaction` на уровне use case.
|
|
49
|
+
- Не удаляй или заменяй ранее поставленную операцию как «устаревшую», если её успешная отправка не
|
|
50
|
+
подтверждена сервером. Coalescing требует отдельной явно доказанной бизнес-семантики и не является
|
|
51
|
+
поведением по умолчанию.
|
|
52
|
+
|
|
53
|
+
## Постановка в очередь
|
|
54
|
+
|
|
55
|
+
Domain use case сериализует request, создаёт stable idempotency key, атомарно сохраняет outbox и
|
|
56
|
+
только затем планирует unique one-time work. Повторное планирование безопасно: используй стабильное
|
|
57
|
+
unique work name для нужного scope и политику, которая не запускает параллельных drain-workers.
|
|
58
|
+
|
|
59
|
+
Room commit и `enqueueUniqueWork` не образуют общей транзакции: process death между ними может
|
|
60
|
+
оставить запись без worker. Добавь обязательную reconciliation-точку — при старте авторизованной
|
|
61
|
+
сессии и восстановлении процесса проверяй наличие pending outbox и повторно планируй drain. Можно
|
|
62
|
+
также наблюдать очередь отдельным process-scoped coordinator, но он не заменяет startup recovery.
|
|
63
|
+
|
|
64
|
+
Worker требует сеть. Настрой backoff по принятой политике и не делай собственный бесконечный retry
|
|
65
|
+
loop поверх WorkManager. Новая запись, добавленная во время работы worker, должна либо попасть в
|
|
66
|
+
текущий drain, либо гарантированно вызвать следующий запуск.
|
|
67
|
+
|
|
68
|
+
## Drain и replay
|
|
69
|
+
|
|
70
|
+
1. Worker получает зависимости через принятый Hilt/WorkManager механизм и делегирует операции
|
|
71
|
+
конкретным use case; он не содержит endpoint-specific бизнес-логику.
|
|
72
|
+
2. Читай записи в строгом порядке выбранного scope. Не отправляй более позднюю зависимую операцию,
|
|
73
|
+
пока предыдущая не получила подтверждение.
|
|
74
|
+
3. Десериализуй payload по operation type, передай тот же `operationId` как idempotency key и
|
|
75
|
+
выполни сетевой вызов через `NetworkService`/Ktor с обычной обработкой ответа проекта.
|
|
76
|
+
4. Удаляй конкретную запись в Room только после подтверждённого success. Если процесс погиб после
|
|
77
|
+
server success, но до delete, следующий replay должен быть безопасен благодаря тому же
|
|
78
|
+
idempotency key.
|
|
79
|
+
5. На retryable ошибке сохрани диагностику, останови этот ordering scope и верни `Result.retry()`;
|
|
80
|
+
не позволяй следующей записи обогнать неуспешную.
|
|
81
|
+
6. На permanent ошибке сохрани её как видимое blocked/dead-letter состояние и верни результат по
|
|
82
|
+
явной продуктовой политике. Не удаляй запись и не маскируй ошибку как success.
|
|
83
|
+
7. Пробрасывай `CancellationException`; в `finally` выполняй только ограниченный cleanup и
|
|
84
|
+
диагностируй stop reason там, где API это поддерживает.
|
|
85
|
+
|
|
86
|
+
## Согласованность и lifecycle
|
|
87
|
+
|
|
88
|
+
- Не держи transaction открытой во время HTTP-запроса. Claim/lease нужен только если архитектура
|
|
89
|
+
допускает несколько consumers; проще обеспечить одного unique worker на scope.
|
|
90
|
+
- После refresh с сервера не затирай локальное optimistic state, пока связанная outbox-операция не
|
|
91
|
+
подтверждена или конфликт не разрешён явно.
|
|
92
|
+
- При logout запроси отмену worker нужного account scope и дождись её завершения там, где lifecycle
|
|
93
|
+
допускает ожидание, затем примени выбранную политику к очереди. Поскольку уже начатый HTTP-запрос
|
|
94
|
+
мог завершиться, worker проверяет owner/current account перед каждой отправкой и перед Room
|
|
95
|
+
mutation; отдельно зафиксируй продуктовую семантику ответа, пришедшего во время logout. Никогда не
|
|
96
|
+
отправляй запись с credentials другого пользователя.
|
|
97
|
+
- Закрой окно между owner-check и чтением auth headers: request boundary/interceptor сверяет
|
|
98
|
+
session generation операции с текущей сессией непосредственно перед отправкой и отклоняет
|
|
99
|
+
несовпадение либо использует credential snapshot, однозначно привязанный к тому же owner. Не
|
|
100
|
+
сохраняй access token внутри outbox payload.
|
|
101
|
+
- Наблюдаемое количество failures/blocked operations предоставляй отдельным `FlowUseCase`, если UI
|
|
102
|
+
действительно его показывает.
|
|
103
|
+
|
|
104
|
+
## Проверка результата
|
|
105
|
+
|
|
106
|
+
Проверь постановку без сети, process death после Room commit до enqueue, process death до запуска
|
|
107
|
+
worker, server success с падением до Room delete, retryable и permanent ошибки, две зависимые
|
|
108
|
+
операции, конкурентное планирование, добавление операции во время drain и logout со сменой
|
|
109
|
+
пользователя. Главные утверждения теста: операция не теряется, не обгоняется и не применяется
|
|
110
|
+
дважды на сервере.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-paging-flow
|
|
3
|
+
description: >-
|
|
4
|
+
Use when пользователь просит добавить Android Paging 3 поток, пагинируемый список или бесконечную
|
|
5
|
+
загрузку через Room PagingSource, network PagingSource либо RemoteMediator с локальным кэшем,
|
|
6
|
+
включая Pager, FlowUseCase и подключение Compose UI. Не используй для обычного непагинируемого
|
|
7
|
+
списка во Flow, ручной кнопки «загрузить ещё» или карусели с уже загруженными элементами. Не
|
|
8
|
+
создавай Room-кэш или RemoteMediator, если задача требует только network-only пагинацию.
|
|
9
|
+
metadata:
|
|
10
|
+
author: michaelbel
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Новый Paging-поток
|
|
14
|
+
|
|
15
|
+
Создаёт один согласованный Paging 3 pipeline от выбранного источника до Compose UI. Сначала выбери
|
|
16
|
+
режим по источнику истины; не добавляй слои только ради симметрии.
|
|
17
|
+
|
|
18
|
+
## Выбери режим
|
|
19
|
+
|
|
20
|
+
### Room-backed
|
|
21
|
+
|
|
22
|
+
Используй, когда данные уже хранятся локально и сеть не участвует. DAO возвращает
|
|
23
|
+
`PagingSource<Int, Entity>`, а `Pager` получает его через `pagingSourceFactory`. Любое изменение
|
|
24
|
+
фильтра должно создавать новый PagingSource.
|
|
25
|
+
|
|
26
|
+
### Network-only
|
|
27
|
+
|
|
28
|
+
Используй отдельный `PagingSource<Key, Item>`, когда кэш не нужен. Тип ключа должен соответствовать
|
|
29
|
+
API: page number, offset или непрозрачный token. Не переводись между этими схемами без необходимости.
|
|
30
|
+
|
|
31
|
+
### Network + Room cache
|
|
32
|
+
|
|
33
|
+
Используй `RemoteMediator` только когда Room является источником данных для UI, а сеть пополняет и
|
|
34
|
+
обновляет кэш. Нужны DAO `PagingSource`, remote keys, сетевые модели/мапперы и транзакционное
|
|
35
|
+
обновление кэша. Идентичность remote key должна включать все параметры выдачи, которые меняют
|
|
36
|
+
результат: пользователя, категорию, фильтры, сортировку и поисковый текст по необходимости.
|
|
37
|
+
|
|
38
|
+
Сформируй один канонический `scopeId` из стабильно сериализованных result-shaping параметров. Один
|
|
39
|
+
и тот же scope используй в remote key, ключе result-membership/cache entity, DAO `WHERE` и
|
|
40
|
+
`ORDER BY`, refresh-delete и позиции mapper. Основную domain entity можно разделять между выдачами,
|
|
41
|
+
но её membership/position обязаны оставаться scope-specific.
|
|
42
|
+
|
|
43
|
+
## Собери pipeline
|
|
44
|
+
|
|
45
|
+
1. Определи key scheme, page size, initial load size, placeholder policy и точный признак конца
|
|
46
|
+
выдачи. Используй фактический `params.loadSize`, если endpoint поддерживает динамический limit.
|
|
47
|
+
2. Для network `PagingSource` реализуй `load` без пропусков и дублей. Рассчитывай `prevKey`,
|
|
48
|
+
`nextKey` и `getRefreshKey` в одной системе координат; offset увеличивай на реально полученное
|
|
49
|
+
число элементов, а token бери только из ответа сервера.
|
|
50
|
+
3. Для Room добавь детерминированный `ORDER BY` со стабильным tie-breaker. Возвращай новый
|
|
51
|
+
`PagingSource` из factory, не сохраняй его экземпляр.
|
|
52
|
+
4. Для `RemoteMediator` обработай `REFRESH`, `PREPEND` и `APPEND` явно. Если API не поддерживает
|
|
53
|
+
prepend, заверши его успешно. На refresh сбрасывай только кэш и keys текущей выдачи; данные другой
|
|
54
|
+
выдачи не затрагивай.
|
|
55
|
+
5. Обновляй remote keys и соответствующие entities в одной `AppDatabase.withTransaction`.
|
|
56
|
+
Сетевой вызов и маппинг выполняй до транзакции. Не очищай успешный кэш перед сетью так, чтобы
|
|
57
|
+
ошибка refresh оставляла пустой экран.
|
|
58
|
+
6. Помести `Pager(...).flow` в конкретный `FlowUseCase<Params, PagingData<T>>`. Внедри в него DAO,
|
|
59
|
+
`AppDatabase`, `NetworkService` и нужные use case напрямую согласно выбранному режиму.
|
|
60
|
+
7. ViewModel предоставляет поток, применяет `cachedIn` в своём lifecycle и пересоздаёт pipeline при
|
|
61
|
+
изменении query через flow-оператор вроде `flatMapLatest`. Compose собирает его через
|
|
62
|
+
`collectAsLazyPagingItems()`.
|
|
63
|
+
|
|
64
|
+
## Ошибки и состояния UI
|
|
65
|
+
|
|
66
|
+
- Возвращай transport/domain ошибки как `LoadResult.Error` или `MediatorResult.Error`; не превращай
|
|
67
|
+
ошибку в пустую успешную страницу.
|
|
68
|
+
- Не поглощай `CancellationException` общим `catch (Throwable)`.
|
|
69
|
+
- Различай `loadState.refresh` и `loadState.append`: refresh управляет полноэкранным loading/error,
|
|
70
|
+
append — нижним индикатором и retry рядом с концом списка.
|
|
71
|
+
- Empty state показывай только после успешного refresh при `itemCount == 0`; старый кэш при refresh
|
|
72
|
+
не является empty state.
|
|
73
|
+
- Pull-to-refresh и retry проходят через отдельные MVI Intent/Event: content диспатчит Intent,
|
|
74
|
+
ViewModel отправляет одноразовый Event, а публичный Screen вызывает `pagingItems.refresh()` или
|
|
75
|
+
`pagingItems.retry()` внутри `ObserveAsEvents`.
|
|
76
|
+
- Используй стабильные ключи элементов, когда они доступны, и не копируй весь `PagingData` в MVI
|
|
77
|
+
model или обычный `List`.
|
|
78
|
+
|
|
79
|
+
## Инварианты RemoteMediator
|
|
80
|
+
|
|
81
|
+
- Порядок записей в Room хранит server ordering явно, например через `position` внутри scope
|
|
82
|
+
выдачи.
|
|
83
|
+
- Remote key и кэшированная membership-запись используют один и тот же канонический scope; не
|
|
84
|
+
позволяй фильтру, сортировке или пользователю разделять key, но смешивать строки результата.
|
|
85
|
+
- End-of-pagination вычисляется по server token/metadata либо по размеру ответа относительно
|
|
86
|
+
запрошенного limit; не смешивай признаки из разных API.
|
|
87
|
+
- Первый APPEND без подходящего remote key не должен повторно загружать первую страницу.
|
|
88
|
+
- Ошибка не продвигает key и не оставляет частично записанную страницу.
|
|
89
|
+
- Refresh одного набора параметров не удаляет remote keys другого набора.
|
|
90
|
+
|
|
91
|
+
## Проверка результата
|
|
92
|
+
|
|
93
|
+
Проверь initial load, append, refresh, retry после сетевой ошибки, восстановление экрана после
|
|
94
|
+
recreation, пустую выдачу, последнюю неполную страницу и смену каждого параметра запроса. Для
|
|
95
|
+
RemoteMediator дополнительно проверь offline-чтение кэша, атомарность entity/key и отсутствие
|
|
96
|
+
дубликатов после повторного APPEND.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-project-from-template
|
|
3
|
+
description: >-
|
|
4
|
+
Use when пользователь просит создать и оформить новый Android-проект копированием шаблона
|
|
5
|
+
`Projects/MyApplication`: задать имя проекта, package/namespace/applicationId, GitHub metadata,
|
|
6
|
+
package directories и выбрать `.idea/icon.svg` для Android, Compose или Jetpack. Не используй
|
|
7
|
+
для добавления модуля или фичи в существующий проект и не используй для проекта, который должен
|
|
8
|
+
быть создан другим шаблоном или Android Studio wizard.
|
|
9
|
+
metadata:
|
|
10
|
+
author: michaelbel
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Новый проект из MyApplication
|
|
14
|
+
|
|
15
|
+
Создай самостоятельный проект из закоммиченного состояния sibling-шаблона `MyApplication` и
|
|
16
|
+
полностью убери его пользовательские идентификаторы. Не переноси историю шаблона, локальные файлы
|
|
17
|
+
IDE или build outputs.
|
|
18
|
+
|
|
19
|
+
Перед изменениями полностью прочитай
|
|
20
|
+
[references/myapplication-checklist.md](references/myapplication-checklist.md). Это карта
|
|
21
|
+
обязательных замен и значений, которые нужно сохранить.
|
|
22
|
+
|
|
23
|
+
## Входные данные
|
|
24
|
+
|
|
25
|
+
Определи из запроса или согласуй только действительно неоднозначные значения:
|
|
26
|
+
|
|
27
|
+
- абсолютный путь новой директории и имя директории проекта;
|
|
28
|
+
- display name приложения и Gradle root project name;
|
|
29
|
+
- namespace; по умолчанию `org.michaelbel.<normalized-name>`;
|
|
30
|
+
- application ID; по умолчанию совпадает с namespace;
|
|
31
|
+
- GitHub owner и repo slug; по умолчанию `michaelbel` и нормализованное имя репозитория;
|
|
32
|
+
- тип иконки: `android`, `compose` или `jetpack`;
|
|
33
|
+
- краткое описание для README.
|
|
34
|
+
|
|
35
|
+
`<normalized-name>` означает lowercase ASCII-сегмент без пробелов, дефисов и других символов,
|
|
36
|
+
недопустимых в Kotlin package. Не угадывай другое имя бренда или другой owner. Если пользователь
|
|
37
|
+
явно задал значение, оно приоритетнее default.
|
|
38
|
+
|
|
39
|
+
Тип иконки определяй по назначению проекта:
|
|
40
|
+
|
|
41
|
+
- `android` — обычное Android-приложение;
|
|
42
|
+
- `compose` — проект или sample, главным предметом которого является Jetpack Compose;
|
|
43
|
+
- `jetpack` — проект библиотеки, компонента или sample из семейства AndroidX/Jetpack.
|
|
44
|
+
|
|
45
|
+
Выбор иконки не разрешает менять плагины, зависимости или архитектуру. Если назначение нельзя
|
|
46
|
+
надёжно определить из запроса, спроси только тип иконки.
|
|
47
|
+
|
|
48
|
+
## Рабочий процесс
|
|
49
|
+
|
|
50
|
+
1. Проверь, что `/Users/mihailbelyj/Projects/MyApplication` существует и является git-репозиторием.
|
|
51
|
+
Изучи его актуальное закоммиченное состояние и `git status`. Если в шаблоне есть незакоммиченные
|
|
52
|
+
изменения, не включай их молча: используй `HEAD` и сообщи об этом либо согласуй другой источник.
|
|
53
|
+
2. Убедись, что целевая директория не существует или пуста. Не объединяй шаблон с существующим
|
|
54
|
+
проектом и не перезаписывай файлы без отдельного согласия.
|
|
55
|
+
3. Экспортируй именно tracked files из `HEAD`, например
|
|
56
|
+
`git -C /Users/mihailbelyj/Projects/MyApplication archive HEAD | tar -x -C <empty-project-dir>`.
|
|
57
|
+
Не копируй `.git`, `.gradle`, `.kotlin`, `build`, `local.properties`, `.DS_Store`,
|
|
58
|
+
`.claude/settings.local.json` и остальные локальные файлы `.idea`.
|
|
59
|
+
4. Инициализируй новый git-репозиторий, не добавляя remote и не создавая commit без соответствующего
|
|
60
|
+
запроса пользователя. Сохрани симлинки `CLAUDE.md` и `GEMINI.md` на `AGENTS.md`.
|
|
61
|
+
5. До текстовых замен вычисли checksum `.github/debug-key.jks`. Сохрани файл побайтово и не меняй
|
|
62
|
+
debug signing block: `keyAlias = "myapplication"`, путь к key store и существующие credentials
|
|
63
|
+
остаются прежними. Не выводи credentials в лог или ответ.
|
|
64
|
+
6. Выполни адресные изменения из checklist. Не делай глобальную замену `myapplication`, потому что
|
|
65
|
+
это имя debug key должно остаться прежним.
|
|
66
|
+
7. Скопируй выбранный asset этого skill в `<project>/.idea/icon.svg`:
|
|
67
|
+
`assets/icons/android.svg`, `assets/icons/compose.svg` или `assets/icons/jetpack.svg`. В git из
|
|
68
|
+
`.idea` должен попадать только `icon.svg`.
|
|
69
|
+
8. Получи через `cuckcoder` MCP актуальные `github-repo` и
|
|
70
|
+
`github-readme`, затем приведи tracked repository files к ним. Не добавляй
|
|
71
|
+
placeholder-текст, выдуманный cover или неподтверждённые ссылки.
|
|
72
|
+
9. Просканируй экспортированный из шаблона набор текстовых файлов на старые project name, display
|
|
73
|
+
name, package и GitHub repo slug; до первого staging не полагайся на пустой `git ls-files` нового
|
|
74
|
+
репозитория. Проверяй signing block отдельным безопасным запросом, который не печатает
|
|
75
|
+
password-поля.
|
|
76
|
+
10. Повтори checksum key store и проверь package directory, package declarations, namespace,
|
|
77
|
+
application ID, archive name, app label, README links, IDE icon и AI-agent instructions.
|
|
78
|
+
|
|
79
|
+
## Проверка и завершение
|
|
80
|
+
|
|
81
|
+
- Проверь, что `CLAUDE.md` и `GEMINI.md` остались симлинками, а `.idea/icon.svg` не игнорируется.
|
|
82
|
+
- Не обновляй SDK, AGP, Kotlin или зависимости только потому, что создан новый проект.
|
|
83
|
+
- Не меняй launcher/splash artwork, CI или module names, если это не следует из отдельного запроса.
|
|
84
|
+
- Шаблон вычисляет `versionCode` через `git rev-list --count HEAD`, поэтому Gradle не сможет пройти
|
|
85
|
+
конфигурацию до первого commit. Если commit не был запрошен, честно зафиксируй этот отложенный
|
|
86
|
+
шаг вместо скрытого commit.
|
|
87
|
+
- После разрешённого первого commit запусти `./gradlew assembleDebug` и `./gradlew lint`. Исправь
|
|
88
|
+
только ошибки, относящиеся к созданию проекта.
|
|
89
|
+
- External GitHub-настройки, remote, secrets и push выполняй только по явному запросу. Если remote
|
|
90
|
+
уже создан и пользователь просит полностью оформить репозиторий, загрузи `github-repo-settings`
|
|
91
|
+
и выполни его после локального создания проекта.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100" height="100" rx="24" fill="#34A853" />
|
|
3
|
+
<path
|
|
4
|
+
d="M92.8438 73.235C92.8177 73.0527 92.7916 72.8964 92.7656 72.7141C92.5833 71.6463 92.3749 70.5784 92.1145 69.5106C91.6717 67.6614 91.0987 65.8643 90.4216 64.1454C89.8486 62.6608 89.1975 61.2283 88.4682 59.848C87.5306 58.0769 86.4888 56.358 85.3168 54.7171C83.8843 52.7117 82.2956 50.8625 80.5766 49.1175C79.8474 48.3883 79.0921 47.685 78.3107 47.0339C76.6178 45.5754 74.8207 44.2471 72.9195 43.0751C72.9455 43.0491 72.9455 43.023 72.9715 42.997C73.831 41.4864 74.7165 40.0018 75.576 38.4912C76.4355 37.0327 77.2689 35.5742 78.1284 34.0896C78.7275 33.0478 79.3525 31.98 79.9516 30.9382C80.1078 30.6778 80.212 30.4434 80.2901 30.1569C80.5245 29.4276 80.5506 28.6463 80.3422 27.917C80.2901 27.7347 80.2381 27.5524 80.1599 27.3961C80.0818 27.2138 80.0036 27.0575 79.8995 26.9013C79.5869 26.3543 79.1181 25.8855 78.5191 25.5469C77.9982 25.2344 77.4252 25.0521 76.8262 25C76.5657 24.974 76.3313 24.974 76.0709 25C75.8625 25.026 75.6542 25.0521 75.4718 25.1042C74.7426 25.2865 74.0915 25.6772 73.5706 26.2502C73.3883 26.4585 73.2059 26.6929 73.0757 26.9273C72.4767 27.9691 71.8516 29.0369 71.2526 30.0787L68.7002 34.4803C67.8407 35.9909 66.9552 37.4755 66.0957 38.9861C65.9915 39.1423 65.9134 39.3247 65.8092 39.4809C65.679 39.4288 65.5488 39.3767 65.4185 39.3247C60.6263 37.5015 55.4434 36.5118 50 36.5118C49.8437 36.5118 49.7135 36.5118 49.5573 36.5118C44.739 36.5639 40.103 37.3973 35.7535 38.9079C35.2586 39.0902 34.7638 39.2726 34.2689 39.4549C34.1908 39.2986 34.0866 39.1423 34.0085 38.9861C33.149 37.4755 32.2635 35.9909 31.404 34.4803C30.5445 33.0218 29.7111 31.5633 28.8516 30.0787C28.2526 29.0369 27.6275 27.9691 27.0285 26.9273C26.8722 26.6669 26.7159 26.4585 26.5336 26.2502C26.0127 25.6772 25.3356 25.2865 24.6324 25.1042C24.424 25.0521 24.2156 25.026 24.0333 25C23.7729 24.974 23.5385 24.974 23.278 25C22.679 25.0521 22.106 25.2344 21.5851 25.5469C21.0121 25.8855 20.5433 26.3543 20.2047 26.9013C20.1006 27.0575 20.0224 27.2138 19.9443 27.3961C19.8662 27.5784 19.8141 27.7347 19.762 27.917C19.5797 28.6463 19.5797 29.4016 19.8141 30.1569C19.8922 30.4173 20.0224 30.6778 20.1526 30.9382C20.7517 31.98 21.3767 33.0478 21.9758 34.0896C22.8353 35.5482 23.6687 37.0067 24.5282 38.4912C25.3877 40.0018 26.2732 41.4864 27.1327 42.997L27.1587 43.023C25.4137 44.1169 23.7468 45.315 22.1581 46.6432C21.2205 47.4246 20.3089 48.258 19.4494 49.1175C17.7044 50.8365 16.1417 52.7117 14.7093 54.7171C13.5373 56.358 12.4955 58.0509 11.5578 59.848C10.8286 61.2283 10.1775 62.6608 9.60449 64.1454C8.92732 65.8904 8.35434 67.6875 7.91158 69.5106C7.65113 70.5524 7.44277 71.6202 7.26045 72.7141C7.23441 72.8964 7.20837 73.0527 7.18232 73.235C7.07814 73.8601 7.00001 74.4851 6.92188 75.1363H93C93 74.4851 92.9219 73.8601 92.8438 73.235Z"
|
|
5
|
+
fill="#202124" />
|
|
6
|
+
<path
|
|
7
|
+
d="M72.4245 63.2077C74.1435 62.0618 74.4039 59.4052 72.9714 57.2956C71.565 55.1599 69.0126 54.3785 67.2937 55.5245C65.5747 56.6705 65.3143 59.3271 66.7467 61.4367C68.1532 63.5724 70.7055 64.3537 72.4245 63.2077Z"
|
|
8
|
+
fill="#34A853" />
|
|
9
|
+
<path
|
|
10
|
+
d="M33.4094 61.4628C34.8158 59.3271 34.5814 56.6966 32.8624 55.5506C31.1435 54.4047 28.5911 55.186 27.1846 57.3217C25.7782 59.4574 26.0126 62.0879 27.7316 63.2339C29.4505 64.3798 31.9769 63.5724 33.4094 61.4628Z"
|
|
11
|
+
fill="#34A853" />
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100" height="100" rx="24" fill="white" />
|
|
3
|
+
<g clip-path="url(#clip0_1352_405)">
|
|
4
|
+
<path
|
|
5
|
+
d="M48.7456 8.0782C48.7541 8.0527 48.7558 8.0255 48.7524 8H50.1617C50.1549 8.0272 50.1566 8.0544 50.1668 8.0799C49.6925 8.3077 49.2199 8.3077 48.7456 8.0782Z"
|
|
6
|
+
fill="#94F1C6" />
|
|
7
|
+
<path
|
|
8
|
+
d="M86.3749 28.7791C87.3779 30.1816 87.8811 31.7456 87.8811 33.4677C87.8811 44.6401 87.8947 55.8125 87.8743 66.9866C87.8675 70.3866 86.363 72.9978 83.439 74.7301C73.8017 80.4353 64.1525 86.1201 54.5067 91.8066C52.9614 92.7178 51.2835 93.0952 49.4951 92.9813C50.0663 92.7841 50.0238 92.3166 50.0238 91.8423C50.017 86.9548 50.0204 82.0673 50.0204 77.1781C50.0204 76.9146 49.9983 76.6494 50.068 76.391C50.1496 76.1615 50.3383 76.0986 50.5559 76.0884C51.3685 76.0476 52.1012 75.762 52.7897 75.354C57.3049 72.6714 61.8371 70.0143 66.3574 67.3402C67.6698 66.5633 69.006 65.8204 70.2963 65.0095C71.8467 64.0337 72.7596 62.6227 72.763 60.7493C72.7783 53.9255 72.763 47.1017 72.7766 40.2779C72.7783 39.4143 72.5913 38.6238 72.1901 37.8724C72.1136 37.7296 72.032 37.5902 72.0252 37.4219C72.0388 37.1958 72.2173 37.104 72.3788 37.0071C76.0491 34.8073 79.7194 32.6109 83.3982 30.4247C84.2176 29.9385 85.0319 29.4455 85.8496 28.9576C86.0111 28.8624 86.1658 28.7349 86.3749 28.7825V28.7791Z"
|
|
9
|
+
fill="#1F86FB" />
|
|
10
|
+
<path
|
|
11
|
+
d="M50.1752 76.2873C50.1701 77.7255 50.1616 79.1637 50.1616 80.6002C50.1599 84.4745 50.1616 88.3488 50.1599 92.2231C50.1599 92.9286 50.1514 92.9286 49.4952 92.9796C48.0689 92.8793 46.7582 92.4322 45.5121 91.7267C35.3988 86.0062 25.2804 80.2942 15.1603 74.5873C13.3022 73.5401 12.2295 71.988 12.0017 69.8596C12.0051 69.7576 12.0136 69.6556 12.0136 69.5519C12.0136 57.5652 12.0136 45.5768 12.0136 33.5901C12.0136 33.4881 12.0051 33.3861 12.0017 33.2824C12.0986 32.0754 12.3111 30.8973 12.8976 29.8144C13.0574 29.7464 13.1815 29.8365 13.3073 29.9079C16.301 31.5892 19.2998 33.262 22.2935 34.9433C23.8932 35.8409 25.4912 36.7419 27.0994 37.6259C27.266 37.7177 27.4445 37.7942 27.5516 37.9659C27.5635 38.0135 27.5635 38.0594 27.5533 38.107C27.232 38.9077 27.1028 39.7322 27.1045 40.5992C27.1198 47.7018 27.1147 54.8044 27.1113 61.907C27.1113 63.2415 27.6621 64.253 28.8249 64.916C31.9342 66.6891 35.0588 68.4367 38.1732 70.2013C41.2621 71.9506 44.3544 73.6948 47.4484 75.4373C48.0927 75.8011 48.7829 76.0425 49.5309 76.0833C49.7366 76.0952 49.9389 76.1258 50.1242 76.2295L50.1752 76.2839V76.2873Z"
|
|
12
|
+
fill="#003144" />
|
|
13
|
+
<path
|
|
14
|
+
d="M27.5143 37.9726C25.238 36.7044 22.96 35.4362 20.6837 34.1663C18.0878 32.7179 15.4919 31.2678 12.896 29.8177C13.5471 28.2911 14.6436 27.1674 16.0529 26.3327C18.2714 25.0186 20.4933 23.713 22.7135 22.4023C30.1187 18.0333 37.5239 13.6643 44.9291 9.29533C46.1089 8.60003 47.3771 8.18353 48.7439 8.07983H50.1651C51.3942 8.17843 52.5587 8.50483 53.6314 9.11003C63.4506 14.6503 73.2664 20.194 83.0805 25.7411C84.4116 26.4942 85.5421 27.4768 86.3734 28.779C83.378 30.5657 80.3792 32.349 77.3855 34.1374C75.6124 35.1965 73.8461 36.2658 72.0764 37.3317C72.039 37.364 71.9982 37.3691 71.9557 37.347C71.7415 37.2076 71.6123 36.9866 71.4491 36.7996C70.6977 35.9343 69.6862 35.443 68.7172 34.8973C66.3134 33.5441 63.9147 32.179 61.5092 30.8258C58.4526 29.1054 55.4096 27.3612 52.3445 25.6527C50.4507 24.597 48.5722 24.6769 46.7039 25.7819C40.9681 29.1751 35.2272 32.5615 29.4846 35.9428C28.8403 36.3219 28.315 36.82 27.9002 37.4422C27.7795 37.6224 27.6996 37.8366 27.5126 37.9692L27.5143 37.9726Z"
|
|
15
|
+
fill="#00DF79" />
|
|
16
|
+
<path
|
|
17
|
+
d="M72.0016 37.3233C72.0271 37.3284 72.0526 37.3301 72.0781 37.3318C72.3382 37.9489 72.7037 38.5218 72.8261 39.1967C72.8601 39.3854 72.8924 39.569 72.8924 39.7594C72.8924 46.8484 72.9077 53.9374 72.8771 61.0264C72.872 62.3847 72.2328 63.5271 71.2247 64.44C70.0857 65.4753 68.6713 66.0856 67.3742 66.8693C64.3448 68.7019 61.2848 70.4835 58.235 72.2838C56.4211 73.3548 54.6106 74.4326 52.7882 75.4917C52.0742 75.9065 51.3177 76.2142 50.4677 76.2074C50.3708 76.2074 50.2722 76.2567 50.1736 76.2839L50.1345 76.289C50.0206 76.1377 50.0206 75.9592 50.0189 75.7841C50.0036 73.3344 49.8744 70.8881 49.9288 68.4384C49.9339 68.2344 49.9169 68.027 49.9849 67.8281C50.041 67.687 50.1668 67.636 50.2977 67.619C51.1715 67.5102 51.894 67.0478 52.625 66.6143C56.1882 64.5063 59.7548 62.4034 63.3231 60.3039C64.5658 59.5729 65.1965 58.5036 65.1931 57.0416C65.1812 52.71 65.1795 48.3784 65.1965 44.0468C65.1999 43.2937 65.0673 42.5916 64.7494 41.9184C64.7494 41.7212 64.9109 41.6532 65.0384 41.5631C67.1634 40.0722 69.3972 38.7513 71.6293 37.4304C71.7432 37.3624 71.8537 37.2893 71.9982 37.3199L72.0016 37.3233Z"
|
|
18
|
+
fill="#1D72B6" />
|
|
19
|
+
<path
|
|
20
|
+
d="M72.0015 37.3233C69.5773 38.787 67.131 40.2201 64.8088 41.847C64.7323 41.8402 64.6626 41.8096 64.6184 41.7484C63.9843 40.8491 63.0204 40.3901 62.1024 39.8716C58.7432 37.9761 55.3806 36.084 52.0282 34.1766C51.9772 34.1477 51.9228 34.1222 51.8735 34.0916C50.3656 33.1498 48.9257 33.2688 47.4161 34.1902C43.8971 36.3373 40.3288 38.3994 36.7741 40.487C36.0533 40.9103 35.409 41.3999 35.0027 42.1513C34.967 42.2159 34.9126 42.2669 34.8463 42.3026C34.6678 42.3434 34.5369 42.2363 34.4026 42.153C32.4374 40.9341 30.4518 39.7509 28.4288 38.6306C28.116 38.4572 27.7369 38.3722 27.5227 38.0407C27.5176 38.0186 27.5142 37.9948 27.5142 37.971C27.8644 37.0785 28.49 36.4138 29.2941 35.9327C31.8543 34.3993 34.4264 32.8863 36.9968 31.3699C40.2982 29.4217 43.5877 27.4548 46.9078 25.5423C48.8118 24.4458 50.7345 24.5733 52.6232 25.6664C54.143 26.5453 55.6798 27.397 57.2064 28.264C58.886 29.2177 60.5622 30.1765 62.2435 31.1268C63.9384 32.0856 65.6452 33.0206 67.3316 33.9947C68.4706 34.6526 69.6725 35.2051 70.7316 35.9973C71.2263 36.3679 71.6581 36.8031 72.0015 37.3216V37.3233Z"
|
|
21
|
+
fill="#00C165" />
|
|
22
|
+
<path
|
|
23
|
+
d="M27.5227 38.0408C29.5321 39.1101 31.5143 40.227 33.4387 41.4408C33.8943 41.7281 34.3601 42.0018 34.8225 42.2823C34.9296 42.4013 34.8854 42.5339 34.8446 42.6563C34.6865 43.1255 34.6882 43.6066 34.6882 44.0928C34.6916 48.6998 34.6984 53.3085 34.6831 57.9155C34.6797 58.9797 35.1149 59.7192 36.0397 60.2411C39.5655 62.2301 43.0981 64.2106 46.6154 66.2149C47.1117 66.4988 47.6166 66.7691 48.1096 67.0581C48.5975 67.342 49.1229 67.5188 49.6788 67.6072C49.8216 67.6293 49.9762 67.6191 50.08 67.7517C50.0851 68.2039 50.0919 68.6578 50.097 69.11C50.1191 71.3285 50.1395 73.547 50.1581 75.7672C50.1581 75.9423 50.1428 76.1174 50.1343 76.2908C48.5397 76.2772 47.2341 75.4884 45.9132 74.7285C44.4309 73.8751 42.9349 73.0404 41.4474 72.1972C39.5383 71.116 37.6309 70.0297 35.7201 68.9502C34.2292 68.107 32.7366 67.2723 31.244 66.4325C30.3396 65.9225 29.4165 65.4414 28.5359 64.8923C27.5363 64.2684 26.994 63.3283 26.9923 62.1468C26.9804 54.762 26.9838 47.3789 26.9906 39.9941C26.9906 39.3022 27.1402 38.6375 27.5193 38.0408H27.5227Z"
|
|
24
|
+
fill="#001719" />
|
|
25
|
+
<path
|
|
26
|
+
d="M50.0801 67.7532C49.3763 67.7532 48.7286 67.556 48.12 67.2109C44.0298 64.8955 39.9396 62.5801 35.846 60.2698C34.9739 59.7785 34.5574 59.0509 34.5591 58.0479C34.5676 53.4545 34.5676 48.8628 34.5574 44.2694C34.5574 43.5911 34.5965 42.9281 34.8226 42.2855C35.1864 41.478 35.8103 40.9289 36.56 40.4869C40.2762 38.3024 43.9907 36.1145 47.6967 33.913C49.0295 33.1208 50.3419 33.1021 51.6849 33.8637C55.6017 36.0822 59.5219 38.2956 63.4421 40.5073C64.0201 40.8337 64.4468 41.3063 64.8072 41.8503C65.2186 42.4895 65.3325 43.1984 65.3325 43.9464C65.3257 48.3375 65.3291 52.7269 65.3308 57.118C65.3308 58.5494 64.7052 59.6289 63.4846 60.3514C59.629 62.6362 55.7649 64.9108 51.9059 67.1905C51.3415 67.5237 50.7363 67.7209 50.0801 67.7566V67.7532Z"
|
|
27
|
+
fill="#CFF0FE" />
|
|
28
|
+
</g>
|
|
29
|
+
<defs>
|
|
30
|
+
<clipPath id="clip0_1352_405">
|
|
31
|
+
<rect width="75.8863" height="85" fill="white" transform="translate(12 8)" />
|
|
32
|
+
</clipPath>
|
|
33
|
+
</defs>
|
|
34
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100" height="100" rx="24" fill="white"/>
|
|
3
|
+
<path d="M17.1241 75.9548C19.8893 73.1896 24.3725 73.1896 27.1378 75.9548C29.903 78.72 29.903 83.2037 27.1378 85.9689L24.3213 88.7853C24.0337 89.073 23.6922 89.3013 23.3164 89.457C22.9406 89.6127 22.5377 89.6928 22.1309 89.6928C21.7241 89.6928 21.3213 89.6127 20.9454 89.457C20.5696 89.3013 20.2281 89.073 19.9405 88.7853L17.1241 85.9689C14.3588 83.2037 14.3588 78.72 17.1241 75.9548ZM82.5503 75.9548C79.7851 73.1896 75.3018 73.1896 72.5366 75.9548C69.7714 78.72 69.7714 83.2037 72.5366 85.9689L75.3531 88.7853C75.6407 89.073 75.9822 89.3013 76.3581 89.457C76.734 89.6127 77.1368 89.6929 77.5437 89.6929C77.9505 89.6929 78.3534 89.6127 78.7293 89.457C79.1051 89.3013 79.4466 89.073 79.7343 88.7853L82.5503 85.9689C85.3156 83.2037 85.3156 78.72 82.5503 75.9548Z" fill="#C6FF00"/>
|
|
4
|
+
<path d="M10 47.282C10 38.6511 19.2901 33.2106 26.8178 37.4339C28.429 38.3379 29.7938 39.6234 30.7926 41.1777C31.7913 42.732 32.3935 44.5076 32.5462 46.3488L35.0275 76.2699C35.0553 76.6055 35.0132 76.9433 34.9038 77.2619C34.7945 77.5804 34.6203 77.8728 34.3922 78.1206C34.164 78.3684 33.887 78.5662 33.5786 78.7015C33.2702 78.8368 32.937 78.9067 32.6002 78.9067H12.4356C11.7897 78.9067 11.1703 78.6502 10.7135 78.1935C10.2568 77.7368 10.0001 77.1174 10 76.4715V47.282Z" fill="#4285F4"/>
|
|
5
|
+
<path d="M90 47.282C90 38.6511 80.7095 33.2106 73.1823 37.4339C71.571 38.3379 70.2061 39.6234 69.2074 41.1777C68.2086 42.732 67.6065 44.5076 67.4538 46.3488L64.9726 76.2699C64.9447 76.6055 64.9868 76.9433 65.0961 77.2619C65.2054 77.5805 65.3796 77.8729 65.6078 78.1208C65.8359 78.3686 66.1129 78.5664 66.4214 78.7017C66.7298 78.8369 67.063 78.9068 67.3998 78.9067H87.5644C87.8843 78.9067 88.201 78.8437 88.4965 78.7213C88.792 78.5989 89.0605 78.4195 89.2867 78.1933C89.5128 77.9672 89.6922 77.6987 89.8146 77.4032C89.937 77.1077 90 76.7909 90 76.4711V47.282Z" fill="#4285F4"/>
|
|
6
|
+
<path d="M24.2293 46.3729C24.2293 46.3729 34.2658 53.143 50.0424 53.143C65.819 53.143 75.8555 46.3729 75.8555 46.3729V40.9193L68.9166 33.6516L50.0424 40.6281L31.1682 33.6516L24.2293 40.9193V46.3729Z" fill="white"/>
|
|
7
|
+
<path d="M75.7287 39.9718C75.6137 39.2196 75.4651 38.4728 75.2835 37.7338C74.7892 35.7166 74.0537 33.7663 73.093 31.9249C71.5673 28.9981 69.4985 26.3883 66.997 24.2349C65.9822 23.3599 64.9015 22.5645 63.7645 21.8556C63.7746 21.8392 63.7833 21.8216 63.7933 21.8052C64.3154 20.904 64.8382 20.004 65.3602 19.1032L66.8914 16.464C67.2582 15.8328 67.625 15.2 67.9902 14.5684C68.1748 14.2499 68.2829 13.8929 68.3061 13.5255C68.3293 13.1581 68.2669 12.7903 68.1238 12.4511C67.9281 11.9834 67.5864 11.5914 67.1498 11.3335C66.7099 11.0737 66.1985 10.961 65.6902 11.0119C65.3172 11.0504 64.9586 11.1765 64.6437 11.38C64.3288 11.5835 64.0665 11.8585 63.8782 12.1828C63.5113 12.8144 63.1445 13.4468 62.7789 14.0784L61.2477 16.7172C60.7261 17.6184 60.2029 18.5184 59.6813 19.4192C59.6245 19.5176 59.5665 19.616 59.5097 19.7156C59.4305 19.684 59.3521 19.6524 59.2729 19.6224C56.2309 18.4649 52.9982 17.8898 49.7436 17.9272C46.9208 17.9527 44.1211 18.4384 41.4547 19.3652C41.1535 19.4696 40.8563 19.5808 40.5611 19.6964C40.5083 19.6044 40.4543 19.5124 40.4011 19.4204C39.8795 18.5196 39.3563 17.6196 38.8347 16.7184L37.3035 14.0796C36.9367 13.448 36.5699 12.8156 36.2043 12.1839C35.9781 11.7938 35.6454 11.4761 35.2453 11.2681C34.8451 11.0601 34.394 10.9704 33.9447 11.0095C33.587 11.0398 33.241 11.151 32.9327 11.3347C32.3983 11.6515 32.0099 12.1657 31.8514 12.7664C31.6895 13.3757 31.7761 14.0244 32.0922 14.57L33.1911 16.4652L34.7223 19.1044C35.2443 20.0052 35.7671 20.9052 36.2887 21.8064L36.3015 21.8288C35.2516 22.4809 34.2492 23.2066 33.3018 24.0005C32.7362 24.475 32.1909 24.9734 31.6674 25.4941C30.6245 26.5306 29.6708 27.6533 28.8166 28.8501C28.1161 29.8306 27.4853 30.859 26.9286 31.9278C25.6638 34.3522 24.7913 36.9618 24.3438 39.6594C24.3262 39.7642 24.3098 39.8698 24.2934 39.9746C24.2354 40.3528 24.1858 40.7323 24.1446 41.1126H75.8735C75.8323 40.7323 75.7827 40.3528 75.7247 39.9746L75.7287 39.9718Z" fill="#34A853"/>
|
|
8
|
+
<path d="M63.4621 33.9632C64.4974 33.2748 64.6478 31.6816 63.7981 30.4052C62.9485 29.1284 61.4209 28.652 60.3861 29.3404C59.3513 30.0292 59.2009 31.6224 60.0501 32.8988C60.8997 34.1756 62.4273 34.6521 63.4621 33.9632ZM40.0127 32.8968C40.8623 31.62 40.7119 30.0272 39.6767 29.3384C38.6419 28.6496 37.1143 29.1264 36.2647 30.4028C35.4155 31.6796 35.5659 33.2728 36.6007 33.9612C37.6355 34.6501 39.1631 34.1732 40.0127 32.8968Z" fill="#202124"/>
|
|
9
|
+
<path d="M24.2293 43.1335H75.8555V63.6782C75.8555 77.9343 64.2985 89.4908 50.0424 89.4908C35.7863 89.4908 24.2293 77.9343 24.2293 63.6782V43.1335Z" fill="#34A853"/>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Карта оформления MyApplication
|
|
2
|
+
|
|
3
|
+
Используй эту карту после экспорта tracked files из `MyApplication`. Сначала прочитай фактические
|
|
4
|
+
файлы шаблона: карта фиксирует его ожидаемую структуру, но не отменяет проверку новых tracked files.
|
|
5
|
+
|
|
6
|
+
## Обязательные замены
|
|
7
|
+
|
|
8
|
+
| Область | Файл или путь | Что изменить |
|
|
9
|
+
| ------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
10
|
+
| Gradle project name | `settings.gradle.kts` | `rootProject.name = "My Application"` на согласованное имя |
|
|
11
|
+
| Namespace | `app/build.gradle.kts` | `namespace = "org.michaelbel.myapplication"` на новый namespace |
|
|
12
|
+
| Application ID | `app/build.gradle.kts` | `applicationId = "org.michaelbel.myapplication"` на новый application ID |
|
|
13
|
+
| APK archive prefix | `app/build.gradle.kts` | `MyApplication-v...` на имя артефакта без пробелов |
|
|
14
|
+
| Kotlin package | `app/src/**/kotlin/**/*.kt` и будущие `java` source sets | Старые package/import references на новый namespace |
|
|
15
|
+
| Package directory | `app/src/main/kotlin/org/michaelbel/myapplication` и существующие test source sets | Переместить в директорию, соответствующую сегментам нового namespace; удалить опустевшие каталоги |
|
|
16
|
+
| App label | `app/src/main/res/values/strings.xml` | `My Application` на display name приложения |
|
|
17
|
+
| GitHub agent | `.github/agents/android.agent.md` | Имя `MyApplication`, package и устаревшие утверждения о структуре проекта |
|
|
18
|
+
| README | `README.md` | Старое имя, описание и все `michaelbel/myapplication` links на новый owner/repo; затем применить актуальные README rules |
|
|
19
|
+
| Git ignore | `.gitignore` | Сохранить build/local patterns и привести `.claude/`, `.idea/`, `!.idea/icon.svg` к актуальным repository rules |
|
|
20
|
+
| IDE icon | `.idea/icon.svg` | Заменить выбранным asset из skill |
|
|
21
|
+
|
|
22
|
+
`AndroidManifest.xml` использует относительное имя `.MainActivity`, поэтому при совпадении namespace
|
|
23
|
+
и package отдельная замена обычно не нужна. Если application ID и namespace намеренно различаются,
|
|
24
|
+
проверь manifest/component resolution явно.
|
|
25
|
+
|
|
26
|
+
## Неприкосновенные значения
|
|
27
|
+
|
|
28
|
+
Не меняй при переименовании:
|
|
29
|
+
|
|
30
|
+
- содержимое `.github/debug-key.jks`;
|
|
31
|
+
- `keyAlias = "myapplication"`;
|
|
32
|
+
- `storeFile = rootProject.file(".github/debug-key.jks")`;
|
|
33
|
+
- существующие `keyPassword` и `storePassword`;
|
|
34
|
+
- имена `debug` signing config и debug build type.
|
|
35
|
+
|
|
36
|
+
Не печатай password-поля при проверке `app/build.gradle.kts`. Сравни checksum key store до и после
|
|
37
|
+
оформления; одного совпадения имени файла недостаточно.
|
|
38
|
+
|
|
39
|
+
## Что переносить из шаблона без переименования
|
|
40
|
+
|
|
41
|
+
- `.github/FUNDING.yml` и `.github/CODEOWNERS`, если owner остаётся `michaelbel`;
|
|
42
|
+
- `.github/workflows/ci.yml`, пока модуль остаётся `app` и output layout не меняется;
|
|
43
|
+
- `AGENTS.md` и симлинки `CLAUDE.md`, `GEMINI.md`;
|
|
44
|
+
- Gradle wrapper, version catalog, SDK и dependency versions;
|
|
45
|
+
- launcher/splash drawables и тему как стартовое оформление, пока пользователь не запросил новый
|
|
46
|
+
branding.
|
|
47
|
+
|
|
48
|
+
Проверь эти файлы на соответствие актуальным правилам. «Без переименования» не означает сохранять
|
|
49
|
+
устаревшую структуру, если источник правил уже изменился.
|
|
50
|
+
|
|
51
|
+
## Что нельзя переносить
|
|
52
|
+
|
|
53
|
+
Экспорт через `git archive HEAD` автоматически исключает большую часть списка. При другом способе
|
|
54
|
+
копирования явно исключи:
|
|
55
|
+
|
|
56
|
+
- `.git/` и историю `MyApplication`;
|
|
57
|
+
- `.gradle/`, `.kotlin/`, все `build/`;
|
|
58
|
+
- `local.properties`;
|
|
59
|
+
- `.DS_Store`;
|
|
60
|
+
- `.claude/settings.local.json`;
|
|
61
|
+
- `.idea/.name`, `*.iml`, `workspace.xml`, caches, device/deployment settings и прочие локальные IDE
|
|
62
|
+
файлы.
|
|
63
|
+
|
|
64
|
+
В новом проекте tracked `.idea`-содержимым должен быть только `.idea/icon.svg`.
|
|
65
|
+
|
|
66
|
+
## Контрольный поиск
|
|
67
|
+
|
|
68
|
+
Ищи старые значения адресно во всех текстовых файлах, экспортированных из template `HEAD`. До
|
|
69
|
+
первого staging они ещё не считаются tracked в новом репозитории:
|
|
70
|
+
|
|
71
|
+
- `MyApplication`;
|
|
72
|
+
- `My Application`;
|
|
73
|
+
- `org.michaelbel.myapplication`;
|
|
74
|
+
- `michaelbel/myapplication`;
|
|
75
|
+
- старый package-directory path.
|
|
76
|
+
|
|
77
|
+
Отдельно проверь lowercase `myapplication`, исключив password-поля и бинарный key store. Единственное
|
|
78
|
+
обязательное оставшееся project-specific совпадение — `keyAlias = "myapplication"`; путь
|
|
79
|
+
`.github/debug-key.jks` также остаётся прежним.
|
|
80
|
+
|
|
81
|
+
## Итоговый checklist
|
|
82
|
+
|
|
83
|
+
- [ ] Новая директория содержит только экспортированные tracked files и осознанно созданные локальные файлы.
|
|
84
|
+
- [ ] История шаблона не перенесена; remote не добавлен без запроса.
|
|
85
|
+
- [ ] Gradle name, namespace, application ID и archive prefix согласованы.
|
|
86
|
+
- [ ] Kotlin package declarations и package directories совпадают.
|
|
87
|
+
- [ ] App label и README относятся к новому проекту.
|
|
88
|
+
- [ ] `.github/agents/android.agent.md` описывает новый проект.
|
|
89
|
+
- [ ] Выбран правильный Android/Compose/Jetpack icon.
|
|
90
|
+
- [ ] Debug key checksum не изменился, alias остался `myapplication`.
|
|
91
|
+
- [ ] В tracked text не осталось старых идентификаторов вне разрешённых signing-значений.
|
|
92
|
+
- [ ] После первого commit проходят `assembleDebug` и `lint`.
|