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

17 KiB
Raw Permalink Blame History

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)

  1. F-46 (Good day → Hello) — one-line warmth fix on EN dashboard.
  2. F-29 (empty-state link not real) — feels broken when you click the word and nothing happens.
  3. F-16 (type pill saturated colors) — calmer chip palette makes /projects feel less alarming.
  4. F-35 (subtitle taxonomy "Fälle") — small but visible on /projects intro.
  5. 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

  • Every BATCH finding (F-01..F-50) classified KEEP / OBSOLETE / RESCOPED / DEFER against current code state.
  • Keeps grouped into 3 PR bundles with effort + risk + finding IDs.
  • Top 5 ranked with rationale.
  • Defer list with reason per item.
  • Head greenlights individual PRs before any coder shift.