Přeskočit obsah

Dev Log — Sofie Kosmo

Kontextový soubor pro cross-session continuitu. Každá nová session si načte stav.

Pozor: Záznamy od 2026-04-08 níže popisují stav před clean-slate resetem 2026-04-22. Ten celý kód (dashboard, events, tasks, excuses, departures, parent, posts, n8n Posts AI workflow) byl smazán. Relevantní archivní záznam, ale nereprezentuje aktuální stav appky. Aktuální stav viz sekce 2026-04-22 a 2026-05-11 výše.

Prostředí

  • Produkční data: ŽÁDNÁ. Databáze obsahuje jen testovací/seed data. Není potřeba opatrnost s migracemi.
  • Supabase: Cloud (free plan), jediná instance, žádný staging.
  • Deploy: Zatím lokální vývoj + Supabase Cloud.

Proč: /architect-review design review odhalil tři praktické problémy v aktuálním auth: (1) staff reálně používá M365, ne Google → Google tlačítko je „mrtvý" provider; (2) rodičovský portál spuštění do 3 měsíců potřebuje login flow; (3) password fallback drží attack surface, který nikdo nevyužívá. Provider rozhodnutí na úrovni školy (M365 ↔ Google Workspace) je navíc pohyblivé, takže cementovat ho do auth vrstvy je riziko.

Rozhodnutí: Magic Link only pro všechny role. Žádný OAuth provider, žádné heslo. Detaily v docs/decisions/2026-05-14-auth-design.md + ADR auth-magic-link-only.md. Apple Sign-In zamítnut.

Implementace (feature/auth-magic-link): - Nový web/src/utils/supabase/admin.ts — service-role client (jen server-side, pro admin.generateLink). - Nový web/src/lib/schemas/auth.ts — Zod schémata pro magic-link request (INV-ARCH-01). - web/src/app/login/actions.ts přepsán: login (Google) a loginWithPassword smazány; nová requestMagicLink (volá signInWithOtp); devQuickLogin přepsán passwordless přes admin generateLink + verifyOtp, gated KOSMO_DEMO_MODE. - web/src/app/login/page.tsx refaktor: jeden e-mail input + tlačítko „Pošli mi přihlašovací odkaz"; quick-login panel se zobrazí jen pokud KOSMO_DEMO_MODE=true. - web/src/app/auth/callback/route.ts — beze změny (exchangeCodeForSession zvládá magic link token). - Nový invariant INV-AUTH-05 v docs/invariants.md + test web/tests/invariants/login-magic-link-only.spec.ts. - INV-AUTH-04 rozšířen (auth callback, ne jen OAuth). - E2E test web/tests/e2e/auth.spec.ts aktualizován pro magic-link flow. - docs/intent/auth-and-roles.md updated (definice úspěchu + out-of-scope).

Operační požadavky: - Supabase Dashboard: enable Email/OTP magic-link mode, TTL 900s, single-use; disable Google/Azure/Apple providery. - Supabase Pro upgrade ($25/měsíc) — předpoklad pro prod rollout rodičům (Free tier mailer 4 maily/h nestačí na 100 rodičů). Tomáš dělá v paralelně. - web/.env.local + Vercel: SUPABASE_SERVICE_ROLE_SECRET (z Supabase Dashboard → Settings → API → service_role; stejná hodnota je už v infra/.env, jen ji zkopírovat), KOSMO_DEMO_MODE=true (jen dev/preview, NIKDY v prod env).

Co nepřišlo: Custom SMTP / Resend integraci jsme úmyslně neimplementovali (default Supabase mailer + Pro upgrade pokryje, Resend je první fallback kdyby doručitelnost zlobila).


2026-05-13 — I³ methodology zavedena (Intent + Invariants + Implementation)

Proč: Repo je plně vibe-coded. Aby PO mohl předávat zadání jakémukoli agentovi a aplikace se reprodukovala se zachovanými pravidly, kód nesmí být kontrakt. Spec-driven sám o sobě je málo (textový dokument lže snadno). Zvolena I³: tenký brief per feature + invariants registry (kritické mají test) + ADRs.

Co se změnilo:

Před Po
docs/specs/ (formal 7-sekční spec) docs/intent/ (4-sekční brief, ~1 strana)
docs/specs/designs/ docs/decisions/ (ADRs, append-only)
docs/BACKLOG.md (vize jako kontrakt) docs/ideas/roadmap.md (vize bez závazku)
docs/ARCHITECTURE.md (mix invariants + stack + vize) docs/invariants.md (4 disciplíny jako INV-ARCH-01..04) + zbytek do ADR / ideas / CLAUDE.md tabulky
docs/REQUIREMENTS.md (overlap s VISION + specs) (smazáno) — implemented features v intent/, vize v ideas/, KPI ve VISION.md
~~spec coverage check~~ doc-curator kontroluje I³ pokrytí (intent ↔ routy ↔ invariants ↔ testy)

Pilot proběhl na auth modulu: brief auth-and-roles.md + 4 invariants (INV-AUTH-01..04) + Playwright test web/tests/invariants/role-gating.spec.ts. Fresh agent z jen docs/intent/auth-and-roles.md + invariants.md + DATAMODEL.md uhádl 5/5 kritických invariants — gate prošel.

Backfill v jednom sprintu: 7 retro briefs (auth, classbook, attendance, slot-topics, students-registry, schedule-slots, day-overrides) + 4 DATA invariants + 4 ARCH invariants. Strážci aktualizováni: doc-curator, product-coach, architect, define command, AGENTS.md lifecycle, PR template.

Klíčová pravidla I³: - Kód není kontrakt → svobodně přepisovatelný (full rewrite je standardní varianta v /architect-review). - Brief popisuje WHAT/WHY, NE jak ani DDL. - Critical invariant bez testu neexistuje → CI gate. - Vize jdou do ideas/, brief vzniká až při /define.

