docs(quick-260916-j4f): Plan — Nachträge: Kalender-Tooltip bricht lange Titel um (min-w-0 break-words, Breite/Klemmung aus TOOLTIP_WIDTH_PX), Notiz-Widget folgt dem Tessera-Farbmodus (useTheme + mounted-Guard wie changelog-view), CHANGELOG.md auf Stichpunkte gestrafft (Soll-Vorlage übernehmen, dann löschen)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+207
@@ -0,0 +1,207 @@
|
||||
---
|
||||
phase: quick-260916-j4f
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
autonomous: true
|
||||
requirements: [QUICK-260916-J4F]
|
||||
|
||||
files_modified:
|
||||
- apps/web/src/components/dashboard/widgets/calendar-widget.tsx
|
||||
- apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx
|
||||
- apps/web/src/components/dashboard/widgets/note-widget.tsx
|
||||
- apps/web/src/components/dashboard/widgets/note-widget.test.tsx
|
||||
- CHANGELOG.md
|
||||
|
||||
files_deleted:
|
||||
- .planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md
|
||||
|
||||
estimate:
|
||||
tokens: 30000
|
||||
raw_tokens: 30000
|
||||
tasks: 3
|
||||
confidence: low
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Kalender-Widget, Tooltip beim Überfahren eines Tages: lange Termintitel werden auf mehrere Zeilen umbrochen statt mit „…“ abgeschnitten; der Tooltip ist 288 px breit und wird am rechten Fensterrand weiterhin so verschoben, dass er vollständig sichtbar bleibt (Klemmwert aus derselben Konstante wie die Breite). Uhrzeit-Spalte, Portal in document.body, Begrenzung auf 5 Einträge plus Hinweis bleiben unverändert."
|
||||
- "Notiz-Widget: der Textbereich (MDEditor) folgt dem Hell/Dunkel-Schalter von Tessera (next-themes `resolvedTheme`), nicht mehr der Betriebssystem-Einstellung. Vor dem Mount ist der Wert 'light' (mounted-Guard wie in changelog-view.tsx), danach 'dark' genau dann, wenn `resolvedTheme === 'dark'`."
|
||||
- "CHANGELOG.md hat exakt den Inhalt von CHANGELOG.soll.md: gleiche drei `## `-Überschriften (`## Unveröffentlicht`, `## 1.1.0 – 2026-09-16`, `## 1.0.0 – 2026-09-15`), 28 Stichpunkte, jeder Punkt eine kurze Zeile ohne Punkt am Ende, echte Umlaute. CHANGELOG.soll.md ist danach gelöscht (nicht committet, war nie im Git)."
|
||||
- "Gates: `pnpm --filter @tessera/web type-check` Exit 0; `pnpm --filter @tessera/web exec vitest run` komplett grün (Basislinie 52 Dateien / 344 Tests → danach 52 Dateien / 347 Tests: +1 Kalender, +2 Notiz); Umlaut-Wächter 3/3; changelog.test.ts 10/10; `sh .gitea/scripts/publish-release.sh --dry-run --tag v1.1.0` Exit 0. KEIN `biome check`, kein Docker-Build, kein Deploy, kein Testserver, kein `git push`."
|
||||
artifacts:
|
||||
- "apps/web/src/components/dashboard/widgets/calendar-widget.tsx — Konstanten `TOOLTIP_WIDTH_PX = 288` und `TOOLTIP_EDGE_PX = 4`, Titel-Span im Tooltip mit `min-w-0 break-words`"
|
||||
- "apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx — neuer Test 4c (Titel-Span umbricht, Tooltip-Breite 288 px)"
|
||||
- "apps/web/src/components/dashboard/widgets/note-widget.tsx — `useTheme` aus next-themes, `mounted`-State, `data-color-mode={mode}`"
|
||||
- "apps/web/src/components/dashboard/widgets/note-widget.test.tsx — `vi.hoisted`-Themenzustand, next-themes-Mock, zwei neue Tests (dark/light)"
|
||||
- "CHANGELOG.md — Stichpunkt-Fassung"
|
||||
key_links:
|
||||
- "Tooltip-Klemmung: `left = max(4, min(rect.left, innerWidth − Breite − Rand))` — Breite und Klemmwert müssen aus EINER Konstante kommen, sonst driften sie (bisher `w-60` = 240 px und `− 244` hart nebeneinander)."
|
||||
- "Titel-Span steht in einem `flex`-Container neben der Uhrzeit-Spalte (`shrink-0`); ohne `min-w-0` darf ein Flex-Kind nicht unter seine Inhaltsbreite schrumpfen, dann greift `break-words` nicht und der Text ragt heraus — deshalb beide Klassen."
|
||||
- "@uiw/react-md-editor wertet `[data-color-mode]` per CSS-Selektor am nächsten Vorfahren aus; das Attribut am Wurzel-Div des Widgets reicht (deshalb stand dort bisher der feste Wert). `ThemeProvider` in apps/web/src/app/layout.tsx (attribute=\"class\", defaultTheme=\"system\", enableSystem) liefert `resolvedTheme` = 'light' | 'dark'."
|
||||
- "Nur note-widget.test.tsx rendert NoteWidget wirklich; page.test.tsx mockt `@/components/dashboard/widgets/note-widget` als `() => null`, die Registry verdrahtet das Widget erst über `wireNoteWidget()` in page.tsx — kein weiterer Test braucht einen next-themes-Mock (gemessen per grep)."
|
||||
- "changelog.ts schneidet an `^## ` und erkennt `## Unveröffentlicht` exakt (`UNRELEASED_RE`); publish-release.sh schneidet mit awk an `^## X.Y.Z( |$)` — die drei Überschriften müssen zeichengenau bleiben (Gedankenstrich „–“, Datum). umlaut-guard.spec.ts prüft nur de.json/en.json, nicht CHANGELOG.md."
|
||||
---
|
||||
|
||||
<objective>
|
||||
Drei Nachträge zu den heutigen Dashboard-Arbeiten (260916-hiv/htc/iex), alle vom Anwender im Browser gemeldet: (1) Der Termin-Tooltip des Kalender-Widgets schneidet lange Titel ab („Deutscher Weltkindertag (…“) — er soll umbrechen. (2) Der Textbereich des Notiz-Widgets bleibt dunkel, wenn Tessera auf „Hell“ steht, weil er der Betriebssystem-Einstellung folgt — er soll dem Tessera-Schalter folgen, wie es die Seite „Was ist neu“ schon tut. (3) Die Änderungsliste CHANGELOG.md ist in Fließtext geraten — sie wird auf kurze Stichpunkte gestrafft (Vorlage liegt fertig im Auftragsordner).
|
||||
|
||||
Purpose: Sichtbare Bedienfehler vor der nächsten Beta beseitigen; Änderungsliste wieder lesbar.
|
||||
Output: Zwei Komponentenkorrekturen mit Tests, eine neue CHANGELOG.md, drei Commits.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/gsd-core/workflows/execute-plan.md
|
||||
@~/.claude/gsd-core/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@/home/vicolab/projects/tessera-ctl/CLAUDE.md
|
||||
@/home/vicolab/projects/tessera-ctl/apps/web/src/components/dashboard/widgets/calendar-widget.tsx
|
||||
@/home/vicolab/projects/tessera-ctl/apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx
|
||||
@/home/vicolab/projects/tessera-ctl/apps/web/src/components/dashboard/widgets/note-widget.tsx
|
||||
@/home/vicolab/projects/tessera-ctl/apps/web/src/components/dashboard/widgets/note-widget.test.tsx
|
||||
@/home/vicolab/projects/tessera-ctl/apps/web/src/components/changelog/changelog-view.tsx
|
||||
@/home/vicolab/projects/tessera-ctl/CHANGELOG.md
|
||||
@/home/vicolab/projects/tessera-ctl/.planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md
|
||||
|
||||
Live gemessen am 2026-09-16 (Planer):
|
||||
- calendar-widget.tsx: Tooltip-Block Z. 290-315. Z. 296 `className="pointer-events-none fixed z-50 w-60 rounded border border-border bg-card p-2 text-xs text-foreground shadow-lg"`, Z. 299 `left: Math.max(4, Math.min(hover.rect.left, window.innerWidth - 244))`, Z. 307 `<span className="truncate">{event.title}</span>` (OHNE `min-w-0` — die Vorgabe „min-w-0 behalten“ trifft nicht zu, es muss ergänzt werden). Die Liste „Nächste Termine“ (Z. 270-281) nutzt ebenfalls `truncate` — die bleibt unverändert (nur der Tooltip ist Auftrag).
|
||||
- calendar-widget.test.tsx: 9 Tests; Test 4 (Z. 149-173) öffnet den Tooltip über `fireEvent.mouseEnter` auf `[data-date="2026-07-20"]` mit Terminen „Team Meeting“ und „Lunch“; `within` ist bereits importiert (Z. 1). Der Titel „Team Meeting“ steht auch in „Nächste Termine“ im DOM — Abfragen daher IMMER mit `within(tooltip)`.
|
||||
- note-widget.tsx: Imports Z. 3-9 (kein next-themes), Komponente ab Z. 42, State-Block Z. 44-51, Cleanup-Effekt Z. 56-61, Wurzel-Div Z. 131 mit festem Farbmodus-Attribut. `MDEditor` ab Z. 175 ohne eigenes `wrapperElement`.
|
||||
- note-widget.test.tsx: 7 Tests; Mocks für next-intl (Z. 5-13) und @uiw/react-md-editor (Z. 22-78); statischer Import `import { NoteWidget } from './note-widget'` Z. 81 („Must import after mocks“); `beforeEach` mit `vi.useFakeTimers()` und fetch-Spy; KEIN next-themes-Mock.
|
||||
- changelog-view.tsx Z. 20-27: `const { resolvedTheme } = useTheme(); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); const mode: 'light' | 'dark' = mounted && resolvedTheme === 'dark' ? 'dark' : 'light';` — Vorbild 1:1 übernehmen.
|
||||
- changelog-page.test.tsx Z. 42-44 zeigt den Mock-Stil: `vi.mock('next-themes', () => ({ useTheme: () => ({ resolvedTheme: 'light' }) }))`.
|
||||
- CHANGELOG.soll.md: 3 `## `-Überschriften (Z. 5, 26, 47), 28 Stichpunkte, kein Punkt am Zeilenende, keine CRLF. Sachlich gegen CHANGELOG.md und STATE.md geprüft — kein Fehler gefunden („Link“ in der 1.0.0-Liste ist historisch korrekt; Kalender-Widget/Favoriten-Titel unter „Neu“ statt „Geändert“ ist die gewollte Neusortierung).
|
||||
- publish-release.sh: `--dry-run --tag v1.1.0` läuft ohne Token und ohne Netz (Exit 0, druckt JSON); jq vorhanden. awk-Schnitt Z. 81-89 an `^## 1\.1\.0( |$)`.
|
||||
- docs/anleitung-anwender.md beschreibt nur Zweck und Gruppen der Liste, nicht den Stil — bleibt unangetastet.
|
||||
- Basislinie der vier betroffenen Testdateien: 4 Dateien / 29 Tests grün. Gesamt-Basislinie laut STATE.md: 52 Dateien / 344 Tests.
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Kalender-Tooltip — Titel umbrechen statt abschneiden, Breite und Klemmwert aus einer Konstante</name>
|
||||
<files>apps/web/src/components/dashboard/widgets/calendar-widget.tsx, apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx</files>
|
||||
<read_first>
|
||||
- apps/web/src/components/dashboard/widgets/calendar-widget.tsx Z. 26-36 (Kopfkommentar Tooltip), Z. 55-60 (hover-State), Z. 288-316 (Tooltip-Portal)
|
||||
- apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx Z. 1-12, Z. 149-201 (Tests 4 und 4b)
|
||||
</read_first>
|
||||
<behavior>
|
||||
- Test 4c (neu, nach 4b): Termin mit langem Titel (z. B. `ev('Deutscher Weltkindertag (Aktionstag der Kinderrechte)', …)` am 2026-07-20), Tooltip öffnen wie in Test 4; `const tooltip = screen.getByTestId('calendar-day-tooltip')`; `const title = within(tooltip).getByText('Deutscher Weltkindertag (Aktionstag der Kinderrechte)')`; `expect(title).toHaveClass('break-words')`, `expect(title).toHaveClass('min-w-0')`, `expect(title).not.toHaveClass('truncate')`; `expect(tooltip).toHaveStyle({ width: '288px' })`. Deutscher Testname: „Test 4c: Tooltip bricht lange Termintitel um statt sie abzuschneiden“.
|
||||
- Tests 4 und 4b bleiben unverändert grün (Portal, 5-Eintrag-Grenze, Hinweis).
|
||||
</behavior>
|
||||
<action>
|
||||
RED zuerst: Test 4c in calendar-widget.test.tsx ergänzen, `pnpm --filter @tessera/web exec vitest run src/components/dashboard/widgets/calendar-widget.test.tsx` — 4c muss ROT sein (Titel hat noch `truncate`, Breite kommt aus `w-60`).
|
||||
|
||||
GREEN in calendar-widget.tsx:
|
||||
1. Zwei Modul-Konstanten oberhalb der Komponente (bei den anderen Konstanten/Imports) anlegen: `const TOOLTIP_WIDTH_PX = 288;` und `const TOOLTIP_EDGE_PX = 4;` mit kurzem deutschen Kommentar (quick-260916-j4f: Breite und Rand-Klemmung des Termin-Tooltips aus einer Quelle, damit Breite und Klemmwert nicht auseinanderlaufen; 288 px entspricht Tailwind w-72).
|
||||
2. Tooltip-Div (Z. 296): die Klasse `w-60` aus `className` entfernen; alles andere in der Klassenliste bleibt. Im `style`-Objekt `width: TOOLTIP_WIDTH_PX` ergänzen und die `left`-Berechnung auf `Math.max(TOOLTIP_EDGE_PX, Math.min(hover.rect.left, window.innerWidth - TOOLTIP_WIDTH_PX - TOOLTIP_EDGE_PX))` umstellen (bisher hart 4 und 244). `top` bleibt `hover.rect.bottom + 4` — dort ebenfalls `TOOLTIP_EDGE_PX` verwenden.
|
||||
3. Titel-Span (Z. 307): `className="truncate"` → `className="min-w-0 break-words"`. Die Uhrzeit-Spalte (`shrink-0 tabular-nums …`) bleibt.
|
||||
4. Kopfkommentar Z. 31-33 um einen Satz ergänzen: Titel im Tooltip brechen um (kein truncate), Breite/Klemmung über `TOOLTIP_WIDTH_PX`/`TOOLTIP_EDGE_PX` (quick-260916-j4f).
|
||||
Nichts an der Liste „Nächste Termine“, an `hoverEvents.slice(0, 5)`, am Portal oder an den Datenpfaden ändern.
|
||||
|
||||
Test 4c muss danach GRÜN sein, alle 10 Kalender-Tests grün. Commit: `fix(web): Kalender-Tooltip bricht lange Termintitel um (Breite/Klemmung aus einer Konstante)`.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/vicolab/projects/tessera-ctl && grep -q 'const TOOLTIP_WIDTH_PX = 288' apps/web/src/components/dashboard/widgets/calendar-widget.tsx && grep -q 'min-w-0 break-words' apps/web/src/components/dashboard/widgets/calendar-widget.tsx && grep -q 'Test 4c' apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx && pnpm --filter @tessera/web exec vitest run src/components/dashboard/widgets/calendar-widget.test.tsx</automated>
|
||||
</verify>
|
||||
<done>Tooltip-Titel tragen `min-w-0 break-words` und kein `truncate`; Breite 288 px und Klemmung kommen aus `TOOLTIP_WIDTH_PX`/`TOOLTIP_EDGE_PX`; calendar-widget.test.tsx 10/10 grün (vorher 9), Test 4c belegt Klassen und Breite.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 2: Notiz-Widget folgt dem Tessera-Farbmodus (next-themes + mounted-Guard wie changelog-view)</name>
|
||||
<files>apps/web/src/components/dashboard/widgets/note-widget.tsx, apps/web/src/components/dashboard/widgets/note-widget.test.tsx</files>
|
||||
<read_first>
|
||||
- apps/web/src/components/changelog/changelog-view.tsx Z. 1-38 (Vorbild)
|
||||
- apps/web/src/components/dashboard/widgets/note-widget.tsx Z. 1-12, Z. 42-62, Z. 128-135
|
||||
- apps/web/src/components/dashboard/widgets/note-widget.test.tsx Z. 1-25, Z. 78-107
|
||||
- apps/web/src/app/(portal)/changelog/changelog-page.test.tsx Z. 40-45 (Mock-Stil next-themes)
|
||||
</read_first>
|
||||
<behavior>
|
||||
- Neuer Test „setzt data-color-mode auf dark, wenn Tessera auf Dunkel steht“: Themenzustand auf 'dark' stellen, `const { container } = render(<NoteWidget instanceId="note-t1" config={{}} isEditMode={false} />)`; `container.querySelector('[data-color-mode]')` hat Attribut `data-color-mode` = `'dark'`.
|
||||
- Neuer Test „setzt data-color-mode auf light, wenn Tessera auf Hell steht“: Themenzustand 'light' → Attribut `'light'`.
|
||||
- Die 7 bestehenden Tests bleiben grün (der Farbmodus ist für sie egal; Vorgabe im Mock: 'light').
|
||||
</behavior>
|
||||
<action>
|
||||
RED zuerst in note-widget.test.tsx:
|
||||
1. Vor den bestehenden `vi.mock`-Aufrufen (nach den Imports) einen gehobenen Themenzustand anlegen: `const themeMock = vi.hoisted(() => ({ resolvedTheme: 'light' as 'light' | 'dark' }));` und darunter `vi.mock('next-themes', () => ({ useTheme: () => ({ resolvedTheme: themeMock.resolvedTheme }) }));` — `vi.hoisted`, damit die Variable trotz Hoisting der Mocks und des statischen Imports in Z. 81 sicher initialisiert ist. Im `beforeEach` `themeMock.resolvedTheme = 'light'` zurücksetzen.
|
||||
2. Die zwei Tests aus `<behavior>` ans Ende des `describe` anhängen (Zustand jeweils VOR `render` setzen). Lauf: `pnpm --filter @tessera/web exec vitest run src/components/dashboard/widgets/note-widget.test.tsx` — beide neuen Tests ROT (Attribut hat noch den festen Wert).
|
||||
|
||||
GREEN in note-widget.tsx:
|
||||
3. Import `import { useTheme } from 'next-themes';` ergänzen (Paket ist installiert, 0.4.6). `useEffect`/`useState` sind schon importiert.
|
||||
4. In `NoteWidget` direkt nach `const t = useTranslations('widgets');`: `const { resolvedTheme } = useTheme();` und `const [mounted, setMounted] = useState(false);`; einen eigenen Effekt `useEffect(() => { setMounted(true); }, []);` (getrennt vom Cleanup-Effekt Z. 56-61). Danach `const colorMode: 'light' | 'dark' = mounted && resolvedTheme === 'dark' ? 'dark' : 'light';` — exakt das Muster aus changelog-view.tsx Z. 20-27 (mounted-Guard, damit Server- und Client-Markup übereinstimmen).
|
||||
5. Wurzel-Div Z. 131: den festen Attributwert durch `data-color-mode={colorMode}` ersetzen. Kurzer Kommentar darüber (quick-260916-j4f: folgt dem Tessera-Schalter statt der Betriebssystem-Einstellung, Muster changelog-view.tsx).
|
||||
Keine Änderung an MDEditor-Props, Speichern, Abhaken oder Übersetzungen.
|
||||
|
||||
Danach alle 9 Notiz-Tests grün und `pnpm --filter @tessera/web type-check` Exit 0. Commit: `fix(web): Notiz-Widget folgt dem Hell/Dunkel-Schalter von Tessera statt der Systemeinstellung`.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/vicolab/projects/tessera-ctl && grep -q "from 'next-themes'" apps/web/src/components/dashboard/widgets/note-widget.tsx && grep -q 'data-color-mode={colorMode}' apps/web/src/components/dashboard/widgets/note-widget.tsx && ! grep -q 'data-color-mode="auto"' apps/web/src/components/dashboard/widgets/note-widget.tsx && grep -q "vi.mock('next-themes'" apps/web/src/components/dashboard/widgets/note-widget.test.tsx && pnpm --filter @tessera/web exec vitest run src/components/dashboard/widgets/note-widget.test.tsx && pnpm --filter @tessera/web type-check</automated>
|
||||
</verify>
|
||||
<done>Wurzel-Div des Notiz-Widgets trägt `data-color-mode={colorMode}` aus `useTheme().resolvedTheme` mit mounted-Guard; note-widget.test.tsx 9/9 grün (vorher 7) mit next-themes-Mock über `vi.hoisted`; tsc Exit 0.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: CHANGELOG.md auf Stichpunkte straffen (Soll-Datei übernehmen, Vorlage löschen), Gesamtgates</name>
|
||||
<files>CHANGELOG.md, .planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md</files>
|
||||
<read_first>
|
||||
- .planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md (ganz, 63 Zeilen)
|
||||
- CHANGELOG.md (ganz, zum Abgleich der Überschriften)
|
||||
- apps/web/src/lib/changelog.ts Z. 26-40 (UNRELEASED_HEADING, SECTION_RE)
|
||||
- .gitea/scripts/publish-release.sh Z. 78-95 (awk-Schnitt)
|
||||
</read_first>
|
||||
<action>
|
||||
1. CHANGELOG.md vollständig durch den Inhalt von CHANGELOG.soll.md ersetzen: `cp .planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md CHANGELOG.md` (Byte-genau, keine Nacharbeit, keine Umlaut-Ersetzung — echte Umlaute bleiben; der Umlaut-Wächter prüft nur de.json/en.json). Ein sachlicher Fehler in der Vorlage wurde bei der Planung nicht gefunden; falls beim Lesen doch einer auffällt (Aussage, die dem Code oder STATE.md widerspricht), korrigieren und im SUMMARY unter „Abweichungen“ nennen.
|
||||
2. Prüfen, dass die drei `## `-Überschriften zeichengenau erhalten sind (Gedankenstrich „–“, Datum) und kein Stichpunkt mit einem Punkt endet (siehe verify).
|
||||
3. Vorlage löschen: `rm .planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md` (Scratch-Eingabe, nie im Git — daher `rm`, nicht `git rm`).
|
||||
4. Gesamtgates laufen lassen und die Zahlen für das SUMMARY notieren: `pnpm --filter @tessera/web type-check`; `pnpm --filter @tessera/web exec vitest run` (Erwartung 52 Dateien / 347 Tests, darin umlaut-guard 3/3 und changelog.test.ts 10/10); `sh .gitea/scripts/publish-release.sh --dry-run --tag v1.1.0` (Exit 0, JSON enthält „Seite „Was ist neu““ im body). docs/anleitung-anwender.md NICHT anfassen (beschreibt nur Zweck und Gruppen der Liste, nicht den Stil).
|
||||
5. Commit nur mit CHANGELOG.md: `docs: Changelog auf Stichpunkte gestrafft (kein Fließtext)`.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/vicolab/projects/tessera-ctl && test ! -e .planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/CHANGELOG.soll.md && grep -qx '## Unveröffentlicht' CHANGELOG.md && grep -qx '## 1.1.0 – 2026-09-16' CHANGELOG.md && grep -qx '## 1.0.0 – 2026-09-15' CHANGELOG.md && ! grep -E '^## ' CHANGELOG.md | grep -vqE '^## (Unveröffentlicht|1\.1\.0 – 2026-09-16|1\.0\.0 – 2026-09-15)$' && test "$(grep -E '^- ' CHANGELOG.md | wc -l)" = 28 && ! grep -qE '^- .*\.$' CHANGELOG.md && grep -q 'Textbereich folgt dem Hell/Dunkel-Schalter' CHANGELOG.md && ! grep -q $'\r' CHANGELOG.md && sh .gitea/scripts/publish-release.sh --dry-run --tag v1.1.0 >/dev/null && pnpm --filter @tessera/web type-check && pnpm --filter @tessera/web exec vitest run</automated>
|
||||
</verify>
|
||||
<done>CHANGELOG.md entspricht der Soll-Vorlage (3 Überschriften, 28 Stichpunkte, kein Satzpunkt am Zeilenende, echte Umlaute); CHANGELOG.soll.md gelöscht; Release-Skript findet den 1.1.0-Abschnitt im Probelauf; Web-tsc 0; Web-vitest komplett grün mit 52 Dateien / 347 Tests.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| Kalenderdaten → DOM (Tooltip) | Termintitel aus externen Kalenderquellen werden im Tooltip gerendert. |
|
||||
| next-themes (localStorage `theme`) → Notiz-Widget | Der Farbmodus kommt aus dem clientseitigen Themenzustand. |
|
||||
| CHANGELOG.md → Build → Seite „Was ist neu“ / Gitea-Release | Markdown wird zur Bauzeit eingebettet und per rehypeSanitize gerendert; das Release-Skript liest Abschnitte. |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|----------|-------------|-----------------|
|
||||
| T-J4F-01 | Tampering / XSS | calendar-widget.tsx Tooltip-Titel | low | mitigate | Titel bleibt React-Textknoten (`{event.title}`), nur CSS-Klassen ändern sich; kein `dangerouslySetInnerHTML`. |
|
||||
| T-J4F-02 | Denial of Service | Tooltip mit sehr langem Titel | low | mitigate | `break-words` bricht auch wortlose Zeichenketten; Breite fest 288 px, Portal `pointer-events-none`, weiterhin maximal 5 Einträge. |
|
||||
| T-J4F-03 | Information Disclosure | Notiz-Widget Farbmodus | low | accept | `resolvedTheme` ist nur 'light'/'dark'; jeder andere Wert fällt auf 'light' zurück. Kein Datenabfluss. |
|
||||
| T-J4F-04 | Tampering | CHANGELOG.md-Ersatz | low | mitigate | Byte-genaues Kopieren der geprüften Vorlage; Gates prüfen Überschriften, Punktzahl und Release-Schnitt; rehypeSanitize in changelog-view.tsx bleibt. |
|
||||
| T-J4F-SC | Tampering | npm/pip/cargo installs | low | accept | Keine Paketinstallation — next-themes 0.4.6 ist bereits im Lockfile und in changelog-view.tsx in Gebrauch. |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- `pnpm --filter @tessera/web type-check` → Exit 0.
|
||||
- `pnpm --filter @tessera/web exec vitest run` → komplett grün, 52 Dateien / 347 Tests (Basislinie 52 / 344; +1 Kalender, +2 Notiz); umlaut-guard 3/3 und changelog.test.ts 10/10 im Gesamtlauf enthalten.
|
||||
- `sh .gitea/scripts/publish-release.sh --dry-run --tag v1.1.0` → Exit 0.
|
||||
- CHANGELOG.soll.md existiert nicht mehr; `git status` zeigt sie nicht (war nie getrackt).
|
||||
- Kein `biome check` als Gate (bekannter Konfigurationsfehler, biome.json unverändert); kein Docker-Build, kein Deploy, kein Testserver, kein `git push`.
|
||||
- Drei Commits, einer je Task (Konvention der heutigen Quick-Tasks): `fix(web): …`, `fix(web): …`, `docs: …`.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Kalender-Tooltip: lange Titel umbrechen (Test 4c), Breite und Klemmung aus einer Konstante.
|
||||
- Notiz-Widget: `data-color-mode` folgt `resolvedTheme` von next-themes mit mounted-Guard (zwei neue Tests).
|
||||
- CHANGELOG.md in Stichpunkt-Fassung, Überschriften intakt, Vorlage gelöscht.
|
||||
- Alle Gates aus `<verification>` grün; SUMMARY nennt die gemessenen Zahlen (vorher 52/344).
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Create `.planning/quick/260916-j4f-nachtraege-kalender-tooltip-umbrechen-no/260916-j4f-SUMMARY.md` when done (Muster: die SUMMARY von 260916-iex — Abschnitte Was gebaut wurde / Entscheidungen / Gemessene Zahlen / Commits / Abweichungen vom Plan).
|
||||
</output>
|
||||
Reference in New Issue
Block a user