mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:21:10 +02:00
feat(templates): generalise to WorkbenchTemplate + ship Calmness pilot (T1)
First pass of the workbench-templates plan (docs/plans/workbench-
templates.md) — templates are no longer agent-centric but a general
"starter kit" bundle: optional agent + optional scene + optional
missions + optional per-module seeds. Pilot non-AI template "Calmness"
ships alongside.
Shape generalisation (packages/shared-ai/src/agents/templates/types.ts):
- AgentTemplate renamed to WorkbenchTemplate; all fields now optional
(agent, scene, missions, seeds). Back-compat AgentTemplate alias
kept so research/context/today keep compiling.
- Added `category: 'ai'|'wellness'|'work'|'lifeEvent'|'delight'` +
`icon` (for non-agent templates that have no avatar) + `version`
field (for future update-detection).
- New WorkbenchTemplateSeedItem shape: `{stableId?, data: unknown}`.
Module-specific seed payloads are typed at the handler side.
- Existing three AI templates nachgezogen: category='ai' (or
'delight' for today-agent), icon, version='1'.
Seed infrastructure:
- apps/mana/apps/web/src/lib/data/ai/agents/seed-registry.ts — in-
memory handler map keyed by module name; module-local seed.ts files
register themselves at import time.
- apps/mana/apps/web/src/lib/modules/meditate/seed.ts — first handler:
createPreset-based, idempotent via stableId embedded as HTML
comment in the preset description (T1 pragmatism; T2 adds a proper
column on the preset schema).
- data/ai/missions/setup.ts pulls `import '$lib/modules/meditate/seed'`
so the handler is registered before any template is applied.
Applicator upgrades (data/ai/agents/apply-template.ts):
- Agent step now optional — skipped cleanly when template has no
agent part.
- New step 4: seeds. Walks template.seeds, looks up the handler for
each module, aggregates per-item outcomes (created/skipped-exists/
failed) into result.seedOutcomes. Missing handler = warning, not
fatal. Crypto/encryption unchanged — seeds go through the same
module stores that module code already uses.
- Result shape gains `seedOutcomes: Record<string, SeedOutcome[]>`
so the gallery can show "3 new, 1 already there".
Calmness pilot (packages/shared-ai/src/agents/templates/calmness.ts):
- category='wellness', NO agent, scene with meditate/mood/journal/
sleep apps, two meditate preset seeds:
* 4-7-8 Atmung (breathing preset)
* Body-Scan 10min (bodyscan preset with 9 scan steps)
- Each seed has a stableId so re-apply is idempotent.
Gallery updates (routes/(app)/agents/templates/+page.svelte):
- Card avatar falls back to t.icon when no agent. "Agent" chip shows
only for agent-templates; "N Seeds" chip shows for templates with
seeds.
- Detail header shows "Workbench-Setup ohne AI-Agent" when no agent.
- New "Seeds" preview section: lists per-module counts + item names.
- Options section gains a "Seed-Daten in Module einpflegen" checkbox.
- Success panel shows seed summary: "3 Seeds neu, 1 bereits
vorhanden".
Tests: shared-ai 26/26, webapp svelte-check 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a524997a2f
commit
a08e45ca16
14 changed files with 887 additions and 119 deletions
338
docs/plans/workbench-templates.md
Normal file
338
docs/plans/workbench-templates.md
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
# Plan: Workbench Templates — Starter-Kits über Module hinweg
|
||||
|
||||
**Status:** Draft, 2026-04-16. Phase T1 (Shape-Generalisierung) + Pilot "Calmness" startet jetzt; T2-T5 folgen iterativ.
|
||||
**Scope:** Erweitere das existierende Agent-Templates-System ([`multi-agent-workbench.md`](./multi-agent-workbench.md) Phase 5) so dass Templates nicht nur Agents bündeln, sondern komplette Workbench-Starter-Kits: Scene + Agent (optional) + Missionen (optional) + **Seed-Daten in beliebigen Modulen** (optional).
|
||||
**Motivation:** Templates wie "Fitness", "Calmness", "Deep Work" haben immensen Onboarding-Wert, brauchen aber _keinen AI-Agent_ — nur Scene + vor-gefüllte Records (Habits, Goals, Meditate-Presets, …). Der heutige `AgentTemplate`-Shape zwingt einen Agent ins Bundle. Das wollen wir auseinanderziehen.
|
||||
**Verwandte Docs:** [`multi-agent-workbench.md`](./multi-agent-workbench.md), [`../architecture/COMPANION_BRAIN_ARCHITECTURE.md`](../architecture/COMPANION_BRAIN_ARCHITECTURE.md), Ideas-Backlog [`../future/AI_AGENTS_IDEAS.md`](../future/AI_AGENTS_IDEAS.md).
|
||||
|
||||
---
|
||||
|
||||
## Entscheidungen (baked in)
|
||||
|
||||
| Frage | Entscheidung | Begründung |
|
||||
|---|---|---|
|
||||
| **Template-Typ-Name** | `WorkbenchTemplate` (umbenennen von `AgentTemplate`) mit optionalen Feldern für Agent, Scene, Seeds, Missions | Ehrlicher Name. `AgentTemplate` wäre ein Sub-Use-Case. Migrations-Path via Alias. |
|
||||
| **Agent ist jetzt optional** | `agent?: AgentConfig` statt required | Wellness-Templates ohne AI sollen machbar sein |
|
||||
| **Kategorisierung** | `category: 'ai' \| 'wellness' \| 'work' \| 'lifeEvent' \| 'delight'` | Gallery kann nach Kategorie gruppieren; Discoverability verbessert sich |
|
||||
| **Seed-Daten pro Modul** | Template hat `seeds: { [moduleName]: SeedItem[] }` — pro Modul ein kleines Array pre-gefüllter Records | Flexibel, modul-lokal typisiert, keine Cross-Contamination |
|
||||
| **Seed-Handler-Registry** | Jedes Modul das seedable sein will exportiert eine `seed.ts` mit `{ moduleName, seedFn(items) }`. Template-Applicator hat eine Registry `SEED_HANDLERS` die sie aggregiert. | Mirror des `input-resolvers`-Musters. Module bleiben autonom; Templates sind durable-lokal typed. |
|
||||
| **Seed-Idempotenz** | Jedes Seed-Item hat optional `stableId`. Wenn der Applicator den Seed mit stableId schon findet, skipped er ihn und wirft eine Warning. Seeds ohne stableId werden immer neu erstellt. | Beides hat Use-Cases. Stable-IDs für "kanonische" Seeds (z.B. "Fitness 10-min Meditation"), UUIDs für "bei jedem Apply neu". |
|
||||
| **Partial-Apply** | Wie Agent-Templates heute — Fehler pro Seed-Slot in `result.warnings`, aber Gesamt-Apply blockiert nicht | Konsistent mit dem existierenden Applicator. |
|
||||
| **Versionierung** | Template-Config hat `version: '1'` Feld. Zukünftiges "Update verfügbar" ist Phase T5; jetzt reicht die Versionierung als _Metadaten_ damit wir später die Logik dranhängen können. | Billige Vorkehrung. |
|
||||
| **Backward-Compat für `AgentTemplate`** | Type-Alias `export type AgentTemplate = WorkbenchTemplate`. Existierende Templates (`research/context/today`) bleiben unverändert. | Null Regression. |
|
||||
| **Gallery-Kategorien** | Ab T1 nur flach gerendert. Ab T3 Gruppierung/Filter. | Incremental. |
|
||||
|
||||
---
|
||||
|
||||
## Daten-Modell
|
||||
|
||||
### Neuer Template-Typ
|
||||
|
||||
```ts
|
||||
// packages/shared-ai/src/agents/templates/types.ts (erweitert)
|
||||
|
||||
export type WorkbenchTemplateCategory = 'ai' | 'wellness' | 'work' | 'lifeEvent' | 'delight';
|
||||
|
||||
export interface WorkbenchTemplateSeedItem {
|
||||
/** Wenn gesetzt: Applicator sucht einen existierenden Record mit
|
||||
* demselben `stableId` und überspringt bei Treffer. Wenn unset:
|
||||
* Applicator erzeugt bei jedem Apply einen neuen Record. */
|
||||
readonly stableId?: string;
|
||||
/** Modul-spezifische Payload. Der SeedHandler des Moduls kennt die
|
||||
* Struktur. Type-Sicherheit über Generic-Parameter in den einzelnen
|
||||
* Template-Konstanten. */
|
||||
readonly data: unknown;
|
||||
}
|
||||
|
||||
export interface WorkbenchTemplate {
|
||||
readonly id: string;
|
||||
readonly version: string; // '1' zunächst
|
||||
readonly label: string;
|
||||
readonly tagline: string;
|
||||
readonly description: string;
|
||||
readonly category: WorkbenchTemplateCategory;
|
||||
readonly color: string;
|
||||
/** Icon-Emoji für die Gallery-Karte (wenn kein Agent dabei ist). */
|
||||
readonly icon: string;
|
||||
|
||||
// Alle folgenden Felder optional — ein Template kann Agent-only,
|
||||
// Scene-only, Seeds-only oder jede Kombination sein.
|
||||
readonly agent?: WorkbenchTemplateAgentPart;
|
||||
readonly scene?: WorkbenchTemplateScenePart;
|
||||
readonly missions?: readonly WorkbenchTemplateMissionPart[];
|
||||
/** Modul-Name → Seed-Items für dieses Modul. Template-Applicator
|
||||
* schaut die Seed-Handler-Registry durch; unbekannte Module
|
||||
* werden als Warning gemeldet, kein hartes Fail. */
|
||||
readonly seeds?: Readonly<Record<string, readonly WorkbenchTemplateSeedItem[]>>;
|
||||
}
|
||||
|
||||
/** Backward compat: die existierenden research/context/today Templates
|
||||
* typieren sich weiterhin als AgentTemplate = WorkbenchTemplate. */
|
||||
export type AgentTemplate = WorkbenchTemplate;
|
||||
```
|
||||
|
||||
### Seed-Handler-Registry
|
||||
|
||||
```ts
|
||||
// apps/mana/apps/web/src/lib/data/ai/agents/seed-registry.ts
|
||||
|
||||
export interface SeedHandler {
|
||||
/** Modul-Name, korrespondiert mit dem Key in Template.seeds. */
|
||||
readonly moduleName: string;
|
||||
/** Wird aufgerufen mit allen Items für dieses Modul.
|
||||
* Soll Idempotenz-Handling (stableId-Check) selbst erledigen.
|
||||
* Gibt pro Item zurück ob es neu angelegt oder geskipped wurde. */
|
||||
readonly apply: (items: readonly WorkbenchTemplateSeedItem[]) => Promise<SeedOutcome[]>;
|
||||
}
|
||||
|
||||
export interface SeedOutcome {
|
||||
readonly stableId?: string;
|
||||
readonly outcome: 'created' | 'skipped-exists' | 'failed';
|
||||
readonly error?: string;
|
||||
}
|
||||
|
||||
export function registerSeedHandler(handler: SeedHandler): void { ... }
|
||||
export function getSeedHandler(moduleName: string): SeedHandler | undefined { ... }
|
||||
```
|
||||
|
||||
Jedes seedable Modul exportiert einen Handler, z.B.:
|
||||
|
||||
```ts
|
||||
// apps/mana/apps/web/src/lib/modules/meditate/seed.ts
|
||||
import { registerSeedHandler } from '$lib/data/ai/agents/seed-registry';
|
||||
import { meditateStore } from './stores/meditate.svelte';
|
||||
|
||||
registerSeedHandler({
|
||||
moduleName: 'meditate',
|
||||
async apply(items) { ... },
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phasen
|
||||
|
||||
### Phase T1 — Shape-Generalisierung + Calmness-Pilot (dieser Durchlauf)
|
||||
|
||||
- [ ] `WorkbenchTemplate` Typ in shared-ai; `AgentTemplate` als Alias
|
||||
- [ ] Existierende 3 Templates (`research/context/today`) bekommen `icon` + `version: '1'` + explizite `category: 'ai'`
|
||||
- [ ] `seeds`-Feld im Typ deklariert (unused bei den 3 bestehenden)
|
||||
- [ ] Webapp: `seed-registry.ts` mit `registerSeedHandler` / `getSeedHandler`
|
||||
- [ ] `apply-template.ts` erweitert um Seeds-Schritt (iteriert `template.seeds`, ruft passenden Handler, aggregiert Warnings)
|
||||
- [ ] **Pilot-Template "Calmness"** — `category: 'wellness'`, keine Agent, Scene `meditate · mood · journal · sleep`, 2 Meditate-Preset-Seeds (z.B. "4-7-8 Atmung" + "Body-Scan 10min")
|
||||
- [ ] Meditate-Modul exportiert `seed.ts` mit `seedHandler` der `createPreset` ruft
|
||||
- [ ] Gallery zeigt neuen Template ohne Kategorie-Filter (flach); Detail-Panel rendert "Seeds" Sektion wenn `template.seeds` gesetzt
|
||||
|
||||
**Ziel:** Calmness-Template funktioniert Ende-zu-Ende. User klickt "Calmness" in der Gallery → Scene wird angelegt → Meditate hat 2 neue Presets → kein Agent, keine Mission. Der _Weg_ ist etabliert; weitere Templates sind dann nur Konfiguration.
|
||||
|
||||
### Phase T2 — Seed-Handler für Kern-Module (~3-4 Tage)
|
||||
|
||||
Module die den größten UX-Gewinn aus Seeding haben:
|
||||
- [ ] `habits` — Habit-Seeds ("Täglich trainieren", "8h Schlaf")
|
||||
- [ ] `goals` — Goal-Seeds (Weekly / Monthly Ziele)
|
||||
- [ ] `todo` — Task-Seeds (Einmal-Tasks für Onboarding)
|
||||
- [ ] `food` — Nutrition-Target-Seeds (Kalorien, Wasser)
|
||||
- [ ] `meditate` — schon in T1
|
||||
- [ ] `drink` — Drink-Preset-Seeds
|
||||
- [ ] `places` — POI-Seeds (z.B. "Lieblings-Café hinzufügen")
|
||||
|
||||
Jedes Seed-Handler-Modul:
|
||||
- exportiert `seed.ts` mit `registerSeedHandler`
|
||||
- ist idempotent über stable-id (wo sinnvoll)
|
||||
- loggt die Outcome-Liste für die Template-Applicator-Warnings
|
||||
|
||||
### Phase T3 — 6 non-AI Templates + Kategorie-Filter (~3-5 Tage)
|
||||
|
||||
- [ ] 🏋️ **Fitness** — Scene + habits + goals + stretch-Routinen
|
||||
- [ ] 🧘 **Calmness** — Scene + meditate-Presets (von T1 übernehmen)
|
||||
- [ ] 💻 **Deep Work** — Scene + habits + times-Projekte + leere Todo
|
||||
- [ ] ✈️ **Travel** — Scene + places-Kategorien + calendar-Block-Template
|
||||
- [ ] 🎓 **Lernen** — Scene + skilltree-Presets + cards-Decks
|
||||
- [ ] 🌙 **Schlaf-Routine** — Scene + sleep-hygiene-checkliste + meditate-Presets
|
||||
|
||||
Gallery-Enhancements:
|
||||
- [ ] Kategorie-Tabs oben ("Alle · 🤖 AI · 🧘 Wellness · 💼 Arbeit · 🎉 Lebensereignis")
|
||||
- [ ] Beliebt-Sektion (Usage-Stats später; jetzt manuell kuratiert)
|
||||
- [ ] Template-Karten zeigen ihre Komponenten als Chips ("🧘 Presets · Scene · 2 Habits")
|
||||
|
||||
### Phase T4 — Update-Erkennung + bessere Delete-Story (~2 Tage)
|
||||
|
||||
- [ ] Template-Version wird am Scene gespeichert ("diese Scene basiert auf Calmness v1")
|
||||
- [ ] Wenn Template v2 veröffentlicht wird: In-UI Hinweis "Update verfügbar — fügt 1 Seed hinzu" mit Apply-Button
|
||||
- [ ] Scene-Delete fragt "Auch Seeds + Agent entfernen?" (default: nein — Seeds können anderweitig nützlich sein)
|
||||
|
||||
### Phase T5 — User-Created Templates (~1 Woche)
|
||||
|
||||
- [ ] Export-Scene-als-Template (inkl. User-Daten-Snapshots wenn User opt-in) → JSON
|
||||
- [ ] Import-Flow in der Gallery ("Template-Datei laden")
|
||||
- [ ] Community-Templates via "Template Teilen"-Link (kopiert JSON in Clipboard für jetzt; Future: Template-Share-Endpoint)
|
||||
|
||||
---
|
||||
|
||||
## Design-Details für Phase T1
|
||||
|
||||
### Wie "Calmness" konkret aussieht
|
||||
|
||||
```ts
|
||||
// packages/shared-ai/src/agents/templates/calmness.ts
|
||||
|
||||
export const calmnessTemplate: WorkbenchTemplate = {
|
||||
id: 'calmness',
|
||||
version: '1',
|
||||
label: 'Calmness',
|
||||
tagline: 'Atem, Stille, ruhige Momente',
|
||||
description: `Ein Workbench-Setup für Stille-Momente. Legt dir eine Szene mit
|
||||
den Modulen Meditate, Mood, Journal und Sleep an und seed-ed zwei Einstiegs-
|
||||
Meditationen — mehr brauchst du nicht um anzufangen.
|
||||
|
||||
Kein AI-Agent. Du meditierst, nicht dein Computer.`,
|
||||
category: 'wellness',
|
||||
color: '#8B5CF6',
|
||||
icon: '🧘',
|
||||
scene: {
|
||||
name: 'Calmness',
|
||||
description: 'Ruhe, Atem, Stille',
|
||||
openApps: [
|
||||
{ appId: 'meditate', widthPx: 540 },
|
||||
{ appId: 'mood', widthPx: 340 },
|
||||
{ appId: 'journal', widthPx: 440 },
|
||||
{ appId: 'sleep', widthPx: 340 },
|
||||
],
|
||||
},
|
||||
seeds: {
|
||||
meditate: [
|
||||
{
|
||||
stableId: 'template-calmness:preset:4-7-8',
|
||||
data: {
|
||||
name: '4-7-8 Atmung',
|
||||
description: 'Beruhigende Atemtechnik. Einatmen 4s, halten 7s, ausatmen 8s.',
|
||||
category: 'breathing',
|
||||
breathPattern: { inhale: 4, hold: 7, exhale: 8, rest: 0 },
|
||||
defaultDurationSec: 300,
|
||||
},
|
||||
},
|
||||
{
|
||||
stableId: 'template-calmness:preset:bodyscan-10',
|
||||
data: {
|
||||
name: 'Body-Scan 10min',
|
||||
description: 'Sanfte Aufmerksamkeits-Wanderung durch den Körper.',
|
||||
category: 'bodyscan',
|
||||
bodyScanSteps: [
|
||||
'Spüre deine Füße', 'Spüre deine Beine', 'Spüre dein Becken',
|
||||
'Spüre deinen Bauch', 'Spüre deine Brust', 'Spüre deine Arme',
|
||||
'Spüre deinen Nacken', 'Spüre deinen Kopf', 'Spüre deinen ganzen Körper',
|
||||
],
|
||||
defaultDurationSec: 600,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Seed-Handler für Meditate (konkret)
|
||||
|
||||
```ts
|
||||
// apps/mana/apps/web/src/lib/modules/meditate/seed.ts
|
||||
import { meditateStore } from './stores/meditate.svelte';
|
||||
import { db } from '$lib/data/database';
|
||||
import { registerSeedHandler } from '$lib/data/ai/agents/seed-registry';
|
||||
import type { LocalMeditatePreset } from './types';
|
||||
|
||||
interface MeditatePresetSeed {
|
||||
name: string;
|
||||
description?: string;
|
||||
category: 'silence' | 'breathing' | 'bodyscan';
|
||||
breathPattern?: { inhale: number; hold: number; exhale: number; rest: number };
|
||||
bodyScanSteps?: string[];
|
||||
defaultDurationSec?: number;
|
||||
}
|
||||
|
||||
registerSeedHandler({
|
||||
moduleName: 'meditate',
|
||||
async apply(items) {
|
||||
const outcomes = [];
|
||||
for (const item of items) {
|
||||
const seed = item.data as MeditatePresetSeed;
|
||||
// Stable-id idempotency: search Dexie for an existing preset
|
||||
// with `templateStableId = item.stableId`. Preset schema doesn't
|
||||
// have that column today; we stash it in `description` for T1.
|
||||
// T2 adds a proper column.
|
||||
if (item.stableId) {
|
||||
const existing = await db
|
||||
.table<LocalMeditatePreset>('meditatePresets')
|
||||
.filter((p) => !p.deletedAt && p.description?.includes(`\`${item.stableId}\``))
|
||||
.first();
|
||||
if (existing) {
|
||||
outcomes.push({ stableId: item.stableId, outcome: 'skipped-exists' });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
await meditateStore.createPreset({
|
||||
...seed,
|
||||
description: seed.description
|
||||
? `${seed.description}\n\n\`${item.stableId ?? ''}\``
|
||||
: `\`${item.stableId ?? ''}\``,
|
||||
});
|
||||
outcomes.push({ stableId: item.stableId, outcome: 'created' });
|
||||
} catch (err) {
|
||||
outcomes.push({
|
||||
stableId: item.stableId,
|
||||
outcome: 'failed',
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
return outcomes;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Note: der "stableId im description einbetten"-Trick ist Pragmatik für T1. T2 führt eine proper `templateStableId` Spalte ein wenn wir mehr Module seeden.
|
||||
|
||||
---
|
||||
|
||||
## Dateien (neu / modifiziert in T1)
|
||||
|
||||
**Neu:**
|
||||
- `packages/shared-ai/src/agents/templates/calmness.ts`
|
||||
- `apps/mana/apps/web/src/lib/data/ai/agents/seed-registry.ts`
|
||||
- `apps/mana/apps/web/src/lib/modules/meditate/seed.ts`
|
||||
|
||||
**Modifiziert:**
|
||||
- `packages/shared-ai/src/agents/templates/types.ts` — generalisierter Shape
|
||||
- `packages/shared-ai/src/agents/templates/index.ts` — Calmness exportieren
|
||||
- `packages/shared-ai/src/agents/templates/research.ts`, `context.ts`, `today.ts` — `category: 'ai'`, `icon`, `version: '1'` nachreichen
|
||||
- `apps/mana/apps/web/src/lib/data/ai/agents/apply-template.ts` — Seeds-Schritt
|
||||
- `apps/mana/apps/web/src/routes/(app)/agents/templates/+page.svelte` — Detail-Panel zeigt "Seeds" Sektion
|
||||
- `apps/mana/apps/web/src/lib/data/ai/missions/setup.ts` — lädt `meditate/seed` beim startMissionTick damit der Handler registriert ist
|
||||
|
||||
---
|
||||
|
||||
## Risiken + Mitigation
|
||||
|
||||
| Risiko | Mitigation |
|
||||
|---|---|
|
||||
| Seed-Handler-Registrierung zur Laufzeit nicht garantiert (z.B. Lazy-Loading bricht Registry) | T1: Handler werden in `startMissionTick` explizit eingebunden (`import '$lib/modules/meditate/seed'`). T2: Module-Registry aufbohren. |
|
||||
| Seed schreibt in encrypted-Tabelle ohne User-Master-Key | Seed-Handler ruft die Modul-Stores (die `encryptRecord` schon nutzen) — Crypto-Pfad unverändert. Funktioniert nur bei unlocked vault (wie alle Writes). |
|
||||
| Stable-ID-Hack via description ist hässlich | T1 akzeptiert das als pragmatisch. T2 führt echte Spalte + Dexie-Migration ein. |
|
||||
| Template-Versionierung ohne Update-Logik | Version wird gespeichert, aber keine Update-UI in T1. Vorbereitung für T4. |
|
||||
|
||||
---
|
||||
|
||||
## Nicht-Ziele T1
|
||||
|
||||
- **Keine Kategorie-UI** (T3)
|
||||
- **Keine Update-Detection** (T4)
|
||||
- **Keine User-Created Templates** (T5)
|
||||
- **Keine echte Dexie-Spalte für stableId** (T2) — T1 nutzt description-Trick
|
||||
- **Kein "Template anwenden v2" Upgrade-Pfad** (T4)
|
||||
|
||||
---
|
||||
|
||||
## Offene Fragen
|
||||
|
||||
1. **Seed-Schemas typisieren?** Heute sind Seeds `data: unknown`. Jeder Handler casted intern. Alternative: jedes Modul exportiert seinen Seed-Typ, Template referenziert ihn. Tight-coupling vs. Flexibilität. → T2 Entscheidung.
|
||||
2. **Scene-Apps validieren?** Wenn ein Template eine `appId: 'foo'` referenziert die es nicht gibt, erscheint ein broken Tab. T2: Warnings auswerfen statt silently leere Tab. → T2.
|
||||
3. **Delete-Cascade?** Wenn User die Calmness-Scene löscht, sollen die 2 Presets weg sein? Meine Tendenz: nein — Presets sind "Vorschläge", User bewertet selbst ob sie die behalten will. Scene ist Layout, Seed ist Inhalt.
|
||||
Loading…
Add table
Add a link
Reference in a new issue