# Agent-Checkliste — vor Commit / Push / Merge > **Operative Ergänzung zu [`AGENTS.md`](../AGENTS.md).** AGENTS.md hat die Regeln/DoD/Scope — > **hier** steht das praktische „bevor du pushst, mach es lokal grün" + die Footguns aus echten Vorfällen. > Die DoD-/Scope-/Ticket-Regeln aus AGENTS.md gelten zusätzlich. ## 0. Jede mutierende Session isoliert starten Aus einem vorhandenen Clone: ```bash pnpm session:start -- / cd ``` Der Befehl erstellt Branch und Geschwister-Worktree immer neu vom aktuellen `origin/main`, hydriert `.env` atomar über den kanonischen SOPS-Age-Key und führt `pnpm install --frozen-lockfile` aus. Bereits vorhandene lokale oder Remote-Branches und vorhandene Zielverzeichnisse werden verweigert. - Nicht im dirty Haupt-Workspace arbeiten. - Einen Session-Branch nicht für ein neues Ticket oder einen Folge-Fix wiederverwenden. - Rein lesende Diagnose ist ausgenommen; vor der ersten Dateiänderung muss ein Session-Worktree stehen. - Scheitert SOPS oder die Installation, muss der Start ohne leere `.env` und ohne halben Worktree zurückrollen. ## 0.5 Atomare Checkpoints während der Umsetzung Nicht bis zum Ende des Auftrags mit dem Committen warten. Nach jeder abgeschlossenen, separat revertierbaren Änderung: 1. `git status --short` prüfen und nur die Dateien des aktuellen fachlichen Checkpoints stagen. 2. `git diff --cached --name-only` und `git diff --cached --stat` lesen. 3. Bei mindestens 25 Dateien oder 800 geänderten Zeilen ohne reine Generierung, Migration oder Massendeletion den Commit vor dem Fortfahren fachlich aufteilen. 4. `git diff --cached --check`, fokussierte Tests und den Typecheck der betroffenen Pakete ausführen. 5. Den Checkpoint sofort committen, bevor ein unabhängiger Bug, Refactor, Tooling-/Test-Fix oder der nächste Plan-/DoD-Punkt begonnen wird. Tests, Typen, Übersetzungen, Redirects und generierte Artefakte bleiben bei der Änderung, die sie erforderlich macht. Änderungen eines anderen Checkpoints bleiben unstaged. `git add -A` ist nur zulässig, wenn `git status --short` nachweislich genau einen Checkpoint enthält. ## 1. Vor JEDEM Push: lokal grün machen CI läuft auf node1 mit begrenzten Slots (~7 Min/Lauf). Fang Fehler **lokal** ab, nicht im CI. ```bash pnpm typecheck # tsc (@hivegrid/web). Andere Pakete: pnpm --filter typecheck pnpm lint # eslint --max-warnings=0 ← WARNINGS FAILEN CI, nicht ignorieren pnpm test # Core-Tests; bei breiteren Änderungen die betroffenen Pakete mit-testen ``` **Merksätze:** - **`esbuild`/`vitest` grün ≠ typecheck grün.** esbuild transpiliert ohne Typprüfung; `tsc` prüft Typen. Beide laufen lassen. - **Lint-Warnings = CI-rot.** `--max-warnings=0` ist hart. Kein `// eslint-disable` ohne Grund (wenn nötig: file-level + begründet). - **Coverage-Gate** (falls dein Modul ein Coverage-Target in `scripts/coverage-targets.json` hat): `pnpm run verify:test-coverage` — läuft vom **Repo-Root** (jsdom-Config!), siehe Footgun §3. ## 2. Passende `verify:*`-Checks vor Push Je nach Änderung die relevanten Validatoren laufen — CI bricht sonst: | Geändert | Check(s) | |---|---| | `.gitea/workflows/*.yml` | `pnpm run verify:gitea-ci-workflow` · `verify:deploy-workflow` | | **Neues `packages/`** | `pnpm run verify:docker-baseline` ← **Dockerfile deps-Target braucht `COPY packages//package.json`** (sonst Deploy rot, §3) | | **Neues Prisma-Modell mit `tenantId`** | `TENANT_SCOPED_MODELS` in `packages/cli/src/commands/tenant/models.ts` ergänzen (Eltern vor Cascade-Kindern) + RLS-Policy in `prisma/rls/-isolation.sql`. Test: `packages/cli/.../tenant/models.test.ts` (§3) | | **Neue Default-Permission** | In **alle vier** Registries: `packages/db/.../permissions-seed.server.ts` (Seed + Rollen-Grant) · `apps/web/app/application/dtos/shared/DefaultPermissions.ts` (Enum) · `apps/web/app/components/core/roles/roleDisplay.ts` (Scope- + Action-Map) · `translations.json` unter `models.permission.defaultPermissions.{scopes,actions}` (de **und** en). Tests: `rolesAndPermissionsService.role-matrix` + `roleDisplay` (§3) | | **`prisma/schema/**` geändert** | **Beide** Gates, nicht nur das erste: `pnpm run verify:migrations-parity` ← Schema ohne Merge-Migration = CI rot (AD-21-Gate; braucht Docker) · `HIVEGRID_RLS_REQUIRE_MIGRATION_CHAIN_PARITY=1 pnpm run verify:rls-live` ← spielt die Kette als **Nicht-Superuser** durch. Auf dem Branch mit `db push` arbeiten ist ok, aber **vor dem Merge** muss die Migration existieren | | **FK auf eine Tabelle mit FORCE RLS** | Der Constraint wird mit einem internen Join über die referenzierte Tabelle validiert, und FORCE gilt auch für den Owner → `ALTER TABLE "" NO FORCE ROW LEVEL SECURITY;` … FK … `FORCE` wieder an (Policies bleiben ENABLED, kein DML im Fenster). **Eine leere referenzierende Tabelle hilft nicht** — die Anweisung wird abgelehnt, bevor eine Zeile gelesen wird. Ein lokaler Replay als Superuser sieht das nicht; nur `verify:rls-live` und die CI-Shadow-DB fangen es | | Dockerfile / Runtime | `verify:docker-baseline` · `verify:docker-non-root` | | UI-Texte | `pnpm run verify:i18n` (keine hartkodierten Strings) | | Allgemein | `verify:ci-baseline` · `verify:source-health` | ## 3. Footguns aus echten Vorfällen - **Neues Workspace-Paket → Dockerfile-COPY-Zeile.** Jedes `packages/` braucht `COPY packages//package.json packages//package.json` im Dockerfile deps-Target (alphabetisch, vor `pnpm install`). `verify:docker-baseline` prüft das. Vergessen = **Deploy bricht erst NACH dem Merge** im Preflight (2026-06-28: `packages/integrations`, Hotfix PR #8). Der Docker-Build selbst + ci.yml tolerierten es früher — jetzt prüft ci.yml es mit. - **Neues `tenantId`-Modell lebt in mehreren Registries.** Modell + RLS-SQL reicht NICHT: `TENANT_SCOPED_MODELS` (Backup/Restore, `packages/cli/.../tenant/models.ts`) muss es kennen, sonst `tenant/models.test.ts` rot. Eltern **vor** Cascade-Kindern listen (Restore-Reihenfolge). (AK-P17b, CI-Fund 2026-06-28) - **Default-Permission lebt in 4 Registries.** Nur in den Seed schreiben reicht NICHT (siehe §2): `role-matrix`-Test verlangt den Eintrag im `DefaultPermissions`-Enum, `roleDisplay`-Test verlangt Scope- **und** Action-Mapping in `roleDisplay.ts` **plus** Übersetzungen unter `models.permission.defaultPermissions.{scopes,actions}` (de+en). Bei mehrstufigem Scope **flache** Keys (`hr.leave` → `hrLeave`), sonst Pfad-Kollision mit dem `hr`-String-Leaf. (AK-P17b) - **Kein `"…"` (doppelte Anführungszeichen) in Kommentaren im `defaultPermissionSeeds`-Array.** Der `roleDisplay`-Test **regex-extrahiert jedes doppelt-gequotete Literal im Array** als Permission-Namen — ein zitiertes Wort im Kommentar wird zur Phantom-Permission und bricht den Test (`… is not valid JSON`). Im Kommentar einfache Anführungszeichen / Backticks nutzen. (AK-P17b) - **Coverage-Gate läuft vom Repo-Root (jsdom).** Tests, die Node-Kontext brauchen (`fs`, `process`), mit `// @vitest-environment node` pinnen. **Kein `process.chdir`** in parallelen Tests (race). `vi.mock` **leakt** zwischen Files in shared Workers → Mocks pro File isolieren / `vi.restoreAllMocks`. - **RLS ist lokal AUS und in Staging/Prod AN.** Ein grüner lokaler Lauf beweist **nichts** über RLS. Greifst du in einer Route/einem Service direkt auf `db.` zu, binde den Kontext (`runWithRlsContext` / `withTenantRLS`) — sonst liefert die Query dort **null Zeilen**, ohne Fehler und ohne Log (2026-07-14: eine neue Route hätte in Prod jedes Profilbild als 404 ausgeliefert). Db-Mocks, die auf jede Query antworten, verstecken genau das. Details: `AGENTS.md` §Row-Level-Security. - **Kein Laufzeit-Flag mit `SEED_`-Präfix.** Der Deploy-Vertrag (`assert-runtime-db-env`) weist jeden `SEED_*`-Schlüssel auf Runtime-Ressourcen ab. Ein Feature-Schalter, der zufällig nach Seed klingt, wird beim Deploy stillschweigend entfernt — genau daran sind die Staging-Demo-Logins gestorben (2026-07-14). - **`.server.ts`-Re-Export ist verboten** (RR7-Client-Build bricht). Stattdessen Component-Extraktion. - **pre-push-Hook blockt?** Erst die Checks **manuell** laufen + Ursache fixen — nicht blind `git push --no-verify`. `--no-verify` nur, wenn der Hook-Fehler nachweislich irrelevant ist (z.B. Hook-Timeout, kein echter Lint-/Typ-Fehler). ## 4. Branch / PR / Merge - **Gitea-Identität fail-closed prüfen:** `git config --local hivegrid.giteaUser` muss den persönlichen Dev-Login dieses Clones enthalten. Die effektive Git-/API-Credential muss vor jedem Push und jedem Gitea-Write via `GET /api/v1/user` exakt diesen Login + `active=true` ergeben. `gitea-admin`, `Sudo` und andere Impersonation sind für Routinearbeit verboten. Nur CI-/Deploy-Bots sind als explizite Servicekonto-Ausnahme zulässig. - **Nie direkt auf `main` pushen** → Branch + PR + normaler Merge-Commit. **Squash ist verboten.** - **Commit-Historie erhalten:** Vor dem Merge erwartete PR-Head-SHA prüfen und Gitea ausschließlich mit der normalen Merge-Strategie (`Do=merge`, nie `Do=squash`) aufrufen. Nach dem Merge muss `git merge-base --is-ancestor origin/main` erfolgreich sein; die einzelnen Feature-Commits behalten ihre ursprünglichen SHAs. - **Versehentlichen Squash append-only reparieren:** Geteiltes `main` niemals umschreiben oder force-pushen. Stattdessen einen bytegleichen History-Repair-PR erstellen, der den ursprünglichen Feature-Head per normalem Merge-Commit anbindet, CI vollständig abwarten und die erhaltene Ancestry nachweisen. - **Session nach normalem Merge aufräumen:** Sobald der PR per normalem Merge-Commit in `main` liegt: `pnpm session:finish -- `. Der Helfer prüft dirty State, aktuelle Main-Ancestry, den Merge-Commit, identische lokale/Remote-Heads, geschlossene PRs und persönliche Gitea-Identität. Erst danach löscht er Remote-Branch, Worktree und lokalen Branch. Bei Squash, Fast-Forward, offenem PR, weitergelaufenem Branch oder lokalen Änderungen stoppt er. Nicht durch `rm -rf` oder `git branch -D` umgehen. - **Parallel-Schema (AD-21):** Modul = eigene `prisma/schema/.prisma`; am Branch `prisma db push`, **Migration erst beim Merge** (forward-only + Inverse-SQL als Kommentar, aus dem Nichts reproduzierbar — `DO $$ … IF [NOT] EXISTS … $$`-Guards). - **Deploy-Path-Filter:** test-/doc-/workflow-only-Merges (`**/*.test.*`, `docs/**`, `.planning/**`, `.gitea/workflows/**`, `*.md`) skippen den Staging-Deploy automatisch. Code-Änderungen triggern ihn. - **Abhängige nicht brechen:** bei Contract-/`core.prisma`-/Querschnitt-Änderungen `blocked-by` UND `blocks` lesen, Konsumenten nachziehen, Auswirkung dokumentieren. ## 5. Secrets & Ticket-Abschluss - **Secrets** nie ins Repo/Chat/CI-Log. Per-User-Token in `~/.cli-tokens/` (chmod 600); geteilte Dev-`.env` via `pnpm env:pull` (SOPS). - **Strikt im Ticket-Scope.** Verbesserungen nur als **„💡 Vorschlag (außerhalb Ticket-Scope)"** ausweisen, nie still einbauen. Fortschritt als **% der DoD** melden; Done erst bei 100 %. - **Abschluss-Reihenfolge:** Umsetzungs-Notiz (Datum + Proof) in der Ticket-Doc → Plane-Kommentar (1. Person, kein AI-Sprech, keine Em-Dashes) → Ticket auf Done.