Distribuce smazaných docs: - ARCHITECTURE.md Disciplíny → docs/invariants.md (INV-ARCH-01..04) - ARCHITECTURE.md Stack → CLAUDE.md tabulka - ARCHITECTURE.md Feed / Messaging / Modules → docs/ideas/feed-vision.md - ARCHITECTURE.md Deployment → překryv s docs/DEPLOYMENT.md (nepřesouváno) - REQUIREMENTS.md feature seznam → docs/intent/ (Implemented) + docs/ideas/roadmap.md (future) - REQUIREMENTS.md KPI → docs/VISION.md (vlastní KPI) - REQUIREMENTS.md NFR → docs/invariants.md (INV-META-01 + dílčí v invariants) - BACKLOG.md → docs/ideas/roadmap.md (přejmenováno s git mv pro historii)


2026-05-13 — Bootstrap setup playbook uzavřen

Konec setup fáze. Iterace 1–5 z plánu kompletní. Tým + infra připravené k produktivnímu vývoji feature přes /define → /architect-review → main Claude → /ux-audit → PR → merge cyklus.

Co se za 3 dny (2026-05-11 až 2026-05-13) postavilo

Vrstva Co stojí Verifikace
Autonomní tým AGENTS.md + 5 subagents (product-coach, architect, ux-designer, process-analyst, doc-curator) + 5 slash commands + Definition of Ready scaffold Architect-review proběhl 2× (Iterace 3, define-readiness), doc-curator proběhl 1× (bootstrap), process-analyst proběhl 1× (bootstrap retro 16 položek, 9 schváleno)
Verifikace Playwright e2e (chromium + Pixel 7), 8/8 smoke testů, GitHub Actions web-ci (lint + build + e2e) CI běží na každý PR; web-ci je required status check
Merge gate CODEOWNERS, PR template, branch protection na main (GitHub Pro) — auto-enforced: CI + 1 approval + resolved conversations + 0 HIGH security findings 5 PRs prošlo přes nový gate (#6 #7 #8 #9 #10)
Observability @sentry/nextjs (client + Node.js + edge), source maps upload v next build, region EU Frankfurt, free 5k events/měs Smoke confirmed: HTTP 500 → event v dashboardu < 30s, stack trace čitelný
Scheduled meta kosmo-monthly-retro (1. v měsíci 20:00) + kosmo-monthly-curate-docs (15. v měsíci 20:00) First curate fires 2026-05-15, first retro 2026-06-01
Data Supabase Cloud DB seedovaná (6 staff + 24 students + 50 schedule slots + guardians + class_staff) select count(*) ověření přes Supabase MCP
Deploy chain Vercel auto-deploy (web app) + Cloudflare Pages (docs.sofie.education) + GitHub Pages backup (gh-pages branch z docs.yml workflow) App.sofie.education + docs.sofie.education aktivní
Memory project_dev_tokens.md (GH + Vercel patterns), MEMORY.md index up-to-date Konsolidováno během setup

Co je deferred (rozhodnuto, ne blokující)

  • Vercel + Supabase Pro upgrade ($45/měs) — eliminuje Supabase auto-pause, password-protected previews, Supabase database branching pro per-PR staging.
  • GH Pages migration (z CF Pages) — jeden deploy target místo dvou, ale CF Pages teď funguje.
  • Sentry projekt rename javascript-nextjskosmo — cosmetic.
  • Supabase staging strategy (architect-review TBD) — záleží na Pro upgrade.
  • GDPR before-production gate — checklist v AGENTS.md, aktivuje se před prvním deploy s reálnými daty žáků.
  • Cost monitoring — náklady aktuálně minimální, do retro queue.
  • GitHub Issues od učitelů + triage — až po onboardingu ředitele.

Side findings + akce zaznamenané po cestě

  • Supabase Free auto-paused → unpaused, ale opakovat se bude každý ~týden bez Pro.
  • Vercel SSO Deployment Protection vypnutá pro headless smoke testy (pre-prod akceptovatelné).
  • Cloudflare Pages stale failing → opraveno v Iteraci closure 2026-05-13 (Python requires-python >=3.14>=3.12, nav broken refs vyčištěno).
  • Define-readiness scaffold přidal Definition of Ready gate + docs/intent/ scaffolding (z paralelního architect-review).

Příští kroky (po uzavření, na volbě PO)

  1. First /define na U-04 — pilot feature flow přes celý pipeline (validuje end-to-end vibe coding s autonomous týmem).
  2. Wait & observe — nech scheduled tasks rozjet (15. 5. první curate cron, 1. 6. první retro). Data z prvních automatických runů budou rich vstup pro budoucí rozhodnutí.
  3. Pro upgrade rozhodnutí kdykoli odděleně, až bude motivace (auto-pause friction, GDPR příprava, branching potřebné).

Closure verdict

Bootstrap setup playbook = ✅ kompletní. Repo je production-ready v pre-prod fázi (bez reálných dat). Next phase = feature development, řízený autonomous týmem.


Smoke test ✅: curl https://sofie-kosmo-ptxmf8xjl-doceks-projects.vercel.app/api/sentry-example-api → HTTP 500, event v Sentry dashboardu, stack trace čitelný (source mapy uploaded úspěšně z Vercel build). Sentry integrace funguje on production-grade Vercel deploy přes všechny tři runtimes (client + Node.js + Edge).

Side findings během smoke testu (vyřešené)

  1. Supabase Free auto-paused projekt po neaktivitě (subdomain iwcisgvhwdzztrfdrpkl.supabase.co neresolvoval). Tomáš unpaused přes dashboard. Důsledek: Free tier auto-pauses každý ~týden neaktivity, na produkci nepoužitelné. Decision: Supabase Pro upgrade plánován (viz „Náklady" rozhodnutí).

  2. Vercel Deployment Protection byla v stavu ssoProtection.deploymentType: "all_except_custom_domains", takže všechny *.vercel.app URLs (vč. previews) vyžadovaly Vercel SSO login. Dnes vypnuto přes REST API (PATCH /v9/projects/{id} body {"ssoProtection": null}) pro umožnění headless smoke testů + ostatních automation. Akceptovatelné v pre-prod fázi (žádná reálná data). Po Vercel Pro upgrade přepneme na password-protected previews (Free umí jen SSO, Pro umí password — ředitel klikne, hotovo).

  3. Supabase Cloud DB má 0 rows ve všech 15 tabulkách — nikdy nebyla seedovaná. Dev quick-login (signInWithPassword s password123) selhal protože žádný profiles user neexistuje na cloudu. Action item pro Iteraci 5+: seed cloud DB ze supabase/seed.sql před prvním reálným uživatelským testem, nebo nastavit auto-seed v migration deployment workflow.

Cleanup v tomto commitu

  • web/src/app/sentry-example-page/ + web/src/app/api/sentry-example-api/ smazány. Wizard je vytvořil jako one-shot smoke verifikaci, smoke jsme provedli, dlouhodobě jsou to public throw endpoints v produkci = noise events + drobný abuse risk. Pro budoucí smoke (např. po major upgrade Sentry SDK) lze přidat ad-hoc throw v dev-only path.
  • @sentry/nextjs v web/, source maps upload v každém next build
  • ✅ GH Secrets: NEXT_PUBLIC_SENTRY_DSN, SENTRY_AUTH_TOKEN
  • ✅ Vercel env vars: oba klíče × všechny 3 prostředí (production + preview + development), kromě SENTRY_AUTH_TOKEN ne v dev
  • ✅ Memory: project_dev_tokens.md dokumentuje GH + Vercel patterns
  • ⚠️ Sentry projekt slug javascript-nextjs — nepřejmenován (wizard default). Pro retro: zvážit přejmenování na kosmo v Sentry dashboardu (org slug zs-sofie).

Další kroky

Iterace 5 plánu setupu: scheduled měsíční /retro + měsíční /curate-docs (cron přes mcp__scheduled-tasks__create_scheduled_task). Předtím lze: Pro upgrade všech 3 SaaS (Vercel + Supabase + GitHub Pro = $49/měs), pak architect-review na Supabase staging strategii.


2026-05-12 — Branch protection na main aktivní (GitHub Pro upgrade)

Kontext: Iterace 3 closure dokumentovala rozhodnutí o soft gate kvůli GitHub Free omezením. Dnes upgrade na GitHub Pro ($4/měs) — protection rules aplikovatelné. Soft gate nahrazený technickým gate.

Aplikováno přes gh api PUT /repos/docek/sofie-kosmo/branches/main/protection

{
  "required_status_checks": {
    "strict": true,
    "contexts": ["Lint + build + e2e"]
  },
  "required_pull_request_reviews": {
    "required_approving_review_count": 1,
    "require_code_owner_reviews": true,
    "dismiss_stale_reviews": false,
    "require_last_push_approval": false
  },
  "required_conversation_resolution": true,
  "allow_force_pushes": false,
  "allow_deletions": false,
  "enforce_admins": false
}

Verifikováno přes gh api repos/docek/sofie-kosmo/branches/main/protection.

Důsledek pro pipeline

Před: 5-step ruční checklist (AGENTS.md "Merge gate manuální"). Tomáš se musel disciplinovaně podívat na CI, approval, conversations, security-review, PR template — a NEMERGNOUT pokud něco chybí.

Po: GitHub merge button šedý dokud CI není zelená, není 1 approval z CODEOWNERS, a všechny komentáře vyřešené. Žádná disciplína potřeba, technický gate vynucuje.

Zbývající ruční kontrola: /security-review (skill, GitHub o ní neví) + PR template body čteknout + Vercel preview otestovat.

Cloudflare Pages check stále FAILURE

Side note: Cloudflare Pages status check na main je dlouhodobě v failure (z bootstrap doc-curate když se přesunul RFC → ideas/). Není required v branch protection contexts — proto neblokuje merge. Necháno k vyřešení v retro queue (separátní concern od web app deploy).

Update v AGENTS.md

Sekce "Merge gate" přepsaná z "manuální discipline gate" zpět na "auto-enforced via branch protection". Tabulka pravidel + procesní checklist + plánovaná rozšíření.

Memory update

project_dev_tokens.md už zaznamenává GH token s scope repo (postačuje na branch protection management).

Test gate na další PR

Tento commit je první přes nový gate — bude muset projít CI + dostat approval. Pokud projde čistě, gate funguje. Pokud zaseknutý, debug + fix v rámci tohohle PR.

Další kroky

  • Iterace 5: scheduled měsíční /retro + /curate-docs (cron přes scheduled tasks)
  • Supabase Pro + Vercel Pro upgrade — TBD rozhodnutí PO
  • Cloud DB seed (action item ze smoke test) — TBD

2026-05-12 — Define-readiness scaffold (architect-review → varianta A)

Kontext: /architect-review provedený nad otázkou „co chybí pro autonomní /define?" identifikoval 12 mezer mezi procesem (AGENTS.md ho popisuje) a artefakty (žádný hotový spec, šablona v agentí logice místo souboru, prázdná docs/specs/, USERS.md není prolinkovaná na specs, žádný DoR, BACKLOG bez „Next 3", chybí glosář).

Rozhodnutí PO

  • Varianta A (iterativní minimální lešení) místo B (per-feature folder + status.yaml) nebo C (zrušit agentí framework). Důvod: žádné 2+ use casy pro strojový YAML index před ≥ 5 implementovanými specs. B je platná evoluce, ne první krok.
  • Vše v jednom PR (feature/define-readiness-scaffold), žádná breaking change.

Změny

  • docs/specs/_TEMPLATE.md — šablona spec souboru jako single source of truth (vytažena z .claude/agents/product-coach.md).
  • docs/specs/_EXAMPLE-morning-attendance.md — kanonický vzor (U-01/02/03 retroaktivně zformalizováno).
  • docs/specs/README.md — index všech specs + workflow diagram + status konvence.
  • docs/specs/designs/.gitkeep — cílová složka pro architect outputs.
  • docs/GLOSSARY.md — doménový slovník (brand Sofie vs codename Kosmo, role v DB enumu, Montessori pojmy, tech stack zkratky).
  • AGENTS.md — nová sekce Definition of Ready (5 bodů, měkký gate) + odkaz v lifecycle diagramu.
  • .claude/agents/product-coach.md — nahrazena inline šablona odkazem na docs/specs/_TEMPLATE.md, přidán GLOSSARY + EXAMPLE krok do „Před zahájením dialogu".
  • docs/USERS.md — k U-01..U-08 přidán sloupec Spec / Status s linkem na spec a statusem (Implemented / Ready for /define / Backlog).
  • docs/BACKLOG.md — nová sekce nahoře ## Next 3 (Ready for /define) s U-04, U-05, U-07.
  • CLAUDE.md — index dokumentace doplněn o docs/GLOSSARY.md a docs/specs/.

Verifikace

End-to-end test smyčky odložen na první ostrý /define — Tomáš pravděpodobně U-04 (přiřazení tématu ročníku). Kritéria úspěchu: 1. Cold-start session umí spustit /define bez doplňujících procesních dotazů. 2. Architect po Approved umístí design do docs/specs/designs/u-04-*-design.md. 3. docs/specs/README.md index obsahuje nový řádek se statusem.

Další kroky

  • Dotáhnout otevřený curate-2026-05-11 PR (stale n8n/Listmonk/Twenty reference) — precondition, aby architect nečetl fikci.
  • Spustit první /define na U-04 a změřit, kolik procesních dotazů coach položí (cíl: 0).
  • Po 5 implementovaných specs vyhodnotit, jestli má smysl varianta B (per-feature folder + status.yaml).

2026-05-12 — Iterace 4: Sentry runtime error tracking

Kontext: AGENTS.md "Observability minimum" požaduje funkční error reporting před produkčním deployem. Bez něj jsi slepý — runtime errors v prohlížeči uživatelů se k tobě nedostanou.

Setup

  • Wizard (npx @sentry/wizard@latest -i nextjs) vytvořil základ:
  • web/src/instrumentation-client.ts (client init s Replay)
  • web/src/instrumentation.ts (server registration hook, onRequestError capture)
  • web/sentry.server.config.ts (Node.js runtime)
  • web/sentry.edge.config.ts (Edge runtime)
  • web/src/app/global-error.tsx (App Router error boundary)
  • web/src/app/sentry-example-page/ + web/src/app/api/sentry-example-api/ (smoke test endpoints — viz "Hygiena" níže)
  • web/next.config.ts obalený do withSentryConfig() (source maps upload, tunnel route /monitoring, tree-shake debug logging)
  • .env.sentry-build-plugin s SENTRY_AUTH_TOKEN (gitignored)
  • web/.gitignore aktualizovaný

  • Sentry projekt:

  • Org: zs-sofie
  • Project: javascript-nextjs (default wizard name — možné přejmenovat na kosmo později)
  • Region: EU (Frankfurt)ingest.de.sentry.io ✓ GDPR
  • Plan: Free (5k events/měs)

Vylepšení nad wizard default (per Sentry skill)

  1. DSN přesunutý do env varNEXT_PUBLIC_SENTRY_DSN (client) / SENTRY_DSN (server fallback). Wizard hardcodoval inline; env var je hygieničtější + umožní jiný DSN per environment, až bude potřeba.
  2. tracesSampleRate env-aware1.0 v dev, 0.1 v prod. Wizard nastavil 1.0 globálně, což by mohlo vyžrat 5k free quotu při traffic spike. 10% v prod stačí pro KPI tracking.
  3. includeLocalVariables: true v server config — wizard ho nedal, ale SKILL.md doporučuje. Stack frames pak nesou hodnoty proměnných → debugging produkčních errorů bez repro.
  4. Middleware matcher — přidán monitoring exclude pro tunnel route (/monitoring jde na Sentry, ne přes auth middleware).

GitHub Actions secrets (nastavené)

  • NEXT_PUBLIC_SENTRY_DSN — DSN, public-by-design (jde do client bundle)
  • SENTRY_AUTH_TOKEN — server-only secret pro source map upload

CI workflow update

.github/workflows/web-ci.yml build step nyní předává Sentry env vars. Source mapy se uploadují automaticky při next build na CI runneru.

Vercel env vars (TODO ručně PO)

CI build nahraje source mapy do Sentry. Ale Vercel build taky potřebuje obě env vars, aby: - NEXT_PUBLIC_SENTRY_DSN — bundloval se do client kódu na Vercel preview/prod - SENTRY_AUTH_TOKEN — nahrával source mapy z Vercel buildu (jinak stack traces na Vercel deployment budou minifikované)

Akce pro PO: 1. Vercel dashboard → sofie-kosmo project → Settings → Environment Variables 2. Add NEXT_PUBLIC_SENTRY_DSN (production + preview + development) 3. Add SENTRY_AUTH_TOKEN (production + preview, NE development — nepotřeba pro lokální vývoj)

Nebo přes vercel env add NEXT_PUBLIC_SENTRY_DSN production preview development (vyžaduje Vercel CLI auth).

Hygiena — example pages

Wizard vytvořil /sentry-example-page + /api/sentry-example-api jako smoke test endpointy. Nechány v repu pro teď kvůli verifikaci na Vercel preview po merge PR. Action item pro příští /retro nebo cleanup PR: rozhodnout, zda gate je za dev-only flag, nebo smazat. Public throw endpoint v produkci = noise + drobné riziko abuse (DoS přes vyvolávání errors).

Smoke test workflow

  1. PR otevřen → Vercel preview deploy → source mapy nahrané (CI logs to ověří)
  2. PO navštíví <preview-url>/sentry-example-page → klik na throw button
  3. PO ověří event v Sentry dashboardu (https://zs-sofie.sentry.io)
  4. Po confirmu: merge PR

Update AGENTS.md

Sekce "Observability minimum" rozšířená o konkrétní status: implementováno přes @sentry/nextjs, DSN region EU, free tier 5k events/měs. Když retro detekuje překročení quoty, zvážit Sentry Team plan ($26/měs) nebo snížit tracesSampleRate.

Další kroky

Iterace 5 plánu setupu: scheduled měsíční /retro + měsíční /curate-docs (cron přes mcp__scheduled-tasks__create_scheduled_task).


2026-05-11 — Iterace 3 closure: GitHub Free tier blocker → soft gate

Kontext: Iterace 3 (PR #4) zavedla CODEOWNERS, PR template a DEV-LOG záznam s plánem aplikovat branch protection přes gh api PUT .../branches/main/protection ihned po merge. Při pokusu o aplikaci:

HTTP 403: "Upgrade to GitHub Pro or make this repository public to enable this feature."

Stejná odpověď i pro novější Rulesets API (POST /rulesets). GitHub Free tier nepodporuje branch protection ani Rulesets na private repech. Vyžaduje GitHub Pro ($4/měs) nebo public repo.

Rozhodnutí PO (Tomáš)

  • Volba C — soft gate, $0. Branch protection vypnutá. Discipline drží AGENTS.md sekce "Merge gate (manuální, GitHub Free tier)" — Tomáš ručně v UI ověří 5 podmínek před merge (CI zelená, approval, resolved conversations, security-review bez HIGH, PR template checklist).
  • Sebe jako jediného CODEOWNER dnes, ředitel se přidá po onboardingu na GitHub.
  • GitHub Pro upgrade odložen — pokud retro v budoucnu ukáže, že manuální disciplína selhává (mergnuté PR s červenou CI, rollbacky), legitimní akce. $4/měs je v noise level.

Vedlejší zjištění (TODO follow-up)

"Cloudflare Pages" check selhal na latest main (60add93). Cloudflare Pages je nezávislý deploy service (mimo náš web-ci workflow), pravděpodobně se rozbil v souvislosti s docs reorganizací při bootstrap doc-curate (RFC → ideas/, SOFIE split, broken links v MkDocs config?). Není urgent — produkční docs.sofie.education běží pravděpodobně z gh-pages branch generovaného docs.yml workflow, ne přímo z Cloudflare Pages build. Action item pro příští /retro: prošetřit a opravit / vyřadit duplicitní deploy.

Update v AGENTS.md

Sekce "Merge gate" přepsaná z "branch protection" na "manuální discipline gate" s explicitní 5-step checklist a poznámkou o budoucím upgrade.

Další kroky

Iterace 4: Sentry integration v web/.


2026-05-11 — Iterace 3: branch protection na main

Kontext: Po Iteraci 2 máme CI workflow, ale je volitelný — bez branch protection lze merge i s červenou CI. Tahle iterace udělá z CI a code-review skutečný gate. Plán z setup playbooku, Iterace 3.

Co se zavedlo

  • .github/CODEOWNERS: default * @docek, plus explicitní vlastnictví autonomous-team konfigurace (AGENTS.md, CLAUDE.md, .claude/, .github/). Když se připojí ředitel jako co-owner, přidá se jeho GitHub handle (AGENTS.md říká „Tomáš nebo ředitel").
  • .github/pull_request_template.md: povinné sekce Summary / Preview / Co testovat / DB migrace / Breaking changes / Definition of Done checklist / Merge gate checklist. Donutí submitter ne přeskočit verifikaci.
  • Branch protection rules na main (aplikováno přes gh api po merge tohoto PR — vyžadují commit s CODEOWNERS na main):
  • Require pull request before merge
  • Require passing status check web-ci
  • Require 1 approval z CODEOWNERS
  • Require resolved conversations
  • Block force push, block deletion
  • enforce_admins=false (PO si v krajním případě může protlačit override; vibe coding s 1 člověkem nesmí blokovat sebe)

Důsledek pro pipeline

Od teď je merge gate na main plně auto-vynucený:

PR otevřen
  → CI běží (lint + build + e2e)
  → 1 approval z CODEOWNERS (Tomáš dnes; ředitel po onboardingu)
  → /security-review nemá HIGH severity
  → konverzace vyřešené
  → MERGE button enabled

Bez všech 4 checků je merge button šedý.

Akce pro PO

  • Volitelně přidat ředitele do CODEOWNERS, až bude mít GitHub účet napojený na repo.
  • Pokud se v budoucnu přidají další required status checks (Vercel deploy, Supabase migration validator), přidat je do branch protection (přes gh api nebo GitHub UI Settings → Branches).

Další kroky

Iterace 4 plánu setupu: Sentry integrace v web/ pro runtime error tracking + Iterace 5: scheduled měsíční /retro + /curate-docs.


2026-05-11 — Iterace 2: Playwright e2e + GitHub Actions web-ci

Kontext: První verifikační infrastruktura. Bez tohoto kroku je vibe coding slepý — žádný způsob, jak ověřit regrese před mergem. Plán z ~/.claude/plans/poj-me-chvilku-pln-na-clever-puzzle.md, Iterace 2.

Co se zavedlo

  • web/playwright.config.ts: 2 projekty (chromium desktop + mobile-chrome via Pixel 7), webServer auto-start pnpm dev, GitHub reporter v CI módu.
  • web/tests/e2e/auth.spec.ts: smoke test /login — ověří Kosmo brand, Google sign-in tlačítko, email/heslo input, dev quick-login panel. 8 testů zelená lokálně v 4.6 s.
  • web/package.json scripty: test:e2e, test:e2e:ui.
  • .github/workflows/web-ci.yml: na push do main + PR (paths web/** nebo workflow sám): pnpm install (frozen) → lint → build → cached Playwright browsers → e2e. Concurrency cancel-in-progress, timeout 15 min, artifact upload reportu při failure.
  • Mobile device volba — Pixel 7 (chromium) místo iPhone 12 (webkit): šetří playwright install webkit (~150MB stažení v CI). Real Mobile Safari coverage přijde, až bude konkrétní use case.

Tech debt vyflagovaný během setupu

ESLint v9 + eslint-plugin-react-hooks nové pravidlo react-hooks/set-state-in-effect označilo 5 pre-existing chyb v classbook komponentách: - AddTopicDialog.tsx:56 (reset state na close dialogu) - StudentMatrix.tsx:48, 60, 65 (mirroring props do state přes useEffect) - TopicAssignmentEditor.tsx:31 (mirroring topic.assigned_student_ids do assigned Set)

Provizorně suppressed přes eslint-disable-next-line ... -- TODO(set-state-in-effect): ... s konkrétním návrhem řešení v komentáři. CI tak projde, ale debt zůstává viditelný v kódu. Action item pro příští process-analyst retro: zařadit refactor classbook setState patternů (derive v render přes useMemo, nebo key prop na Dialogu).

Required GitHub secrets před mergem PR

Aby CI passla na CI runneru, repo musí mít nastavené 2 GitHub Actions secrets: - NEXT_PUBLIC_SUPABASE_URL — z .mcp.json (project iwcisgvhwdzztrfdrpkl) - NEXT_PUBLIC_SUPABASE_ANON_KEY — z web/.env.local

Anon key je public-safe (klient ho stejně inlinuje do bundle), takže není reálný secret, ale GitHub Actions secrets je správné místo.

Pozorování (mimo scope, do dalšího retra)

  • Next 16 ukazuje warning: middleware file convention je deprecated, má se přejmenovat na proxy. Nelámaná funkčnost, ale upgrade dluh.
  • ESLint má dalších 9 warnings (unused vars, missing useMemo deps) — solo dev může postupně vyčistit.

Další kroky

  1. PO: nastavit oba GitHub secrets v repo settings (Settings → Secrets and variables → Actions).
  2. PO: review + merge PR.
  3. Iterace 3 plánu: .github/CODEOWNERS, PR template, branch protection na main (CI + approval + security review jako merge gate).

2026-05-11 — Bootstrap cleanup (po setupu autonomního týmu)

Kontext: Nasazen autonomní tým (AGENTS.md, 5 subagents + 5 slash commands). Spuštěn /retro bootstrap → identifikováno 16 položek (viz RETRO/2026-05-11-bootstrap.md). PO schválil 8 položek.

Provedené úklidové operace

N1 — legacy artefakty z rootu: - Smazáno: extract_pdf.py, main.py, kosmo-dokumentace.zip, .venv/, .python-version - Ponecháno: pyproject.toml, uv.lock — používá je MkDocs build (deploy na docs.sofie.education přes Cloudflare) - README.md přepsán na realistický Next.js + MkDocs stack

C1 — Dify legacy: - Smazán dify/ (root) a infra/dify/nginx/ — chatflow nikdy aktivně nenasazený

C4 — Azure SSO guide: - Smazán docs/GUIDE_AZURE_APP_REGISTRATION.md — operational runbook, ne projektová dokumentace

N4 — adresářová konzistence: - web/src/components/StudentClassTabs.tsxweb/src/components/students/StudentClassTabs.tsx - Import v web/src/app/(app)/zaci/page.tsx aktualizován - Root components/ zůstává jen pro globální komponenty (AppHeader.tsx)

N5 — squash migrací: - 3 migrace zkombinovány do 20260422000001_init.sql: - default_teacher_id uuid references profiles(id) přidán inline do schedule_slots + index - attendance_done_at timestamptz přidán inline do classbook_entries - Smazány 20260423000001_attendance_done.sql a 20260423000002_default_teacher.sql - Akce pro PO: spustit supabase db reset před dalším deployem, ověřit RLS

N7 — pnpm workspace: - Smazán web/pnpm-workspace.yaml — repo není monorepo

Decommissioning Listmonk + n8n (související s RW1, RW4): - Sofie reformulace n8n workflow se neaktivně používá → odložen rewrite RW1 - Smazán n8n/ adresář (workflow JSON + prompty) - Z infra/docker-compose.yml odstraněny služby n8n a listmonk - Z infra/init-databases.sql odstraněny databáze n8n a listmonk - Když přijde čas znovu zavést AI orchestraci: implementovat jako Vercel Edge Function nebo Inngest, ne znovu n8n stack - Listmonk — až přijde newsletter, použít Resend transactional + ručně HTML šablonu (150 příjemců = triviální objem, žádný důvod pro Listmonk)

N3 part 1 — backups working tree: - Smazáno infra/backups/ z working tree (7 MB SQL dumpů z března 2026) - Adresář byl už v infra/.gitignore, ale soubory tam fyzicky byly

N3 part 2 — backups z git historie: NENÍ POTŘEBA. Procesní analytik mylně tvrdil v retro reportu, že dumpy jsou commitnuté v git historii. Trojí ověření (git log --all -- infra/backups/, git log --diff-filter=A na SQL/dump pattern, kontrola .gitignore) prokázalo, že soubory byly vždy gitignored a nikdy se nedostaly do žádného commitu. Risk byl pouze na lokálním disku, který jsme vyčistili v N3 part 1. GDPR audit git historie čistý. Lesson learned pro budoucí retro reporty: process-analyst by měl ověřovat git tracking, ne jen disk presence.

Co bylo zamítnuto / odloženo

  • N2 (cost monitoring) — náklady jsou zatím minimální, odloženo do budoucna
  • N6 (konsolidace docker-compose) — Twenty se aktivně používá, BookStack připraven na budoucí RAG. Compose ponechán s Twenty + BookStack.
  • C3 (smazat MkDocs) — MkDocs běží produkčně na docs.sofie.education (Cloudflare). Ponechán.
  • C5 (smazat curriculum/) — ponecháno

Další kroky

  1. Spustit /curate-docs bootstrap — sladit docs s realitou po cleanupu, navrhnout reorganizaci adresáře. Bude potřeba přepsat zmínky o n8n/Listmonk v ARCHITECTURE.md, INTEGRATIONS.md, MVP.md, SOFIE.md, CLAUDE.md "Klíčová rozhodnutí" tabulce, DEPLOYMENT.md, index.md, BACKLOG.md, REQUIREMENTS.md, RFC-knowledge-graph.md.
  2. Spustit supabase db reset — ověřit squashnutou migraci.
  3. Iterace 2 plánu setupu: Playwright e2e + GitHub Actions web-ci.

Aktuální stav frontendu (po 2026-05-11)

Routy a komponenty

web/src/app/
├── layout.tsx              ← Root layout
├── login/                  ← Magic link přihlášení
├── auth/callback/          ← OAuth callback
├── pending/                ← Čekající na schválení
└── (app)/                  ← Authenticated app shell
    ├── layout.tsx          ← App layout (AppHeader)
    ├── page.tsx            ← Třídnice — cross-class day view (výchozí)
    ├── classbook-actions.ts← Server actions: docházka, témata
    ├── plan/page.tsx       ← Týdenní plán (WeekView)
    └── zaci/
        ├── page.tsx        ← Seznam žáků (přehled kontaktů)
        └── [id]/page.tsx   ← Detail žáka

web/src/components/
├── AppHeader.tsx           ← Globální header (třída tabs, logout)
├── classbook/              ← Komponenty třídnice
│   ├── ClassbookView.tsx   ← Orchestrátor (tabs: Moje | Kentaur | Phenix)
│   ├── DayView.tsx, WeekView.tsx ← Zobrazení den/týden
│   ├── SlotCard.tsx, SlotSheet.tsx ← Slot detail + edit sheet
│   ├── PlanCell.tsx, PlanSlotSheet.tsx ← Plánování
│   ├── DayCell.tsx, DayHeader.tsx, StudentMatrix.tsx
│   ├── StudentAvatar.tsx, AddTopicDialog.tsx, ReadOnlySlotSheet.tsx
│   └── TopicAssignmentEditor.tsx
└── students/
    └── StudentClassTabs.tsx

web/src/lib/
├── schemas/attendance.ts, topics.ts, common.ts ← Zod schemas
├── classbook.ts, classbook-server.ts ← Klientská a serverová logika
├── classes.ts, auth.ts, grade-colors.ts, utils.ts
└── supabase/ ← Klientské utility

DB schema (jediná migrace: 20260422000001_init.sql)

Tabulky: profiles, classes, school_years, students, guardians, student_guardians, students_classes, class_staff, activities, schedule_slots, attendance_records, classbook_entries, slot_topics, student_slot_topics, day_overrides.

Typy: role, class_type, attendance_status, a další. RLS polícy na všech tabulkách.


2026-04-22 — Reset MVP, 4 architektonické disciplíny

Kontext: Pozice bez produkčních dat. Rozhodli jsme se odstartovat znovu s disciplinovaným základem namísto retrofitu do 7 existujících migrací a rozsáhlého frontendu.

Rozhodnutí

  1. Clean slate (DB + feature kód):
  2. Smazány všechny migrace → jedna nová 20260422000001_init.sql
  3. Smazán starý seed.sql → přepsán pro 2 třídy (Kentaur, Phenix)
  4. Smazán feature frontend: events, tasks, excuses, departures, parent pages, posts, tracking, dashboard, students/families CRUD
  5. Ponechána infrastruktura: lib/supabase/, Shadcn UI primitives, root layout, Tailwind setup

  6. MVP scope = 2 třídy, 2 features:

  7. Kentaur (4.+5.), Phenix (6.+7.) — budoucí 2. a 3. trojročí
  8. Učitel: třídnice (docházka "kdo chybí?" + téma per ročník/žák) + evidence žáků (read-only)
  9. Rodič: bez přístupu do appky, jen kontakt v evidenci
  10. Mobile-first, desktop = týdenní grid (ne roztažený mobil)

  11. 4 architektonické disciplíny (viz ARCHITECTURE.md):

  12. Endpointy přes Zod schema
  13. RLS policies v rolích, ne v user.id
  14. Auth připravený na service-to-service (dual auth middleware)
  15. Relační model, žádné JSON bloby pro hlavní entity

  16. Schema-ready pro vrstvu 2 (UI post-MVP, ale DB hotová):

  17. day_overrides — mimořádné dny (škola do lesa), per-class nebo NULL = celoškolní
  18. classbook_entries.taught_by — zastupování hodiny
  19. afterschool class_type + students_classes M:N — družina pro obě třídy
  20. attendance_records.arrived_at/left_at nullable — per-minute timestamps až budou potřeba

  21. Roadmap — pořadí:

  22. MVP (teď)
  23. Příprava na hodinu
  24. Audio debrief (voice)
  25. Mimořádné dny UI
  26. Zastupování hodiny UI
  27. Družina UI
  28. MŠMT export
  29. OpenAPI → MCP wrapper
  30. Gemini/Claude integrace

Proč teď a ne později: ~2 dny extra disciplíny dnes = 2 měsíce ušetřené později. Po produkčních datech by každá z těchto změn byla výrazně dražší.


Aktuální stav features

Kompletní přepis DB schématu — DONE (2026-04-08)

Staré migrace (5 souborů) nahrazeny 4 čistými migracemi pokrývajícími celý evidenční scope:

  • 20260408000001_core.sql — 14 enumů, profiles, classes (s class_type), school_years, students, guardians, student_guardians, students_classes, class_staff, activities
  • 20260408000002_attendance.sql — schedule_slots, attendance_records, class_daily_records, excuses, departure_permissions
  • 20260408000003_events_tasks.sql — events (s target_class_ids array), event_responses, tasks
  • 20260408000004_posts_competencies.sql — posts (interní, nikdy pro rodiče), post_activities (M:N tagging), competency_catalog, student_competencies, notifications, storage bucket

Seed.sql s reálnou strukturou školy: Orion, Perseus, Kentaur I, Kentaur II, Družina, kroužky (Šachy, Keramika, Angličtina extra), 48 žáků, 8 učitelů, 30 rodičů, rozvrh, ukázkové události/omluvenky/odchody.

Učitelský dashboard — DONE (2026-04-08)

Tři záložky: Třída / Třídnice / Přehled.

  • Třída: Grid karet žáků, klik → Sheet s PostForm a historií poznámek
  • Třídnice: Docházka (toggle přítomnost), textarea "co jsme dělali", přehled odchodů/omluvenek dne
  • Přehled: Moje úkoly (checkbox), nadcházející události, aktivní omluvenky, statistiky

Události — DONE (2026-04-08)

  • Seznam nadcházejících událostí s badges typu
  • Detail události s tasky a odpověďmi rodičů
  • Formulář pro vytvoření události s initial tasky
  • Target class_ids pro cílování na konkrétní třídy

Tasky — DONE (2026-04-08)

  • Seznam úkolů (aktivní/splněné), checkbox toggle
  • Vytvoření tasku (title, note, assignee, due_date, optional event vazba)
  • Ředitel vidí všechny tasky, učitel své

Omluvenky — DONE (2026-04-08)

  • Seznam omluvenek (aktivní/všechny filtr)
  • Formulář pro vytvoření (žák, od-do, důvod)
  • Bez approval flow — rodič zadá, učitel vidí

Departure permissions — DONE (2026-04-08)

  • Dva typy: samostatný odchod (s reminder) a vyzvednutí (jméno + telefon)
  • Trvalé a jednorázové
  • Přehled dnes/trvalé

Rodičovský pohled — DONE (2026-04-08)

  • Homepage s kartami dětí (rozvrh dne, nadcházející události, 4 akční tlačítka)
  • Formulář omluvenky
  • Formulář odchodu/vyzvednutí (podmíněný podle typu)
  • Trvalá nastavení (správa permanentních oprávnění)
  • Historie omluvenek

Přepínání kontextu učitel/rodič — DONE (2026-04-08)

  • Učitel, který je zároveň rodič, může přepínat kontext v UI
  • Detekce přes guardians.user_id vazbu
  • Cookie kosmo-context řídí aktivní kontext
  • Navigace se mění podle kontextu

Posts (poznámky k žákům) — UPDATED (2026-04-08)

  • PostForm a PostCard zachovány a integrovány do učitelského dashboardu
  • Přidán M:N tagging přes post_activities (tagy = activities/předměty)
  • RLS přepracován: poznámky vidí autor + třídní učitel + ředitel. Ostatní učitelé vidí jen své.
  • n8n workflow Sofie — Posts AI Processing (ID: 4WCjQRrBiv6e0H6I) — beze změn

Kompetence — DB READY (2026-04-08)

  • Tabulky competency_catalog + student_competencies vytvořeny
  • Status flow: not_presented → presented → practicing → mastered
  • UI zatím neimplementováno, čeká na import z Transparent Classroom

Notifikace — DB READY (2026-04-08)

  • Tabulka notifications vytvořena
  • UI (zvonek v headeru) zatím neimplementováno

Klíčová rozhodnutí

  • Kompletní přepis schématu: Žádná produkční data, přepsali jsme vše od nuly do 4 čistých migrací
  • Flat třídy s class_type: school/kindergarten/nursery/afterschool/club — žádná hierarchie
  • Activities = předměty + kroužky: Jedna tabulka, type discriminátor, slouží i jako tagy na posty
  • Departure permissions: Unified tabulka s type (independent/pickup), is_permanent, reminder
  • Poznámky interní: Posts NIKDY viditelné rodičům. RLS: autor + třídní + ředitel.
  • Rodina odvozená z guardiana: Žádná separátní tabulka families, guardian implicitně definuje rodinu
  • Přepínání rolí: Učitel-rodič detekován přes guardians.user_id, kontext v cookie
  • Události = automatická publikace: Vytvoření události = rodiče ji vidí. Žádné drafty.
  • Tasky KISS: title, note, assignee, due_date, is_completed. Žádný kanban, žádné priority.
  • Školní rok jen na vazbách: students_classes a class_staff mají school_year_id, zbytek má timestamp

Struktura frontendu

web/src/app/
├── layout.tsx              ← Hlavní layout s role-aware navigací
├── page.tsx                ← Seznam žáků (admin/evidence view)
├── login/                  ← Magic link přihlášení
├── auth/callback/          ← OAuth callback
├── pending/                ← Čekající na schválení
├── dashboard/              ← Učitelský dashboard (3 záložky)
│   ├── page.tsx
│   ├── layout.tsx
│   └── components/         ← ClassTab, Classbook, Overview, StudentCard, ...
├── students/               ← CRUD žáků (detail, edit, guardians)
├── families/               ← Přehled rodin/guardianů
├── events/                 ← Události (seznam, detail, nová)
├── tasks/                  ← Úkoly
├── excuses/                ← Omluvenky (staff view)
├── departures/             ← Odchody/vyzvedávání (staff view)
├── parent/                 ← Rodičovský pohled
│   ├── page.tsx            ← Homepage (děti, rozvrh, akce)
│   ├── layout.tsx
│   ├── excuse/new/         ← Formulář omluvenky
│   ├── departure/new/      ← Formulář odchodu/vyzvednutí
│   ├── settings/           ← Trvalá nastavení
│   └── excuses/            ← Historie omluvenek
└── actions/                ← Server actions
    ├── auth.ts, students.ts, guardians.ts, families.ts
    ├── posts.ts, dashboard.ts
    ├── events.ts, tasks.ts, excuses.ts, departures.ts
    └── parent.ts

Brainstorm gamifikace rodičů — DOCUMENTED (2026-04-15)

16 nápadů ve 4 tierech zachyceno v docs/GAMIFICATION.md. Klíčové směry: redukce friction (předpřipravená omluvenka, platební autopilot), sociální norma (třídní momentum), emoční vazba (family timeline), viditelný dopad (ušetřený čas učitele). Feed třídy zapsán jako budoucí brainstorm téma.

TODO (další kroky)

  • Build test a oprava případných chyb
  • Deploy migrace na Supabase Cloud
  • Otestovat s reálnými daty (ředitel)
  • Import kompetencí z Transparent Classroom
  • Notifikace UI (zvonek v headeru)
  • Push notifikace (Service Worker)
  • Activity tagy chips v PostForm
  • Export třídnice do PDF