From kto-ma-racje-toolkit
Kompletny, wielowymiarowy audyt aplikacji "Kto Ma Rację?". Uruchom gdy user poprosi o "pełny audyt", "full audit" lub "audyt aplikacji". Uruchamia 10 agentów równolegle i dostarcza zbiorczy raport BLOCKER/WARNING/INFO. Wersja v2 (po retrospektywie 2026-05-01) — dodane: schema drift, lifecycle matrix, anti-pattern sweep repo-wide, cross-function consistency, fix-induced regression detection.
How this skill is triggered — by the user, by Claude, or both
Slash command
/kto-ma-racje-toolkit:full-auditThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Przeprowadź KOMPLETNY, WIELOWYMIAROWY audyt aplikacji "Kto Ma Rację?".
Przeprowadź KOMPLETNY, WIELOWYMIAROWY audyt aplikacji "Kto Ma Rację?".
Subagent self-reports = false positives. "TS clean + verified" w raporcie subagenta nie znaczy "działa". Wymagaj konkretów: paste tsc output, paste grep callerów, simulate path mentally.
Anti-patterns powtarzają się. Gdy znajdujesz instance znanego anti-patternu (z lesson_*.md), sweep CAŁY repo grep'em — nie tylko obecne miejsce.
Fixy wprowadzają nowe bugi. Każdy fix-phase wymaga osobnego re-audytu zmienionych ścieżek. Zwłaszcza: contract changes (return shapes), routing additions (mutability of destination), nowe screens (visual pattern compliance).
Schema drift jest realny. Live DB ≠ migrations folder. Cross-check information_schema.tables vs supabase/migrations/ periodycznie.
RODO per-lifecycle, nie tylko delete-account. Cross-partner PII access matrix per event: signup / pair-create / dispute / pair-unpair / partner-deleted / account-delete. Każdy event ma inny cleanup contract.
Zanim zaczniesz — przeczytaj:
CLAUDE.md — zasady projektu, znane pułapki, historiadocs/PUBLICATION-CHECKLIST.md — co było sprawdzane wcześniejdocs/session-summaries/supabase/migrations/ — wszystkie migracje DB po koleilib/translations/pl.ts i en.ts — kompletność tłumaczeń + delta od ostatniego audytumemory/lesson_*.md, memory/feedback_*.md) — znane anti-patterns do sweep'uUruchom 10 agentów równolegle, każdy na innym obszarze. Zbierz wszystkie wyniki i dostarcz jeden zbiorczy raport z priorytetami BLOCKER / WARNING / INFO.
WSZYSTKIE 10 agentów MUSI używać subagent_type: "general-purpose". NIE używaj Explore dla żadnego.
Powód (lesson 2026-05-17): full-audit dispatched 10 agentów, 7/10 padło natychmiast z "Prompt is too long" — wszystkie 7 miały Explore, wszystkie 3 które przeszły miały general-purpose. Explore ma mniejszy input prompt budget bo jego system prompt jest bogatszy (search strategies, breadth modes). Audyt = open-ended cross-cutting analysis = dokładnie ten case dla którego tool description literalnie mówi "Do NOT use Explore for code review, design-doc auditing, cross-file consistency checks, or open-ended analysis".
Jeśli mimo general-purpose któryś agent padnie z "Prompt is too long" — skróć tylko jego prompt, nie wszystkich. Patrz memory/lesson_full_audit_subagent_type_choice.md.
Przetestuj każdą możliwą ścieżkę użytkownika od początku do końca. Dla każdej ścieżki sprawdź: czy każdy krok ma następny krok, czy żaden ekran nie jest ślepy zaułek, czy wszystkie dane przechodzą między krokami.
Rejestracja i onboarding:
Parowanie partnerów:
ktomaracje://join/CODE (legacy) i ktomaracje://pair?code=X&token=Y (Aurora) otwierają właściwy ekran?Flow sporu — pełna ścieżka:
Edge cases w flow sporu:
analysis_failed UI faktycznie się pokazuje — verify error.message/code propagation przez invokeEdge)Logowanie i sesja:
updateUser({password}) czy pozostałe sesje są invalidowane (signOut({scope: "others"}))?Usuwanie konta vs unpair (RODO):
delete-account czyści WSZYSTKIE tabele (profiles, couples, disputes, notifications, push_tokens, emotional_profiles, debug_logs, bonus_analyses)?emotional_profiles są DELETE'owane (bo couples archive ≠ couples delete, FK cascade nie strzela)?analyzing, both_done) mają visual cue?if (!user) return; w onPress/onSubmit handlers → każdy musi mieć Alertawait supabase.from(...).update(...).eq(...) BEZ .then(({error})=>...) lub const { error } = przed → silent failure riskawait supabase.from(...).insert(...) ten sam wzorzecapp.json jest prawdziwy (nie testowy)?ca-app-pub-3940256099942544~1458002511)?__DEV__ branch używa TestIds, prod używa real ID. TestIds w prod = $0 revenue + AdMob policy violation.console.warn)Dla każdego miejsca gdzie jest reklama, oceń:
requestNonPersonalizedAdsOnly: true NIE zastępujeAuroraBackground + GlassCard (gdzie pasuje) + GradButton zamiast raw TouchableOpacity z bg color + useTheme() zamiast static colorsapp/reset-password.tsx, app/confirm.tsx) — często pomijane bo "tylko 300ms"#[0-9A-Fa-f]{3,6}) w plikach .tsxuseColorScheme + lightColors/darkColors raw, nie static colorsnumberOfLines na display_name renders)TouchableOpacity i Pressable bez accessibilityLabelt() — hardcoded accessibilityLabel="Email" to bug (PL screen reader na EN UI mówi "Email", EN na PL mówi "Hasło")accessibilityRole na icon-only buttonsborderRadius używa tokens z lib/theme.ts?pl.ts z en.ts — raportuj różnice w obu kierunkachDeepStringify wymusza identyczną strukturę[ąćęłńóśźż] w string literalslang === "en" ? ... : ... ternaries — powinny być przez t() (poza locale codes typu "en-US" / "pl-PL")app.json — czy permission strings są bilingual?KAŻDY nowy klucz PL przeanalizuj pod kątem typowych błędów:
"Mieszane chmury" (n.) vs "Mieszanie chmury" (rzeczownik odsłowny — błąd)„" (otwierający dolny + zamykający górny), EN używa ""? ! :: w PL bez spacji (zawsze)Czytaj WSZYSTKIE nowe klucze (delta od ostatniego audytu), nie tylko spot-check 30 random.
expo-localization (OS locale), NIE z tekstu useraapp/dispute/[id].tsx — czy parsing werdyktu jest emoji-based, nie regex na polskie słowa?accessibilityLabel przechodzą przez t() (nie hardcoded "Email" / "Hasło")KAŻDA edge function wywołująca Claude API MUSI mieć IDENTYCZNY pattern. Skomparuj wszystkie 4: analyze-dispute, generate-profile, generate-context-hint, generate-continuation-context:
<dispute_data>/<history_data> markers? (każda fn)display_name sanitized: name.replace(/[^\p{L}\p{M}0-9 -]/gu, "").slice(0, 30)? (KAŻDA — flag jeśli któraś tylko truncate)Cross-function inconsistency = anti-pattern. Flag każdą rozbieżność jako WARNING.
SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';
Każda tabela MUSI mieć RLS enabled. Sprawdź każdą policy:
couples SELECT bez archived_at IS NULL może leakować)WITH CHECK matches USING?subscription_tier, archived_at, partner_*_id)? Trigger-based blocker?SELECT trigger_name, event_object_table FROM information_schema.triggers WHERE trigger_schema='public'SECURITY DEFINER trigger: czy search_path jest hardened (SET search_path = public, pg_temp)?console.log w edge fns dla user text (text_a, text_b, topic, bio, fears)debug_logs insert payloads — KAŻDY trace() call inspect for PII (display names liczą się jako PII pod RODO; lengths OK)Sentry.captureException extra field — czy nie wycieka user content?sk-ant-, sk_live_, eyJ w kodzie.gitignore — czy .env, credentials.json, *.keystore, google-services.json, GoogleService-Info.plist, *-service-account.json są wykluczone?.github/workflows/*.yml?supabase.functions.invoke() poza lib/invoke-edge.ts — powinno być ZEROverify_jwt: true/false per fn — udokumentowane w header komentarzu?crypto.timingSafeEqual lub equivalent constant-time compare?Math.random() jest zastąpiony przez crypto.getRandomValues() w sensitive contexts (invite tokens)?handleSubscribe robi prawdziwy zakup IAP, czy stub?EXPO_PUBLIC_IAP_ENABLED flag?SubscriptionContext czyta z couples.subscription_tier (NIE z RC SDK)?couples UPDATE policy/trigger blokuje client-side subscription_tier mutation? (krytyczne — bez tego user może self-grant Premium)bonus_analyses table + grant_bonus_analysis RPC istnieją w migracjach? (audit historyczny: były pre-existing schema drift)Zweryfikuj listę feature'ów i sprawdź czy każdy jest poprawnie gated server-side:
supabase/migrations/ z migration history table w prodEXPO_PUSH_TOKEN zapisywany przez register-push-token edge fn (NIE bezpośrednio w _layout.tsx — RLS race)?startsWith("ExponentPushToken[") po obu stronach (klient + serwer)?/dispute/<id>?eas.json profile development/preview/production poprawne?app.json ↔ package.json version match?versionCode inkrementowany przed prod build?.github/workflows/build-android.yml używa eas build --local?GOOGLE_SERVICES_JSON_B64 w eas-build-pre-install?EXPO_PUBLIC_* env vars exposed w workflow env: block (Sentry DSN, PostHog, RevenueCat)?import "../lib/sentry" przed JSX)?beforeSend (text_a/b, fears, bio)?npm audit — krytyczne podatności?expo-doctor — zgłasza problemy?Google Play:
app.json: tylko potrzebne android.permissions?App Store (przyszłość):
NSCameraUsageDescription per-locale?Przeczytaj WSZYSTKIE lesson_*.md w pamięci + feedback_*.md + ostatnie podsumowania sesji.
Dla każdego znanego bugfixa sprawdź:
Dla KAŻDEGO lesson_*.md zrób grep całego repo i wylistuj WSZYSTKIE instancje. Format:
Anti-pattern: <nazwa z lesson>
Pre-existing instances (znane historycznie): [file:line, ...]
NEW instances (wprowadzone od ostatniego audytu): [file:line, ...]
Status: ✅ all fixed / 🔴 N new instances / ⚠️ pattern repeated in NEW code
Konkretne sweepy do wykonania:
if (!user) return; w onPress handlers (lesson_dead_buttons_silent_returns) — repo-wide grepawait supabase.from(...).update(...) BEZ { error } destructure — repo-wide grepawait supabase.from(...).insert(...) BEZ { error } destructure — repo-wide grepsupabase.functions.invoke( poza invoke-edge.ts (lesson_functions_invoke_401_race) — powinno być ZEROclaude-.*-202[0-9] w edge fns (lesson_claude_model_aliases) — powinno być ZERO{var} w translations (lesson_i18next_interpolation) — zamiast {{var}}„" w TS literals bez escape (lesson_i18next_interpolation)FileSystem.cacheDirectory|writeAsStringAsync|EncodingType (lesson_expo_file_system_v19) — powinno być ZERO (deprecated API)startsWith("ExponentPushToken[") filter (lesson_push_token_format)lang === "en" ternaries dla UI text — zostają tylko locale codesaccessibilityLabel="..." z PL/EN słowami zamiast t('a11y.*')__DEV__ gates wokół monetyzacji (lesson_dev_gate_monetization) — powinno być ZEROcanOpenURL dla custom schemes na Android bez <queries> (lesson_linking_android11)#XXXXXX w app//lib/components/ poza lib/theme.tsPo sweep'ie, dla KAŻDEGO patternu który występuje 2+ razy w NEW code, dodaj propozycję:
mustSucceed(...))Cross-check live DB vs repo migrations.
-- Tables
SELECT table_name FROM information_schema.tables
WHERE table_schema='public' AND table_type='BASE TABLE'
ORDER BY table_name;
-- RPCs (procedures + functions)
SELECT proname, pronargs FROM pg_proc
WHERE pronamespace = 'public'::regnamespace
ORDER BY proname;
-- Triggers
SELECT trigger_name, event_object_table FROM information_schema.triggers
WHERE trigger_schema='public'
ORDER BY trigger_name;
-- Policies
SELECT tablename, policyname, cmd FROM pg_policies
WHERE schemaname='public'
ORDER BY tablename, policyname;
-- Columns per table (for column drift detection)
SELECT table_name, column_name FROM information_schema.columns
WHERE table_schema='public'
ORDER BY table_name, ordinal_position;
supabase/migrations/:.sql w supabase/migrations/ (włącznie z baseline 00000000000000_initial_schema.sql)supabase.from('X') w app/, lib/, supabase/functions/ — lista tabel używanych przez code.rpc('X') — lista RPCs używanych przez codeSCHEMA DRIFT REPORT
🔴 In prod but missing from migrations:
- Table: bonus_analyses
- RPC: grant_bonus_analysis(uuid)
- Trigger: ...
🔴 In migrations but missing from prod (migration not applied):
- ...
⚠️ Column type / nullability mismatch:
- couples.subscription_tier: prod = text, migration = varchar
✅ In sync: N tables, N RPCs, N triggers, N policies
Sprawdź cleanup contracts per-lifecycle-event, nie tylko delete-account.
Per event wypełnij macierz:
| Event | Tables modified | Data deleted | Data preserved | Cross-partner PII access AFTER | Notifications |
|---|---|---|---|---|---|
| signup | profiles, couples? | - | - | - | - |
| email_confirm | auth.users | - | - | - | - |
| couple_create | couples, profiles | - | - | - | - |
| pair_invite_create | pair_invites | - | - | - | - |
| pair_invite_redeem | pair_invites, couples, profiles | - | - | - | - |
| dispute_create | disputes | - | - | - | push to partner |
| dispute_respond | disputes | - | - | - | push to creator |
| dispute_reveal | disputes | - | - | - | - |
| dispute_analyze | disputes, debug_logs | - | - | - | push to both |
| pair_unpair (consensual) | couples (archive), profiles, emotional_profiles?, push_tokens? | ? | ? | CHECK: czy ex-partner czyta drugiego emotional_profile? | push to survivor |
| partner_deleted (one-sided) | couples (archive), auth.users | cascade chain | survivor's data | survivor sees archived couple | push to survivor |
| account_delete (full RODO) | wszystkie tabele | wszystko user-owned | nic | nic | push to partner |
Tables modified:
Data deleted:
Data preserved:
Cross-partner PII access AFTER event (KRYTYCZNE):
profiles, emotional_profiles, disputes text_a/b, bonus_analyses granted_to)Notifications:
LIFECYCLE MATRIX REPORT
🔴 RODO leaks (PII persists where it shouldn't):
- pair_unpair: emotional_profiles NOT deleted; ex-partner reads other's fears indefinitely
🟡 Soft cleanup gaps (90-day cutoff client-only):
- archived couples: 90-day grace enforced w `useArchivedCouple` hook only; SQL ma no cutoff
✅ Clean: account_delete cascades correctly; ...
Po zebraniu wyników wszystkich 10 agentów, dostarcz raport w tym formacie:
═══════════════════════════════════════════════
PEŁNY AUDYT — Kto Ma Rację?
Data: [data] · Wersja: [X.Y.Z]
═══════════════════════════════════════════════
🔴 BLOKERY (nie publikuj bez naprawy)
[lista z plikiem:linią i szacowanym nakładem pracy]
**Per blocker oznacz**: pre-existing | introduced-by-Faza-N
🟡 OSTRZEŻENIA (napraw przed closed testing)
[lista z plikiem:linią]
🟢 INFO (popraw kiedy będzie okazja)
[lista]
✅ CO DZIAŁA DOBRZE
[lista potwierdzonych mechanik]
📊 STATYSTYKI AUDYTU
- TypeScript errors: X
- Translation key parity: X = X (PL ↔ EN)
- Hardcoded PL/EN strings in app/.tsx: X
- Inline lang === "en" ternaries (excl. locale codes): X
- Screens without SafeAreaView: X
- Buttons without accessibilityLabel: X
- Console.log of user text in edge fns: X
- AI edge fns without rate limit: X
- Tables without RLS: X
- Schema drift items: X
- Bare supabase.functions.invoke() outside invoke-edge.ts: X
- Pinned Claude snapshots: X
- Silent .from().update() without { error }: X
🔁 FIX-INDUCED REGRESSIONS (NOWA SEKCJA)
Z poprzednich faz fix, które wprowadzone bugi:
- B2 (Faza 1): invokeEdge response shape change broke dispute UI handler
- W16 (Faza 1): reset-password.tsx skipped Aurora pattern
- ...
🔁 ANTI-PATTERN REPO-WIDE SWEEP (NOWA SEKCJA)
Per known lesson_*.md anti-pattern:
- silent_returns: 5 instances [list], 0 new since last audit
- bare_supabase_invoke: 0 instances ✅
- ...
🔁 CROSS-CUTTING CONSISTENCY (NOWA SEKCJA)
- AI edge fns sanitization: 3/4 use canonical pattern, 1 (generate-profile) only truncates
- Error response shapes: limit_exceeded vs analysis_failed have different shapes
- New screens visual pattern: 4/5 use Aurora; reset-password.tsx bypasses
- ...
🔁 SCHEMA DRIFT (NOWA SEKCJA)
- ...
🔁 LIFECYCLE MATRIX (NOWA SEKCJA)
- ...
📋 PLAN NAPRAWY
Faza 1 (przed publikacją): [lista z czasem]
Faza 2 (przed closed testing): [lista z czasem]
Faza 3 (post-launch): [lista z czasem]
SZACOWANY CZAS NAPRAWY BLOKERÓW: X godzin
WERDYKT: GOTOWY DO PUBLIKACJI / WYMAGA NAPRAWY (X blokerów)
lesson_*.md w pamięcipackage.json + app.json (flag mismatch)Każdy subagent prompt MUSI zawierać sekcję:
Verification checklist (MUST report in summary):
1. Paste exact `npx tsc --noEmit` output
2. Grep for all callers of changed APIs (paste file:line list)
3. For new code paths: simulate happy path mentally + walk through each step
4. For new screens: verify follows Aurora pattern (AuroraBackground/GlassCard/GradButton)
5. For changed contracts: list every consumer + verify they handle new shape
6. For DB changes: verify trigger/policy implications across other tables
7. Anti-pattern sweep: if fixing instance of known anti-pattern, grep entire codebase, fix ALL
lessons-update skill żeby wyciągnąć anti-patterns / fix-induced regressions / surprises i zapisać do memory/ jako lessons. To zwiększa baseline dla kolejnych sesji (auto-load via SessionStart hook).v2 (2026-05-01) — po retrospektywie pełnego cyklu audyt + 5 fix-phases:
npx claudepluginhub marcin-elj/kto-ma-racje-toolkit --plugin kto-ma-racje-toolkitGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.