diff --git a/docs/feature-mdeditor.md b/docs/feature-mdeditor.md
index 152de8d..48fe3d2 100644
--- a/docs/feature-mdeditor.md
+++ b/docs/feature-mdeditor.md
@@ -130,3 +130,62 @@ Konfiguration: `Table.configure({ resizable: false })`
- `/code` (inline) — nach dem Löschen des Slash-Texts gibt es keine Auswahl; das Code-Mark wird als "stored mark" für den nächsten Tipp-Vorgang aktiviert (Tiptap-Standardverhalten)
- Bubble Menu Link-Button nutzt `window.prompt` — blockiert kurz den Browser
+
+---
+
+## Read-Mode: RenderedMarkdown-Pipeline
+
+### Komponenten
+
+| Komponente | Datei | Zweck |
+|-----------|-------|-------|
+| `RenderedMarkdown` | `components/RenderedMarkdown.svelte` | Generisches Render-Primitiv (marked + DOMPurify). Props: `text`, `historyEntryId?`, `topicId?`, `class?` |
+| `HistoryEntryText` | `components/HistoryEntryText.svelte` | Wrapper für HistoryEntry-Text. Erzwingt `entry: EntryLike` als Pflicht-Prop, leitet `id`/`topicId` an `RenderedMarkdown` weiter |
+| `refClick` | `actions/refClick.ts` | Svelte Action — Event-Delegation für @mentions, Assignments, Task-Chips, Wiki-Links |
+
+### Wann `HistoryEntryText` vs. `RenderedMarkdown`
+
+**`HistoryEntryText`** — immer wenn der Text einem HistoryEntry gehört (Chip-Klick soll Text aktualisieren können):
+```svelte
+
+
+```
+
+**`RenderedMarkdown`** — für echte read-only-Kontexte ohne HistoryEntry-Bezug:
+```svelte
+
+
+```
+
+`RenderedMarkdown` direkt mit expliziten IDs — wenn kein vollständiges Entry-Objekt vorhanden (projizierte Typen mit abweichenden Feldnamen):
+```svelte
+
+```
+
+### `EntryLike`-Interface
+
+`HistoryEntryText` akzeptiert ein strukturelles Minimum — kompatibel mit vollständigen `HistoryEntry`-Objekten und schmalen Projektionen:
+```typescript
+interface EntryLike { id: string; topicId: string; text: string; }
+```
+TypeScript erzwingt alle drei Felder. Vergessene IDs → Compile-Fehler (nicht silent failure wie vorher).
+
+### `refClick`-Action: Param-Übergabe
+
+Die Action empfängt `historyEntryId`/`topicId` explizit über `use:refClick`. `RenderedMarkdown` setzt dies intern — Aufrufer müssen die Action nie direkt verwenden.
+
+Bei Task-Chip-Klick dispatcht `refClick` ein `ka-open-task-create`-Event mit `historyEntryId` im Detail. `ContextPage` fängt es und löst daraus `contextId` auf:
+```
+historyEntryId → db.historyEntries.get() → entry.topicId → db.topics.get() → topic.contextId
+```
+
+### Vollständige Render-Chain (Task-Flow)
+
+```
+[] Aufgabe → renderMarkdown.ts (marked extension)
+ → [ ]
+ → RenderedMarkdown (use:refClick={{ historyEntryId, topicId }})
+ → Klick → handleTaskNewClick(historyEntryId, topicId)
+ → ka-open-task-create event (bubbles up to ContextPage)
+ → createTask() + updateHistoryEntry([] → [T:id])
+```
diff --git a/docs/feature-tasks.md b/docs/feature-tasks.md
index 0c5a466..78938d4 100644
--- a/docs/feature-tasks.md
+++ b/docs/feature-tasks.md
@@ -76,29 +76,83 @@ Das `source`-Feld und `externalId`/`externalUrl` bereiten künftige Integratione
## Implementierungshinweise (für Wartung)
+### Architektur: Wo HistoryEntries auftauchen
+
+HistoryEntries sind **topic-scoped**, nicht context-scoped. Ein HistoryEntry gehört zu einem Topic (`entry.topicId`), das Topic gehört zu einem Kontext (`topic.contextId`). Daraus folgt:
+
+```
+HistoryEntry.text
+ → gerendert in RenderedMarkdown
+ → Task-Chip-Klick braucht entry.id + entry.topicId
+ → ContextPage löst daraus contextId auf
+```
+
+**Der nicht-offensichtliche Fall: `EventCard`**
+
+`EventCard` zeigt einen *Termin* (Kontext vom Typ `meeting`), nicht direkt einen HistoryEntry. Die Meeting-Notizen sind aber intern als HistoryEntry gespeichert — unter dem speziellen Topic `notesTopicId(event.id)`. Dieser Mechanismus ist im EventCard-Code versteckt (`liveQuery` auf `notesTopicId`). Wer `EventCard` nur von außen sieht ("das ist eine Meeting-Karte"), erwartet dort keinen HistoryEntry-Kontext — und vergisst deshalb, `historyEntryId` zu übergeben.
+
+Merksatz: **Überall wo `entry.text` oder ein abgeleiteter Text (title/body-Split) gerendert wird, muss `entry.id` als `historyEntryId` mitgegeben werden — egal wie die Komponente heißt.**
+
### `historyEntryId` muss überall explizit übergeben werden
-`RenderedMarkdown` wird an ~10 Stellen instanziiert. Ohne `historyEntryId`-Prop öffnet ein Task-Chip-Klick das Modal mit `historyEntryId: null` — der Task wird angelegt, aber der Quelltext (`[] …` → `[T:id]`) wird **nicht** aktualisiert.
+`RenderedMarkdown` wird an ~10 Stellen instanziiert. Ohne `historyEntryId`-Prop öffnet ein Task-Chip-Klick das Modal mit `historyEntryId: null` — der Task wird angelegt, aber der Quelltext (`[] …` → `[T:id]`) wird **nicht** aktualisiert. Der Fehler ist stumm: kein Fehler, kein visuelles Feedback, nur der Chip bleibt `[ ]`.
-**Alle Stellen müssen `historyEntryId={entry.id} topicId={entry.topicId}` übergeben**, wenn der gerenderte Text einem HistoryEntry gehört:
+**Vollständige Instanz-Übersicht:**
-| Datei | Status |
-|-------|--------|
-| `HistoryItem.svelte` | ✓ |
-| `JournalView.svelte` (daily-log Branch) | ✓ |
-| `JournalView.svelte` (Meeting-Scope Branch) | ✓ |
-| `EventCard.svelte` (Meeting-Notizen) | ✓ |
-| `DashboardView.svelte`, `ArchivedView.svelte`, `WiedervorlageCard.svelte` | — kein Task-Kontext nötig |
-| `EditableMarkdown.svelte` (Topic-Body Preview) | — kein HistoryEntry, Task-Chips dort sind aktuell nicht aktiv |
+| Datei | Quelle | historyEntryId | Notiz |
+|-------|--------|---------------|-------|
+| `HistoryItem.svelte` | `entry` | ✓ | |
+| `JournalView.svelte:626/640` | `entry` (daily-log) | ✓ | |
+| `JournalView.svelte:674` | `entry` (Meeting-Scope) | ✓ | |
+| `EventCard.svelte` | `notesEntry` (versteckt) | ✓ | `notesEntry` = erster Entry aus `notesTopicId(event.id)` |
+| `DashboardView.svelte:539/541` | `entry` | ✗ | read-only Dashboard, kein Task-Flow vorgesehen |
+| `DashboardView.svelte:569` | `entry` | ✗ | read-only Dashboard |
+| `ArchivedView.svelte` | `entry` | ✗ | archivierte Einträge, kein Task-Flow vorgesehen |
+| `WiedervorlageCard.svelte` | `entry` (body-Split) | ✗ | Wiedervorlage-Kontext, kein Task-Flow vorgesehen |
+| `PersonsView.svelte` | `task.text` | — | kein HistoryEntry |
+| `EditableMarkdown.svelte` | Topic-Body | — | kein HistoryEntry, `topicId` wäre theoretisch möglich |
+
+Wenn zukünftig Task-Chips auch in Dashboard/Archiv/Wiedervorlage aktiv werden sollen, müssen dort `historyEntryId` und `topicId` ergänzt werden.
### Debugging-Anleitung
-Symptom: Chip klickbar, Modal öffnet, aber `historyEntryId: null` → Text wird nie geändert.
+Symptom: Chip klickbar, Modal öffnet, aber Text bleibt `[] …` (kein `[T:id]`).
-Diagnose: Browser-Konsole im Klick-Event, dann im DOM:
+Diagnose im Browser-Devtools-Konsole:
```js
document.querySelector('[data-task-new]').closest('.markdown-content').parentElement.className
```
-→ Wenn die Klasse **nicht** aus `HistoryItem`/`JournalView` stammt, fehlt der `historyEntryId`-Prop in der entsprechenden Komponente.
+→ Klasse identifizieren → zugehörige Komponente finden → prüfen ob `historyEntryId` Prop gesetzt ist.
-Häufige Falle: `EventCard` rendert Meeting-Notizen via `RenderedMarkdown` ohne Kontext — Notizen sind intern als HistoryEntry (`notesTopicId(event.id)`) gespeichert, müssen explizit aufgelöst werden.
+### Empfohlenes Refactoring: `HistoryEntryText`-Komponente
+
+Die Wurzel des Problems ist, dass `RenderedMarkdown` ein generisches Render-Primitive ist, aber der HistoryEntry-Kontext implizit mitgegeben werden muss. Eine dedizierte Wrapper-Komponente würde das explizit machen:
+
+```svelte
+
+
+
+```
+
+Verwendung dann z.B.:
+```svelte
+
+
+```
+
+**Vorteile:**
+- `historyEntryId` kann nicht mehr vergessen werden — es ist Pflicht-Prop (TypeScript-Fehler sonst)
+- Neue Views die HistoryEntry-Text rendern, verwenden automatisch die richtige Komponente
+- `RenderedMarkdown` ohne `historyEntryId` bleibt erlaubt für echte read-only-Kontexte (Dashboard, Archiv)
+
+**Aufwand:** ~7 Stellen umbauen, kein Logik-Änderung. Kein dringender Handlungsbedarf, aber sinnvoll beim nächsten größeren Refactoring-Sprint.
diff --git a/ka-note/VERSION b/ka-note/VERSION
index 727c55f..5fabac2 100644
--- a/ka-note/VERSION
+++ b/ka-note/VERSION
@@ -1 +1 @@
-1.2.1
\ No newline at end of file
+1.2.2
\ No newline at end of file
diff --git a/ka-note/client/src/lib/components/ArchivedView.svelte b/ka-note/client/src/lib/components/ArchivedView.svelte
index 56762dc..24e0c84 100644
--- a/ka-note/client/src/lib/components/ArchivedView.svelte
+++ b/ka-note/client/src/lib/components/ArchivedView.svelte
@@ -3,7 +3,7 @@
import { db } from '$lib/db/schema';
import { updateTopic } from '$lib/db/repositories';
import LinkTitle from './LinkTitle.svelte';
- import RenderedMarkdown from './RenderedMarkdown.svelte';
+ import HistoryEntryText from './HistoryEntryText.svelte';
import type { Topic, HistoryEntry } from '@ka-note/shared';
interface Props {
@@ -60,7 +60,7 @@
{#each historyCache.get(topic.id) ?? [] as entry (entry.id)}
{:else}
Keine Einträge.
diff --git a/ka-note/client/src/lib/components/DashboardView.svelte b/ka-note/client/src/lib/components/DashboardView.svelte
index f4836f2..f29dff7 100644
--- a/ka-note/client/src/lib/components/DashboardView.svelte
+++ b/ka-note/client/src/lib/components/DashboardView.svelte
@@ -8,6 +8,7 @@
import { extractAssignments, extractProjects, extractMentions, extractCompanies } from '$lib/utils/extractors';
import { mention } from '$lib/actions/mention';
import RenderedMarkdown from './RenderedMarkdown.svelte';
+ import HistoryEntryText from './HistoryEntryText.svelte';
import LinkTitle from './LinkTitle.svelte';
import MarkdownEditor from './MarkdownEditor.svelte';
import EditableMarkdown from './EditableMarkdown.svelte';
@@ -536,9 +537,9 @@
>×
-
+
{#if body}
-
+
{/if}
{/if}
@@ -566,7 +567,7 @@
>{entry.contextName}:
{entry.topicTitle}
-
+
{:else}
Keine Einträge gefunden.
diff --git a/ka-note/client/src/lib/components/EventCard.svelte b/ka-note/client/src/lib/components/EventCard.svelte
index 8b2dd00..4773d3f 100644
--- a/ka-note/client/src/lib/components/EventCard.svelte
+++ b/ka-note/client/src/lib/components/EventCard.svelte
@@ -4,7 +4,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/db/schema';
import MarkdownEditor from './MarkdownEditor.svelte';
- import RenderedMarkdown from './RenderedMarkdown.svelte';
+ import HistoryEntryText from './HistoryEntryText.svelte';
import { updateEvent, updateEventNotes, softDeleteContext } from '$lib/db/repositories';
import { notesTopicId } from '$lib/db/repositories';
import { mention } from '$lib/actions/mention';
@@ -207,8 +207,8 @@
onclick={() => (editingNotes = true)}
onkeydown={(e) => e.key === 'Enter' && (editingNotes = true)}
>
- {#if notesText}
-
+ {#if notesEntry && notesEntry.text}
+
{:else}
Notizen hinzufügen...
{/if}
diff --git a/ka-note/client/src/lib/components/HistoryEntryText.svelte b/ka-note/client/src/lib/components/HistoryEntryText.svelte
new file mode 100644
index 0000000..c4362aa
--- /dev/null
+++ b/ka-note/client/src/lib/components/HistoryEntryText.svelte
@@ -0,0 +1,17 @@
+
+
diff --git a/ka-note/client/src/lib/components/HistoryItem.svelte b/ka-note/client/src/lib/components/HistoryItem.svelte
index 5ef9591..a6016ed 100644
--- a/ka-note/client/src/lib/components/HistoryItem.svelte
+++ b/ka-note/client/src/lib/components/HistoryItem.svelte
@@ -1,7 +1,7 @@