Files
paliad/docs/audit-polish-2-2026-04-29.md
m 80fdab0963 docs(t-paliad-067): polish audit triage 2 — classify F-01..F-50, propose 3 PRs
Re-verified every BATCH finding from docs/audit-polish-2026-04-27.md
against the post-PR-B/D/E + palette + firm-name codebase.

- 18 OBSOLETE (already shipped via t-paliad-060/061/062/063/064/065).
- 26 KEEP — bundled into PR-1 (i18n leak sweep + activity log), PR-2
  (visual residue + small per-page polish), PR-3 (tab/chip/notes-hint
  consistency).
- 1 RESCOPED (F-20 colour fixed by palette sweep, structural rule
  consolidation still pending).
- 7 DEFER — design-call or redesign-class items (F-23, F-25, F-32, F-38,
  F-40, F-48, F-49).

Top-5 user-visible items ranked: F-07 dashboard activity narrative, F-15
red archive button, F-04 raw i18n key on /deadlines/new, F-12 AKTE column
header (rename residue), F-13 appointments AKTE cell collision.

DESIGN-READY GATE — head reviews before any coder shift.
2026-04-29 13:58:51 +02:00

260 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Paliad Polish Audit — Triage 2 — 2026-04-29
**Source audit:** `docs/audit-polish-2026-04-27.md` (50 findings, 41 screenshots).
**Method:** for every BATCH-tagged finding, re-verified against the current
codebase (post-PRs B/D/E + the brand palette sweep + firm-name sweep).
**Goal:** mark each finding KEEP / OBSOLETE / RESCOPED / DEFER, group the keeps
into 23 ship-ready PRs, and rank what m would notice first on Monday morning.
**What already shipped since the original audit:**
- t-paliad-060 (PR-B): F-05, F-06 — `lang` attr on date/time inputs.
- t-paliad-061 (PR-D): F-11, F-17, F-18, F-19, F-26, F-44, F-45.
- t-paliad-062 (PR-E): F-02, F-03, F-08, F-09.
- t-paliad-063 (palette): F-14, F-30, F-31 (explicitly superseded per commit).
- t-paliad-064 (reminder redesign): the new settings UI uses inline-flex
`caldav-toggle-label` blocks → incidentally fixes F-22.
- t-paliad-065 (firm-name): F-01.
- Pre-audit (t-paliad-049 modal/breadcrumb polish): /projects/new already has
a Cancel button (`btn-cancel`) → F-34 OBSOLETE.
---
## Verification table
| ID | Status | Notes |
|---|---|---|
| F-01 | OBSOLETE | Stripped by t-paliad-065 firm sweep. Curl of `/` and `/login` shows only "Paliad" + "HLC". |
| F-02 | OBSOLETE | t-paliad-062 (search input padding). |
| F-03 | OBSOLETE | t-paliad-062 (migration 024 column rename). |
| F-04 | KEEP | `frontend/src/client/deadlines-new.ts:45` still references `fristen.field.project.choose`; `i18n.ts` only has `fristen.field.akte.choose` → renders raw key. Either rename in deadlines-new.ts to `fristen.field.akte.choose`, or add the new key. |
| F-05 | OBSOLETE | t-paliad-060. |
| F-06 | OBSOLETE | t-paliad-060. |
| F-07 | KEEP | `internal/services/project_service.go:625` emits `project_type_changed` with English title "Project type changed"; description embeds raw English values (`case → litigation`). Dashboard activity widget renders these verbatim. Plus mixed-language nouns ("Note zu deadline hinzugefügt"). Same class as the t-paliad-037 sweep but for newer events. |
| F-08 | OBSOLETE | t-paliad-062. |
| F-09 | OBSOLETE | t-paliad-062. |
| F-10 | KEEP | The `inf.rejoin` raw slug renders because client-side rule lookup falls through when no matching rule label exists. Need a missing-rule label fallback (display "—" or a humanized variant) and/or i18n key for known catalog slugs. |
| F-11 | OBSOLETE | t-paliad-061. |
| F-12 | KEEP | `frontend/src/deadlines.tsx:101` and `frontend/src/appointments.tsx:101` still ship `<th data-i18n="fristen.col.akte">Akte</th>` / `termine.col.akte`; i18n.ts L541/1043 still maps to "Akte". PR-D fixed the *filter* dropdown; the *column header* was deliberately left for PR-A which never ran. |
| F-13 | KEEP | `client/appointments.ts:153` and `client/deadlines.ts:197` render `<span class="frist-project-title">` but `global.css:4716` only styles `.frist-akte-title { display: block; }` — class-name mismatch from the rename → ref + title render inline → "L-2026-001Siemens AG ./." collision. Trivial: rename the CSS or the markup. |
| F-14 | OBSOLETE | t-paliad-063 (palette sweep). |
| F-15 | KEEP | `projects-detail.tsx:334` still uses `className="btn-danger"` (red `#dc2626`) for the "Projekt archivieren" button. The destructive-modal confirm action also uses `btn-danger`, which is fine — it's the entry-point button on the working surface that screams. |
| F-16 | KEEP | `global.css:4089-4093` still ships saturated random colors per type chip (`akten-type-client` lavender, `akten-type-litigation` pink-red, `akten-type-patent` cyan, `akten-type-case` salmon, `akten-type-project` neutral-green). Same classes drive `/projects` and `/admin/team`. |
| F-17 | OBSOLETE | t-paliad-061. |
| F-18 | OBSOLETE | t-paliad-061. |
| F-19 | OBSOLETE | t-paliad-061. |
| F-20 | RESCOPED | Palette sweep harmonized the *colour* (every active tab now points at `--hlc-lime`), but the structural inconsistency remains: `.akten-tab.active` uses `font-weight: 600` + midnight text, while `.login-tab.active` and `.gebuehren-tab.active` use accent-coloured text. Drop to one rule. |
| F-21 | KEEP | `internal/services/deadline_service.go:306` still inserts events with title `"Deadline updated"` (English, in DE narrative on /projects/{id}/history). Same fix lane as F-07. |
| F-22 | OBSOLETE | t-paliad-064 PR-3/4 introduced `caldav-toggle-label` (`display: inline-flex`, `gap: 0.5rem`) for every checkbox row — labels and checkboxes are now adjacent. |
| F-23 | DEFER | Hiding STATUS when single-valued is a design call (some users like the redundancy as a trust signal). Punt to a later "table density" pass. |
| F-24 | KEEP | Mobile filter row still stacks awkwardly. Single-page CSS fix on `/projects` (and adjacent `/deadlines`/`/appointments`). |
| F-25 | DEFER | Card-layout-on-mobile is a design refactor, not a polish edit. Spans `/projects`, `/deadlines`, `/appointments`, `/admin/team`. Out of scope for polish-2; flag as a standalone t-task. |
| F-26 | OBSOLETE | t-paliad-061. |
| F-27 | KEEP | `client/projects-detail.ts:1143` always renders the breadcrumb; no path-depth check. One conditional in `renderBreadcrumb()`. |
| F-28 | KEEP | Cell empty-placeholder is split: `/admin/team` and `/projects/{id}/deadlines` use "—"; `/projects` (REFERENZ, CLIENTMATTER) and `/appointments` (ORT) render blank. Pick one and grep for empty-cell renders. |
| F-29 | KEEP | TSX has a real `<a href="/checklists">` but `i18n.ts` strings (L949/2190) ship plain text "…unter Checklisten angelegt." On runtime translation, the anchor disappears. Fix: store the link in i18n with a placeholder (`{link}`) and substitute at render, or render two strings and inject the anchor. |
| F-30 | OBSOLETE | t-paliad-063 sidebar reskin. |
| F-31 | OBSOLETE | t-paliad-063 (button restyle). |
| F-32 | DEFER | The agenda was redesigned (day-bucket section headings now exist). The per-card urgency pill is still rendered, but it now carries information *only* when the urgency disagrees with the bucket (e.g. an "Überfällig" item appearing under HEUTE). Keeping it is defensible. Mark as design-call, not polish. |
| F-33 | KEEP | One `title=` attribute per project-ref render in `dashboard.ts` and `agenda.ts`. Trivial. |
| F-34 | OBSOLETE | `projects-new.tsx:46` already ships `<a className="btn-cancel" data-i18n="projekte.cancel">Abbrechen</a>`. |
| F-35 | KEEP | `projects.tsx:34` + `i18n.ts:844` still read "Mandanten, Streitsachen, Patente und Fälle …". Actual taxonomy is Mandant / Streitsache / Patent / Verfahren / Projekt. Replace "Fälle" → "Verfahren" (and possibly mention "Projekte"). |
| F-36 | KEEP | `ProjectFormFields.tsx:19` still ships `<option value="client">Mandant</option>` first → implicit default. Switch to a "Bitte wählen…" placeholder option, or default to `case`. |
| F-37 | KEEP | `client/notes.ts` textarea has no Strg+Enter / Cmd+Enter hint, no character counter, no markdown hint. Add a small footer line. |
| F-38 | DEFER | Bottom-nav badge semantics is a design decision — needs to match the agenda urgency definition. Tackle alongside any future agenda-redesign task. |
| F-39 | KEEP | Tree view shows "11" while flat shows "11 / 11"; pick one format. One client edit. |
| F-40 | DEFER | Glossary chip language ("Litigation" / "Prosecution" vs "Allgemein") is a product decision, not a polish fix. m to call. |
| F-41 | OBSOLETE | Was tagged OK in the audit. |
| F-42 | KEEP | Same fix as F-13 (`frist-project-title` CSS class) plus a monospace ref pill style + ellipsis on title. Bundle with F-13. |
| F-43 | KEEP | Empty state on `/projects/{id}/parties` is a single line — add an empty-state CTA card (matches the pattern used elsewhere). |
| F-44 | OBSOLETE | t-paliad-061. |
| F-45 | OBSOLETE | t-paliad-061. |
| F-46 | KEEP | `i18n.ts:1906` still maps `dashboard.greeting.prefix` to "Good day". Change to "Hello" (or "Hi"). One-line. |
| F-47 | KEEP | `/settings` profile placeholder "z.B. Associate, Partner, PA" still mixed EN/DE in i18n. One-line. |
| F-48 | DEFER | `/projects/{id}/sub-projects` would 404, but the canonical `/children` URL works and tabs auto-resolve to it. Aliasing is low-value; flag the canonical path in docs instead. |
| F-49 | DEFER | Tagged DEFER in original audit. |
| F-50 | KEEP | One CSS rule on `<main>` (or `body`) — bottom-padding equal to bottom-nav height on `<768px`. |
**Summary:** 18 OBSOLETE (already shipped), 26 KEEP, 1 RESCOPED (F-20), 7 DEFER (F-23, F-25, F-32, F-38, F-40, F-48, F-49). The KEEP set is the polish-2 backlog.
---
## PR plan — 3 bundles
### PR-1 — i18n leak sweep + activity log narrative 🟡
Single concern: text rendered to a German narrative that's still English or
raw-keyed. Ship as one PR — they're touched in adjacent files and the
reviewer can verify them together by walking the dashboard and the activity
tab.
**Includes:** F-04, F-07, F-10, F-12, F-21, F-29, F-35, F-46.
- F-04 (deadlines-new picker key) — i18n key add or rename. *Pure i18n.ts.*
- F-07 (dashboard activity event types + narrative nouns) — needs three
edits: (a) Go service-side, switch event titles from "Project type changed"
/ "Note added to deadline" to neutral identifiers; (b) i18n.ts add
`dashboard.action.project_type_changed`, `…note_added`, etc.; (c) frontend
dashboard renderer translates the event_type and the dynamic values
(`case` → t("projekte.type.case")) before joining into the narrative.
*This is the only Go-side change in the bundle.*
- F-10 (raw `inf.rejoin`) — frontend rule-label lookup falls back to "—"
when no label exists; can be done in `client/deadlines.ts` only. Optional
follow-up: backfill `fristen.rule.<slug>` keys.
- F-12 (AKTE column header) — flip `fristen.col.akte` and `termine.col.akte`
to "Projekt" / "Matter" (DE/EN), plus the `data-i18n` attribute label.
- F-21 ("Deadline updated" in Verlauf) — same shape as F-07; one Go edit
(`deadline_service.go:306` title → neutral identifier) plus i18n key add.
- F-29 (checklists empty-state link) — store the empty-state copy as two
i18n strings or a `{link}` placeholder; render with a real `<a>`.
- F-35 (subtitle taxonomy) — flip "Fälle" → "Verfahren" in
`projekte.subtitle` (DE+EN) and the SSR fallback in `projects.tsx:34`.
- F-46 (Good day) — one-line i18n change.
**Risk:** medium. Go-side event-emission edits need a smoke test of the
activity feed (dashboard widget + project Verlauf tab) post-deploy. Existing
events in the DB carry the *old* English titles — the renderer should
translate the event_type, not the stored title (so historical rows benefit
too). Worth calling out explicitly in the PR description.
### PR-2 — visual residue + small per-page polish 🟢
Single concern: small CSS/markup edits, mostly self-contained per page.
**Includes:** F-13, F-15, F-24, F-27, F-28, F-33, F-36, F-39, F-42, F-43,
F-47, F-50.
- F-13 (appointments AKTE collision) — rename CSS rule
`.frist-akte-title``.frist-project-title` (or add the new selector).
Same rule fixes F-42 partially.
- F-15 (red archive button) — change `className="btn-danger"`
`btn-secondary` (or introduce `btn-archive` with neutral/outline styling).
Modal confirm button stays red.
- F-24 (mobile filter row wrapping) — `/projects` filter container CSS:
`flex-direction: column` + `align-items: stretch` at `<480px`; each
filter as its own labelled block.
- F-27 (single-child breadcrumb) — `renderBreadcrumb` early-return when
the chain has length ≤ 1.
- F-28 (placeholder consistency) — grep cell renderers; render "—" for
empty REFERENZ, CLIENTMATTER, ORT, REGEL, WEITERE STANDORTE.
- F-33 (truncated ref tooltip) — `title=` attr on
`.dashboard-upcoming-project-ref` and `.agenda-item-project`.
- F-36 (Mandant default) — add a `<option value="" disabled selected>` /
`Bitte wählen…` first row in `ProjectFormFields.tsx:18`.
- F-39 (search counter format) — match flat ("11 / 11") to tree view, or
the other way, by editing the tree-view counter.
- F-42 (deadlines AKTE wrapping) — same CSS rename as F-13 + `text-overflow:
ellipsis` on `.frist-project-title` with a `title=` for the full text.
- F-43 (parties empty state) — add an empty-state CTA card with a "Partei
hinzufügen" call.
- F-47 (settings placeholder mixed) — pick all-DE or all-EN; one i18n edit.
- F-50 (mobile bottom-nav overlap) — `<main>` `padding-bottom: var(--bottom-nav-h)`
at `<768px`.
**Risk:** low. Each change is local; the only cross-cutting bit is the F-13
+ F-42 CSS rename, but the class is referenced in exactly two TS files.
### PR-3 — visual consistency: tabs + chips + Notiz hint 🟡
Single concern: harmonization that touches several pages with one change
each.
**Includes:** F-16, F-20, F-37.
- F-16 (type pill saturated colors) — neutralize to a single chip background
with the type icon for differentiation; reserve color-as-signal for the
*Mandant* root (or for `/admin/team` STANDORT). Touches `global.css:4089-4093`
+ `admin-team.tsx` chip render.
- F-20 (tab styling) — collapse the three active-tab rules
(`.akten-tab.active`, `.login-tab.active`, `.gebuehren-tab.active`) to one
shared style. Could simply make the two minority rules `@extend` the
canonical lime-underline + midnight-text + 600-weight pattern.
- F-37 (Notiz textarea hint) — small footer line under the textarea with
"Strg+Enter zum Speichern" (DE) / "Cmd+Enter to save" (EN).
**Risk:** medium. Tab rule consolidation is the riskiest edit in the
backlog — it touches every `.login-tab` and `.gebuehren-tab` consumer
(login page + Gebührentabellen page). Verify both visually post-edit.
The chip change is visually larger but lower risk because the saturated
colors carry no behaviour.
---
## Top 5 — what m notices first on Monday morning
1. **F-07 — Dashboard activity log English event types.** The activity
widget is on the landing page, every login. Reading "Test Tester
project_type_changed" or "Note zu deadline hinzugefügt" makes the app
feel half-baked in 30 seconds. Sibling F-21 lives on the project Verlauf
tab (next-most-read). High visibility, medium effort.
2. **F-15 — "Projekt archivieren" red button.** Wrong affordance changes
user behaviour: real lawyers will hesitate to archive routine matters
because "red = scary". Trivial fix, biggest behaviour delta.
3. **F-04 — Raw `fristen.field.project.choose` key on /deadlines/new.**
Visible, plainly broken text in a primary form. One-line fix.
4. **F-12 — AKTE column header on /deadlines and /appointments.** The
filter dropdown was renamed to "Projekt" in PR-D; the *column header* still
says "Akte" in the same row. Side-by-side inconsistency screams "rename
half-done". Trivial.
5. **F-13 — `L-2026-001Siemens AG ./.` collision on /appointments AKTE
cell.** Looks like a data-corruption bug at first glance. Caused by a
single CSS class rename that was missed; one-line fix.
(All five fit in PR-1 + PR-2 above. Recommend shipping those two first.)
### Honourable mentions (#610)
6. F-46 (Good day → Hello) — one-line warmth fix on EN dashboard.
7. F-29 (empty-state link not real) — feels broken when you click the word
and nothing happens.
8. F-16 (type pill saturated colors) — calmer chip palette makes /projects
feel less alarming.
9. F-35 (subtitle taxonomy "Fälle") — small but visible on /projects intro.
10. F-50 (mobile bottom-nav overlap on dashboard) — only mobile, but
immediately visible to anyone on a phone.
---
## Defer list
Findings where polish-2 isn't the right scope — either they need a design
call, span a redesign-class change, or carry low value-per-effort.
- **F-23** — STATUS column noise. Hiding when single-valued is a usability
call (some users like the redundancy). Defer to a "table density" pass.
- **F-25** — Mobile tables → card layout. Genuine redesign across four
pages. Should be its own t-task with screenshots and an alignment
pass on the mobile pattern. Out of scope for "polish".
- **F-32** — Agenda redundant urgency pill. After the day-bucket redesign,
the pill *can* still differ from the bucket (e.g. an overdue item under
HEUTE). Keeping it is defensible; design call before changing.
- **F-38** — Bottom-nav agenda badge semantics. Needs to match the agenda
redesign decision; tackle there.
- **F-40** — Glossary chip language (EN/DE mix). Product decision (m).
- **F-48** — `/sub-projects` URL alias. The canonical `/children` works;
guessable-URL-alias is low value. Document the canonical path instead.
- **F-49** Already DEFER in original audit (meta-circular changelog
entry).
---
## Recommendation summary
- Ship **PR-1** (i18n leak sweep + activity log narrative) first biggest
user-visible delta, contains 3 of the top-5.
- Ship **PR-2** (small visual residue) right after low-risk, high
per-edit value, contains the other 2 top-5 items + F-46 / F-50.
- **PR-3** (tab + chip consistency) is worthwhile but riskier; OK to land
after PR-1/PR-2 stabilize. Leave for later in the week or punt to a
separate t-task if velocity is constrained.
- **DEFER list** to a later "design-pass" or "mobile-pass" task; do not
bundle them with these PRs.
## Acceptance
- [x] Every BATCH finding (F-01..F-50) classified KEEP / OBSOLETE /
RESCOPED / DEFER against current code state.
- [x] Keeps grouped into 3 PR bundles with effort + risk + finding IDs.
- [x] Top 5 ranked with rationale.
- [x] Defer list with reason per item.
- [ ] Head greenlights individual PRs before any coder shift.