Adds a one-tap voice recorder at the top of the Dreams module. Speak
your dream right after waking, the audio is sent through a server-side
proxy to mana-stt, and the transcript appears in the entry as soon as
it lands.
- New /api/v1/dreams/transcribe SvelteKit server route proxies the
upload to mana-stt with the server-held MANA_STT_API_KEY (never
exposed to the browser); validates mime, size, missing config
- Adds MANA_STT_URL + MANA_STT_API_KEY to the mana-web env config in
generate-env.mjs (private, not PUBLIC_ prefixed)
- New DreamRecorder class wraps MediaRecorder with reactive
$state — status, elapsed timer, error; supports cancel
- dreamsStore.createFromVoice creates a placeholder dream with
processingStatus='transcribing' and kicks off the upload
- dreamsStore.transcribeBlob uploads, writes the result back into
the dream, falls back to processingStatus='failed' on errors
- Adds processingStatus + processingError + audioDurationMs to
LocalDream; backwards-compatible defaults in toDream
- Mic button in ListView with idle / requesting / recording
(with elapsed timer + pulsing red) / stopping states
- Cancel button discards the in-flight recording
- Transcribing badge ●●● + failed ! badge on dream rows
- Inline editor shows live transcription status; while it's running
and the user hasn't typed anything, the transcript folds into the
edit buffer as soon as it arrives
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PublicRsvpList: collapse onMount/onDestroy/$effect into a single
$effect with proper cleanup; eliminates the redundant interval init
paths and the dead else-branch
- DetailView: re-push the snapshot to mana-events when a published
event is opened, so any earlier fire-and-forget that lost a write
silently self-heals
- New _eventsTombstones queue (db version 8): when unpublish/delete
fails to remove the server snapshot, queue (eventId, token) for
retry; ListView drains the queue on mount with capped attempts
- Public /rsvp/[token]: detect Accept-Language in +page.server.ts,
pass lang to the page, and use a small inline DE/EN dict in
strings.ts — no svelte-i18n on the public route
New unified-app module under apps/mana/apps/web/src/lib/modules/cycles.
Adds three Dexie tables (cycles, cycleDayLogs, cycleSymptoms) in db v7,
SYNC_APP_MAP entry, app-registry registration, branding (icon + entry +
APP_URLS), and a /cycles route.
Includes phase derivation (menstruation/follicular/ovulation/luteal),
heuristic next-period and fertile-window prediction (rolling mean over
last 6 cycles), 10 default symptoms, and 33 unit tests covering the
pure utilities.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New data-layer-listeners.ts wires the fire-and-forget CustomEvents the
sync engine and quota helpers emit into the rest of the app:
- mana:storage-quota-exceeded
→ toast.info / .warning / .error depending on whether the recovery
cleanup succeeded, and a Sentry capture for the failure cases.
- mana:sync-telemetry
→ push:error / pull:error are routed to captureException with the
error category as a tag. Auth and network errors are downgraded to
console.warn so they don't drown Sentry in expected token blips.
→ apply:malformed-drop becomes a captureMessage warning.
→ success events log to console.debug only when import.meta.env.DEV.
- Tombstone cleanup loop
→ cleanupTombstones() runs once on idle after boot, then every 24h.
Errors caught locally and reported via captureException with a
'tombstone-cleanup' tag. Soft-deleted rows older than 30 days are
hard-purged so the IndexedDB doesn't grow unbounded.
Wired into the root layout's onMount: installDataLayerListeners()
returns a dispose function that removes both window listeners and
clears the cleanup interval.
Closes the audit's "no telemetry" + "no quota handling" + "tombstone
cleanup helper exists but unused" trio in one shot.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SymbolsView:
- Sort tabs (Häufigkeit / A-Z / Zuletzt) above the cloud
- More dramatic font scaling using sqrt easing for visual hierarchy
- "?" badge on symbols without a personal meaning, dimmed until hover
- "Zuletzt" sort shows the most recent dreamDate per symbol
- A-Z and Zuletzt switch the cloud to a vertical list layout
- Hides symbols whose count dropped to zero (e.g. after merge)
SymbolDetailView:
- Auto-save with 500ms debounce + transient "Gespeichert" hint
- Co-occurring chips are clickable and navigate to that symbol's detail
- Dream refs are clickable buttons; ListView passes onOpenDream so a
click jumps back to the timeline and opens the dream for editing
- Manual merge UI: "Zusammenführen…" button reveals a select with all
other symbols, confirmation dialog before merging
- Re-initializes edit buffer when navigating between symbols (lastInitId
guard instead of one-shot initialized flag)
Helpers:
- getLastUsedBySymbol returns a Map of symbol → most recent dreamDate
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New Hono+Bun service at services/mana-events on port 3065 with two
schemas in mana_platform: events_published (snapshots) and public_rsvps
(unauthenticated responses), plus a per-token hourly rate-limit bucket.
- Host endpoints (JWT) for publish/update/unpublish/list-rsvps
- Public endpoints for snapshot fetch + RSVP upsert with rate limiting
- New /rsvp/[token] page outside the auth gate, SSR-loads the snapshot
- Client store wires publishEvent/unpublishEvent to the server, syncs
snapshot updates after edits, and deletes the snapshot on event delete
- DetailView polls GET /events/:id/rsvps every 30s while open and lets
hosts import a public response into their local guest list
- generate-env, setup-databases.sh, .env.development, hooks.server.ts,
package.json wired for local dev
Adds a Symbols view to the Dreams module — the long-term differentiator
that lets users build a personal symbol vocabulary instead of relying
on generic dream-dictionary entries.
- New view-mode tabs (Träume / Symbole) at the top of the Dreams view
- SymbolsView: wordcloud-style list of all symbols sized by frequency,
with name search and inline color dots
- SymbolDetailView: editable name + personal meaning + color picker,
mood distribution bars, co-occurring symbols, and chronological
list of all dreams that reference the symbol
- dreamsStore.updateSymbol: rename propagates to all referencing dreams,
collisions auto-merge with the existing symbol
- dreamsStore.deleteSymbol: removes the symbol from all dreams
- dreamsStore.mergeSymbols: rewrites references and sums counts
- New query helpers: getDreamsWithSymbol, getMoodDistribution,
getCooccurringSymbols
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates DATA_LAYER_AUDIT.md to reflect the actual state after the
seven-commit audit pass. All critical (🔴) and high-priority (🟡)
items from the original audit are now closed; remaining 🟢 items are
listed in a Backlog section with clear next steps.
Status table at the top maps each sprint to its commit hash so the
audit doc is now self-referential — anyone reading it can jump
directly to the change that fixed each item.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sprint 4.1 — per-table sync apply lock
Replaces the global _applyingServerChanges boolean with a Set of
currently-applying table names (beginApplyingTables / isApplyingTable).
applyServerChanges now scopes the lock to exactly the tables it touches,
so a user typing into chat while todo is syncing no longer has their
write silently dropped from _pendingChanges. The legacy single-flag API
is kept as a thin shim for backward compatibility.
Sprint 4.2 — IndexedDB quota handling
- quota-detect.ts (no Dexie deps, importable from database.ts):
isQuotaError() across browsers + Dexie wrapped errors,
notifyQuotaExceeded() dispatches a CustomEvent the UI can subscribe to.
- quota.ts (re-exports detect helpers + adds db-aware bits):
cleanupTombstones() hard-deletes old soft-deleted rows to reclaim space,
withQuotaRecovery() wraps a write op with one cleanup-and-retry pass.
- applyServerChanges wraps each per-table transaction in a quota
recovery loop. A full DB no longer crashes the pull.
- The Dexie creating/updating hooks now write _pendingChanges via
trackPendingChange(), which catches QuotaError on the fire-and-forget
promise and surfaces the event instead of silently losing the entry.
Sprint 4.3 — sync telemetry events
New sync-telemetry.ts emits a window CustomEvent for every push/pull
lifecycle transition: push:start/ok/error, pull:start/ok/error,
apply:malformed-drop, apply:done. Errors carry a coarse category
(network/auth/http-5xx/http-4xx/parse/unknown) and durations are
measured in ms. No record contents are emitted — safe to forward to
Sentry / a debug HUD without leaking PII.
Sprint 4.4 — indexed queries on hot dashboard paths
Three cross-app dashboard widgets that previously full-scanned every
task / time block on every render now use indexed range queries:
- useTodayTasks → .where('dueDate').belowOrEqual(endOfToday)
- useUpcomingTasks → .where('dueDate').between(start, end)
- useUpcomingEvents → .where('startDate').between(now, future)
useFavoriteContacts hits the indexed isFavorite column directly (with
a number-or-boolean compound key for legacy / fresh records).
Verified: 20/20 tests in sync.test.ts still passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New 'events' module for planning gatherings with guest lists and RSVPs,
distinct from the personal calendar. Events surface in the calendar via
TimeBlock with sourceModule='events'. Guests, RSVPs and a publish stub
work fully local-first; the public RSVP server lands in Phase 1b.
- Filter tabs (All / Lucid / Nightmare / Recurring) above the dream list
- Symbol chips in the insights ribbon are clickable to filter the list
- Symbol chips on each dream row are clickable too, with active state
- Editor exposes dreamDate, bedtime and wakeTime via native pickers
- Sleep quality star rating in the editor (1–5, toggleable)
- Recurring-dream toggle alongside the lucid toggle
- Recurring badge on dream rows
- Dream row converted from <button> to div role=button so nested chip
buttons are valid HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new Dreams module to the unified Mana app for capturing dream
journal entries with mood, lucid status, recurring symbols, and
timeline insights. Founder-tier gated for now.
- Dexie schema v5 with dreams, dreamSymbols, dreamTags
- Mutation store with auto symbol counting on create/update/delete
- ListView with quick capture, inline editor, mood picker, lucid
toggle, monthly grouping, insights ribbon, context menu
- Workbench registration with note → dream drop transform
- New 'dream' DragType, dreams app icon, mana-apps catalog entry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Package uses moduleResolution: NodeNext which requires explicit .js extensions on relative ESM imports. Without these, prepare/build failed and broke pnpm install for the whole monorepo.
The implicit-any errors on (table) callbacks were cascading from the broken imports — they resolve once the modules import correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The lockfile had grown five (!) different vitest versions over time:
1.6.1, 2.1.9, 3.2.4, 4.1.2 and 4.1.3 — pulled in by various
packages that pinned outdated majors. The mismatch produced the
classic "createDOMElementFilter not found" startup crash because
hoisted @vitest/utils@3.x was loaded by the nested @vitest/runner@4.x.
Bumped every package.json that pinned an old vitest:
- apps/manavoxel/apps/web (^4.1.0 → ^4.1.2)
- apps/matrix/apps/web (^4.1.0 → ^4.1.2)
- apps/memoro/apps/server (^3.0.0 → ^4.1.2)
- apps/nutriphi/packages/shared (^2.1.8 → ^4.1.2)
- packages/qr-export (^3.0.5 → ^4.1.2)
- packages/shared-llm (^2.0.0 → ^4.1.2)
- packages/shared-storage (^4.1.0 → ^4.1.2)
- packages/spiral-db (^1.6.1 → ^4.1.2)
- packages/test-config (^3.0.0 → ^4.1.2)
- packages/wallpaper-generator (^3.0.5 → ^4.1.2)
After a clean pnpm-lock.yaml regenerate, every @vitest/* sub-package
resolves to a single version (4.1.3, picked by semver) — no more
duplicates between hoisted and nested node_modules.
Verified by running:
pnpm --filter @mana/web vitest run src/lib/data/sync.test.ts
→ 20/20 tests passing in 217ms
pnpm --filter @mana/web vitest run src/lib/data/time-blocks/recurrence.test.ts
→ 19/19 tests passing in 198ms
Pre-existing test failures in base-client.test.ts (German error
strings vs english assertions), dashboard.test.ts (widget count
drift), and content/help/index.test.ts (svelte-i18n locale not
initialised in test env) are unrelated and tracked separately.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Type-aware linting via @typescript-eslint/projectService loads the entire TS program into memory; with 27+ modules in the unified app the default 4GB heap OOMs. Bump explicitly in the lint script.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- shared-branding/mana-apps: drop duplicate `mana` and obsolete `inventar` URL entries
- web/app.d.ts: move __BUILD_HASH__/__BUILD_TIME__ ambient declarations into declare global so they survive module-scoping
- web: remove dead supabase template (routes/api/example, lib/server/middleware) — locals.session no longer exists post auth migration
- habits/queries: drop stale Record<string,string> cast on LocalHabit (legacy emoji field)
- shared-stores/toggle-field: cast to Dexie UpdateSpec instead of Partial<T> for newer dexie types
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ManaCore→Mana rename converted both `manaCoreSvg` and the existing
`manaSvg` to the same identifier, leaving two `const manaSvg = ...`
declarations and two `mana:` keys in APP_ICONS. This broke any consumer
of the package with a duplicate-symbol error at SSR build time.
Removed the legacy ManaCore icon (4-circle quartet) and kept the
current Mana brand icon (single droplet). Removed the duplicate
APP_ICONS entry as well.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New SyncChange / FieldChange / SyncOp types replace `any[]` in
applyServerChanges. The wire format is now self-documenting and
TypeScript catches malformed callsites at compile time.
- isValidSyncChange() validates incoming server payloads at the boundary:
malformed entries are dropped with a single warn log, valid ones are
applied. A bad row from the server can no longer corrupt IndexedDB.
Hand-rolled type guards keep us free of a runtime-validation dep.
- applyServerChanges() and readFieldTimestamps() are now top-level
exports (extracted out of createUnifiedSync's closure) so they can be
imported directly by tests. Behaviour is unchanged — the closure
variant inside the sync manager just resolves the module-level
symbol now.
- New sync.test.ts covers:
* pure isValidSyncChange and readFieldTimestamps cases
* field-level LWW: server-newer wins, split outcome when local-newer
on one field and server-newer on another
* insert with __fieldTimestamps stamping
* soft-delete LWW guard
* malformed-entry drop with valid entries surviving
* sync-loop guard: server-applied writes don't generate _pendingChanges
- fake-indexeddb added as devDependency for the integration tests.
Note: the monorepo's vitest install is currently tangled across mixed
@vitest/* package versions in the lockfile, so `pnpm test` fails before
reaching this file. The tests are written to pass on any vitest 4.x once
that's untangled — needs its own dedicated cleanup pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- calendar/types: replace duplicate recurrenceRule with recurrenceDate on CalendarEvent; map it in timeBlockToCalendarEvent
- recurrence: drop stale Record casts now that LocalTimeBlock types isRecurrenceException and recurrenceDate
- todo: route recurrenceRule through TimeBlock in createTask/updateTask, load it from block in useTaskForm; accept labelIds via metadata; remove stale projectId casts
- calendar/events: include linkedBlockId/parentBlockId/recurrenceDate in createDraftEvent
- habits: drop unused db / LocalTimeBlock imports
- eslint-config: disable consistent-type-imports (parser conflict with .svelte.ts files)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous startup.sh checked colima status via `colima status | grep running`
and, if that failed, ran `colima stop --force` unconditionally before starting.
This is destructive: a transient status mis-detection can kill a healthy running
VM, and the subsequent start often hangs because of leftover locks/processes.
Triggered today during the ManaCore→Mana rename: reloading the docker-startup
LaunchAgent ran the script, which falsely concluded colima was down, killed the
running VM, and left 12 zombie limactl processes plus a stale disk lock symlink.
The whole production stack (incl. Forgejo) was offline until manual cleanup.
Changes:
- Use `docker info` as the readiness check instead of `colima status` —
it directly tests the thing we care about (docker socket reachable)
- Only do cleanup work when we actually need to start; never SIGKILL a
running VM as a "precaution"
- When we do need to start: reap any zombie limactl/colima processes from
prior failed runs, and clear the stale disk-in-use lock if no process
actually holds it
- Verify successful start with `docker info`, not `colima status`
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Defense-in-depth on top of the existing application-level WHERE clauses:
- Migrate() now ENABLE + FORCE row level security on sync_changes and
installs a policy that gates rows on current_setting('app.current_user_id').
FORCE makes the policy apply to the table owner too, so the application
role used by mana-sync cannot bypass it regardless of grants.
- New withUser(ctx, userID, fn) helper opens a transaction and calls
set_config('app.current_user_id', userID, true) before running fn.
Empty userIDs are rejected up-front so an unauthenticated request can
never reach the database with an empty RLS scope (which would match
every row).
- RecordChange / GetChangesSince / GetAllChangesSince all run inside
withUser. WITH CHECK on the policy double-validates the user_id column
on insert against the active session, so a future code path that
forgets the WHERE clause cannot leak data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Single source of truth for the active user via data/current-user.ts;
layout pushes authStore.user.id into it on every auth state change.
- Dexie creating-hook auto-stamps userId from getEffectiveUserId(); the
updating-hook strips userId from modifications so records are
effectively user-immutable after creation.
- BaseRecord gains an optional userId so module types inherit it without
per-module declarations. All hardcoded 'guest'/'local' fallbacks in
module type-converters and session timer stores are deleted; the dead
userId field is removed from the public view types where it was
unused (Task, Conversation, Template, Deck, Plant, Contact, etc.).
- New guest-migration.ts: on first authenticated session, walks every
sync-tracked table, deletes guest-owned records and re-adds them so
the creating-hook re-stamps with the real user id and produces fresh
insert pending-changes with the full payload. Stale guest pending-
changes are cleared up-front.
- Drive-by: root onMount now returns its cleanup synchronously; the
previous async form silently dropped the cleanup callback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1 (PWA) fully implemented and verified:
- All 29 ListViews, 17 DetailViews, 14 Modals responsive
- Build successful, no new type errors
- Checkboxes marked done, completion date added
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ListViews (25 remaining modules):
- All module ListViews now have responsive container padding (p-3 sm:p-4)
- All interactive items have min-h-[44px] touch targets on mobile
- Picture/Moodlit grids: grid-cols-2 on mobile, grid-cols-3 on desktop
DetailViews (17 modules):
- All DetailViews have reduced padding on mobile (0.75rem vs 1rem)
- All buttons, inputs, selects have min-height: 44px on mobile
Modals (14 components):
- Shared Modal.svelte: bottom-sheet pattern on mobile (slides up from bottom)
- 13 app-specific modals: same bottom-sheet treatment
- Reduced padding, larger close buttons, max-h-[95vh] on mobile
Shared UI components:
- GlobalSpotlight: bottom-sheet on mobile, prevents iOS zoom, hides keyboard hints
- PillDropdown: full-width bottom-sheet on mobile with backdrop
- AppDrawer: 44px touch targets on buttons and search
- TagStrip: 44px min-height on all pill buttons
- ToastContainer: larger touch targets, safe-area positioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cross-Module Drag & Drop:
- WeekView day columns accept 'task' and 'habit' drops
- Dropping a task auto-schedules it on that day (creates TimeBlock)
- Dropping a habit creates a logged block on that day
- HabitTile now has dragSource (long-press to drag)
Activity Feed:
- ActivityFeedWidget shows the 10 most recently updated timeBlocks
- Shows type icon, title, action label (running/completed/planned), time ago
- Registered as 'activity-feed' dashboard widget
- i18n keys added (de + en)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Generate PWA icons (192x192, 512x512, apple-touch-icon) from favicon
- Add Apple PWA meta tags, theme-color, and viewport-fit=cover to app.html
- Upgrade caching preset to 'full' (adds font + CDN caching)
- Add manifest shortcuts for Dashboard, Todo, Calendar, Chat
- Switch registerType to 'prompt' for user-controlled updates
- Add OfflineIndicator component (offline banner + sync status badge)
- Add PwaUpdatePrompt component (detects waiting SW, skip-waiting on confirm)
- Add networkStore for online/offline + sync status tracking
- Wire sync manager status into networkStore for pending change counts
- Update offline page text to reflect local-first architecture
- Add mobile/desktop app strategy doc and Tauri v2 implementation plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Drag & drop: external timeBlocks (tasks, habits, timeEntries) can now be
dragged and resized directly in calendar views via updateBlock()
- Conflict detection: ConflictWarning component shows overlapping timeBlocks
in EventForm and QuickEventPopover in real-time
- Plan vs Reality: startFromScheduled() creates linked logged blocks from
scheduled blocks, EventCard shows checkmark badge for linked blocks,
linkBlocks() now validates kind compatibility
- Timeline view: full-page /timeline route with chronological day view,
day navigation, type filters, duration stats, live indicators, and
connected dot+line visualization
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Habits:
- Add defaultDuration field to Habit type and domain model
- HabitForm: duration input (minutes) alongside target-per-day
- Logged habits with defaultDuration auto-set endDate on their TimeBlock
Todo:
- Task DetailView: "Kalender planen" button to schedule tasks on calendar
- Creates/updates/removes TimeBlock via scheduledBlockId
- Date + time inputs with one-click unschedule
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CalendarEventsWidget now shows all timeBlock types with type icons
and live indicators (was only showing calendar events before)
- Added day_timeline i18n keys in all 5 languages (de/en/es/fr/it)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename the music module from "Mukke" to "Music" across the entire
codebase: API routes, web app module, shared packages, search provider,
dashboard widgets, i18n keys, app registry, and route paths.
Add POST /api/v1/music/cover/upload endpoint that uploads cover art
images through mana-media for deduplication, thumbnails, and Photos
gallery visibility.
Dexie table names (mukkePlaylists, mukkeProjects) kept unchanged to
preserve existing IndexedDB data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Chronological day timeline showing all timeBlocks for today across all
modules (events, tasks, habits, time entries). Shows summary stats
(total time, counts per type), live indicators for running timers,
and habit icons. Links to calendar for full view.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a central `timeBlocks` table that owns the time dimension
(start, end, recurrence, live status) for all modules. Calendar, times,
habits, and todo modules keep only domain-specific data with a
timeBlockId reference. The calendar becomes a universal time view
showing events, tasks, habits, and time entries from all modules.
Key changes:
- New `$lib/data/time-blocks/` module (types, service, queries, collections)
- Dexie schema v3 with timeBlocks table + migration from existing data
- Calendar events store creates TimeBlock + LocalEvent pairs
- Times timer uses TimeBlock.isLive instead of LocalTimeEntry.isRunning
- Habits logHabit creates point-event TimeBlocks (with optional duration)
- Todo scheduled tasks create TimeBlock via scheduledBlockId
- Calendar views filter by blockType, show items from all modules
- All calendar views use getItemColor() for cross-module color support
Also includes mukke → music module rename.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace $effect + liveQuery().subscribe() with useLiveQueryWithDefault
in 6 dashboard modules (todo, calendar, contacts, habits, notes, finance)
to prevent cascading $state writes exceeding Svelte 5 effect depth limit
- Defer checkInlineSuggestion in Dexie hooks via setTimeout to avoid
cross-table reads within a single-table transaction scope
- Add 5s timeout to trySSO fetch calls so app loads in guest mode when
mana-auth is unreachable
- Fix guestMode reactivity by declaring with $state()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Picture, Contacts, Planta, Storage, and NutriPhi image uploads now go
through mana-media instead of directly to S3. This enables SHA-256
deduplication, automatic thumbnail generation, EXIF extraction, and
makes all images visible in the Photos gallery. Non-image files (PDFs,
audio, docs) continue to use shared-storage directly. SVG avatars in
Contacts also stay on shared-storage since Sharp can't process SVGs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add curated icon registry (73 Phosphor icons, 8 categories) in shared-icons
- Add DynamicIcon atom and IconPicker molecule in shared-ui
- Migrate habits module from emoji strings to Phosphor icon names
- Add Dexie version(2) migration for emoji→icon field rename
- Replace inline SVGs in habits with Phosphor components
- Add drag-and-drop photo upload to Photos workbench ListView
- Add blob: to CSP img-src for upload previews
- Add dev:media script and include mana-media in dev:manacore:servers
- Add ./toast export to shared-ui package.json
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Card-based layout for each automation with clear visual hierarchy
- Colored flow chips (WENN=blue, FILTER=amber, DANN=green) replacing
hard-to-read inline text
- Clearer step-based create form with badge labels per section
- Better suggestion cards with icon, accept/dismiss buttons
- Toggle switch, name, and flow on separate lines
- Delete button only visible on hover
- Consistent spacing and typography
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>