Commit graph

3161 commits

Author SHA1 Message Date
Till JS
db4dd437bd feat(api): MCP server endpoint — expose AI tools to external clients
Mount an MCP (Model Context Protocol) server at /api/v1/mcp in the
unified Hono API. External clients like Claude Desktop, Cursor, and
VS Code Copilot can discover and call all 29 Mana tools via the
standard MCP protocol.

Architecture:
- WebStandardStreamableHTTPServerTransport for Bun/Hono compatibility
- AI_TOOL_CATALOG → MCP tool definitions with JSON Schema (via Zod)
- Stateful sessions with Mcp-Session-Id header
- Auth via existing authMiddleware (JWT or API key)

Phase 1 scope: tools/list returns all 29 tools with schemas,
tools/call acknowledges with descriptive messages. Phase 2 will add
actual DB reads/writes via sync_changes.

Usage:
  Claude Desktop config:
  {"mcpServers": {"mana": {"url": "http://localhost:3060/api/v1/mcp"}}}

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:37:52 +02:00
Till JS
827b252090 feat(settings): inline sync, my-data, and vault — delete all sub-routes
The three Settings sub-routes (/settings/sync, /settings/security,
/settings/my-data) were standalone pages with their own PageHeaders
that felt disconnected from the workbench settings app. Inline them
as section components so everything lives in one scrollable view:

- SyncSection.svelte (from /settings/sync) → embedded in Data tab
- MyDataSection.svelte (from /settings/my-data) → embedded in Data tab
- VaultSection.svelte (from /settings/security) → embedded in Security tab

Each component is the route content minus PageHeader/Breadcrumbs/
svelte:head. Toasts stay self-contained in each section.

- Delete all three route files + empty /settings/ directory tree
- Add 'vault' anchor to searchIndex (search "Verschlüsselung")
- Update external links: sync-status dropdown, sync billing banner,
  EncryptionIntroBanner → /?app=settings#cloud-sync / #vault

The routes/(app)/settings/ directory is now completely gone.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:30:33 +02:00
Till JS
56171ff13b fix(ai): resolve tool name + parameter drift between catalog and webapp
Some checks are pending
CI / Build mana-api-gateway (push) Blocked by required conditions
CI / Build mana-crawler (push) Blocked by required conditions
CI / Build mana-media (push) Blocked by required conditions
CI / Build mana-credits (push) Blocked by required conditions
CI / Build mana-web (push) Blocked by required conditions
CI / Build chat-backend (push) Blocked by required conditions
CI / Build chat-web (push) Blocked by required conditions
CI / Build todo-backend (push) Blocked by required conditions
CI / Build todo-web (push) Blocked by required conditions
CI / Build calendar-backend (push) Blocked by required conditions
CI / Build calendar-web (push) Blocked by required conditions
CI / Build clock-web (push) Blocked by required conditions
CI / Build contacts-backend (push) Blocked by required conditions
CI / Build contacts-web (push) Blocked by required conditions
CI / Build presi-web (push) Blocked by required conditions
CI / Build storage-backend (push) Blocked by required conditions
CI / Build storage-web (push) Blocked by required conditions
CI / Build telegram-stats-bot (push) Blocked by required conditions
CI / Build food-backend (push) Blocked by required conditions
CI / Build food-web (push) Blocked by required conditions
CI / Build skilltree-web (push) Blocked by required conditions
Docker Validate / Validate Dockerfiles (push) Waiting to run
Docker Validate / Build calendar-web (push) Blocked by required conditions
Docker Validate / Build quotes-web (push) Blocked by required conditions
Docker Validate / Build todo-backend (push) Blocked by required conditions
Docker Validate / Build todo-web (push) Blocked by required conditions
Docker Validate / Build mana-auth (push) Blocked by required conditions
Docker Validate / Build mana-sync (push) Blocked by required conditions
Docker Validate / Build mana-media (push) Blocked by required conditions
Mirror to Forgejo / Push to Forgejo (push) Waiting to run
8 mismatches fixed between AI_TOOL_CATALOG and webapp module tools:

Tool name renames (webapp → catalog name):
- record_visit → visit_place (places)
- undo_last_drink → undo_drink (drink)
- location_log → get_current_location (places, catalog side)

Catalog parameter fixes (aligned to webapp execute functions):
- create_event: startIso/endIso → startTime/endTime + isAllDay/location/description
- create_note: title required→optional, content optional→required
- complete_tasks_by_title: titleSubstring → titleMatch
- create_place: add latitude/longitude (required) + category enum + address
- create_journal_entry: English mood enum → German mood enum

Webapp parameter additions:
- create_contact: add company + notes params (store already accepts them)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:18:51 +02:00
Till JS
299cf9cf72 chore: cleanup dead props, deps, dirs, and stale comments
- Remove empty dirs: modules/mana/, modules/subscription/, and 7
  empty route dirs (spiral, profile, themes, help, apps, mana, credits)
- Remove @mana/subscriptions from web app dependencies (never imported)
- PillNavigation: drop settingsHref, manaHref, allAppsHref/allAppsLabel
  props + their link-builder blocks (none are passed anymore; all system
  pages route via /?app=<id> deep-links now)
- Update layout comment to reflect current architecture

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:17:59 +02:00
Till JS
d40a61119e refactor(ai): dynamic tool registry — single-source catalog in shared-ai
Introduce AI_TOOL_CATALOG in @mana/shared-ai as the single source of truth
for all 29 tool schemas (17 propose + 12 auto). Both the webapp policy and
the server-side mana-ai planner now derive their tool lists from the catalog
instead of maintaining independent hardcoded copies.

- New: packages/shared-ai/src/tools/schemas.ts — catalog with ToolSchema type
- Rewrite: proposable-tools.ts — derived from catalog instead of hardcoded array
- Rewrite: services/mana-ai/src/planner/tools.ts — 277→30 lines (imports from catalog)
- Simplify: webapp policy.ts — derives AUTO/PROPOSE from catalog defaultPolicy

Adding a new tool now requires 2 files instead of 3-5:
1. Add schema to AI_TOOL_CATALOG (shared-ai)
2. Add execute function in the module's tools.ts (webapp)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:06:07 +02:00
Till JS
b4ce8523b0 feat(credits): merge subscription management into Credits & Abo
The standalone "Abonnement" workbench app (lib/modules/subscription/)
duplicated billing functionality that should live alongside credits.
Users saw two separate apps for the same domain.

Replace the placeholder SubscriptionPage in the Abo tab with the real
subscription management from the subscription module:
- Current plan status with cancel/reactivate
- Plan selection with billing interval toggle (monatlich/jährlich)
- Stripe checkout integration
- Invoice history (collapsed <details>)
- Stripe billing portal link

Delete:
- lib/modules/subscription/ (merged into credits)
- app-registry 'subscription' registration
- CreditCard icon import (no longer used)

The Credits & Abo app now has 5 tabs:
1. Übersicht — balance + recent transactions + quick-buy
2. Abo — current subscription + plan picker + invoices
3. Verlauf — full transaction table
4. Kaufen — one-time credit packages (Stripe)
5. Kosten — per-operation pricing breakdown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:51:31 +02:00
Till JS
3be4612f04 fix(mana-llm): google-genai v1.73 keyword-only Part.from_text()
google-genai >=1.70 changed Part.from_text() from positional to
keyword-only argument. The production container installed v1.73.1
and crashed on startup with "Part.from_text() takes 1 positional
argument but 2 were given".

Fix: Part.from_text(msg.content) → Part.from_text(text=msg.content)

Tested live: curl https://llm.mana.how/v1/chat/completions with
model=google/gemini-2.5-flash returns correct response.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:47:23 +02:00
Till JS
3ce8420bc1 fix: drop duplicate manaHref — Credits & Abo is the single billing entry
After merging /mana into the credits workbench app, both manaHref and
creditsHref pointed to /?app=credits, rendering two identical dropdown
entries ("Mana" + "Credits"). Drop manaHref so only the "Credits"
entry remains.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:40:51 +02:00
Till JS
659a7d9774 fix(mana-llm): add google-genai to requirements.txt for Docker builds
google-genai was in pyproject.toml but missing from requirements.txt.
The Dockerfile uses pip install -r requirements.txt, so the Google
provider never loaded in production. Now that the key is set and the
cloud tier upgraded to gemini-2.5-flash, the import fires on startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:40:30 +02:00
Till JS
c6c4d630fe refactor(subscriptions): compact row-based card layout
SubscriptionCard and PackageCard were large centered multi-cell cards
designed for a standalone pricing page. In the workbench context (narrow
card inside a carousel), they wasted too much vertical space for users
to compare plans at a glance.

Redesigned both as horizontal rows:
- Icon | name+mana | price | action — all in one line
- Badges (current/popular) inline next to the plan name
- No more 3-column internal grid with 70px min-height cells
- Clickable row replaces separate SubscriptionButton

SubscriptionPage:
- Drop the big centered header (icon + title + subtitle)
- Move Usage + Costs into a collapsed <details> section
- Section titles as small-caps labels
- Billing toggle at top, plans immediately visible

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:38:30 +02:00
Till JS
d83fc370a0 docs: update tool coverage table + server-side research + templates
Catches up all docs with the current state of the AI tool system.

services/mana-ai/CLAUDE.md:
- New v0.6 status section documenting NewsResearchClient,
  pre-planning research injection, config.manaApiUrl, and the full
  28-tool / 11-module inventory (17 propose + 11 auto).

apps/mana/CLAUDE.md:
- New "Tool Coverage" table in the AI Workbench section listing all
  tools per module with their policy (propose vs auto).
- New "Templates" subsection documenting the two-section gallery
  (agent vs workbench templates), the seed-handler registry, and
  the current handlers (meditate, habits, goals).
- Architecture cross-reference updated to include §23.

docs/architecture/COMPANION_BRAIN_ARCHITECTURE.md:
- §23.2 gains a "Server-Side Research (mana-ai, ab v0.6)" subsection
  explaining how NewsResearchClient mirrors the client-side research
  pre-step: same endpoints, same trigger regex, but HTTP-direct from
  the Docker network instead of SvelteKit-internal.

docs/plans/README.md:
- workbench-templates.md added to the roadmap table (T1 shipped).
- Multi-agent description updated to mention 28 tools + server-side
  web-research.
- Architecture cross-reference includes §23.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:35:40 +02:00
Till JS
2ead0f36df fix(subscriptions): single-column layout for workbench context
SubscriptionPage had responsive multi-column grids (up to 4 columns
on xl). In the workbench card context this created awkward layouts.
Switch to single-column throughout and narrow max-width to 40rem.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:34:36 +02:00
Till JS
be81d11dc3 feat(ai): SSE streaming for foreground Mission Runner
Enable real-time token streaming during the planner "calling-llm" phase
so the user sees live progress ("empfange Plan… 128 tokens") instead of
a static spinner. The parser still receives the full text once complete —
no partial-JSON risk.

Changes:
- Extract shared SSE parser from playground into @mana/shared-llm/sse-parser
- remote.ts: use stream:true when onToken callback is provided
- AiPlanInput: add optional onToken field (shared-ai)
- ai-plan task: pass onToken through to backend.generate()
- runner.ts: throttled (500ms) phaseDetail updates during streaming
- Playground: refactored to use shared SSE parser

Also includes: AI agent architecture comparison report (docs/reports/)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:32:43 +02:00
Till JS
8a0bf93699 chore(cloud-tier): upgrade default model gemini-2.0-flash → gemini-2.5-flash
gemini-2.0-flash is deprecated June 1 2026. gemini-2.5-flash has been
stable since Q1 2026 with similar pricing ($0.15/$0.60 per 1M tokens
vs $0.10/$0.40 — pricing table already had the entry).

Three files touched:
- packages/shared-llm/src/backends/cloud.ts — client default
- services/mana-llm/src/config.py — server default
- services/mana-llm/src/providers/google.py — Ollama→Gemini fallback
  map + constructor default + deduplicated model list

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:32:03 +02:00
Till JS
95e65bbdcb chore: remove /apps route — not needed
The standalone /apps page (AppsPage from shared-ui) is redundant in the
workbench model — apps are discoverable via the app picker and scene
management directly on the home screen.

- Delete routes/(app)/apps/+page.svelte
- Remove command menu "Alle Apps" entry
- Drop allAppsHref prop from PillNavigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:30:37 +02:00
Till JS
27ac5fc23e feat(credits): merge Credits + Mana subscription into one workbench app
The former /credits (balance, transactions, Stripe checkout, cost
breakdown) and /mana (subscription plans placeholder) were separate
pages covering the same billing domain. Merge into a single workbench
app "Credits & Abo" with 5 tabs:

1. Übersicht — balance cards + recent transactions + quick-buy
2. Abonnements — SubscriptionPage from @mana/subscriptions
3. Transaktionen — full transaction history table
4. Kaufen — Stripe-integrated package cards
5. Kosten — per-operation cost breakdown with category filter

Stripe redirect handling: Stripe returns to /?app=credits&success=true.
The deep-link handler opens the app and strips ?app; the ListView reads
?success / ?canceled from window.location.search on mount, shows the
appropriate toast, and cleans the URL via history.replaceState.

- Delete /credits/+page.svelte and lib/modules/mana/ (placeholder)
- Register workbench app id='credits' (Crown icon, amber)
- Replace mana app registration (no longer needed)
- Update all links: command menu, PillNavigation (manaHref + creditsHref
  both → /?app=credits), CreditsSection, CreditsWidget,
  TransactionsWidget, CompleteStep, sync-status, sync billing page,
  gift redeem page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:26:27 +02:00
Till JS
23b8cc13fb feat(ai-tools): server-side web-research + contacts for agents
Two major tool expansions — the Recherche-Agent and Today-Agent can
now research the web autonomously (no browser needed), and a future
Meeting-Prep agent can read + create contacts.

=== research_news (server-side execution) ===

The biggest addition: mana-ai can now call mana-api's news-research
endpoints (POST /discover + /search) directly, without a browser.

Infrastructure:
- services/mana-ai/src/planner/news-research-client.ts — full HTTP
  client with discover→search pipeline. 15s/30s timeouts. Graceful
  null on any failure (network, mana-api down, bad response) so the
  tick never crashes from research errors.
- config.manaApiUrl added (default http://localhost:3060); wired in
  docker-compose.macmini.yml as http://mana-api:3060 + depends_on
  mana-api with service_healthy condition.

Pre-planning research step (cron/tick.ts):
- Before the planner prompt is built, the tick checks if the
  mission's objective or conceptMarkdown matches research keywords
  (same RESEARCH_TRIGGER regex the webapp uses). When it matches:
  * NewsResearchClient.research(objective) runs discovery + search
  * Results are injected as a synthetic ResolvedInput with id
    '__web-research__' and a formatted markdown context block
  * The Planner then sees real article URLs/titles/excerpts and can
    reference them in create_note / save_news_article steps
  * Log line: "pre-research: N feeds, M articles"

Tool registration:
- research_news added to AI_PROPOSABLE_TOOL_NAMES + mana-ai tools.ts
  with params (query, language?, limit?). This lets the planner also
  explicitly propose a research step as a PlanStep (in addition to
  the pre-planning auto-injection).

=== create_contact ===

- Added to AI_PROPOSABLE_TOOL_NAMES + mana-ai tools.ts with params
  (firstName required, lastName/email/phone/company/notes optional).
- Contacts are encrypted at rest; server planner can plan the step
  but execution stays on the webapp (same as all propose tools).
  Full server-side contact resolution via Key-Grant is a future
  enhancement.
- get_contacts added to webapp AUTO_TOOLS so agents can inspect
  existing contacts without nagging (read-only, auto-policy).

Module coverage now:
   todo (5)   calendar (2)   notes (5)   places (4)
   drink (3)  food (2)       news (1)    journal (1)
   habits (3)  news-research (1)  contacts (1)

  11 modules, 28 tools total (17 propose, 11 auto).

Tests: mana-ai 41/41 (drift-guard passes), shared-ai type-check
clean, webapp svelte-check 0 errors, 0 warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:25:45 +02:00
Till JS
ae53e93b9a feat(mana): migrate subscription page to workbench app
Extract /mana route into lib/modules/mana/ListView.svelte. Register as
workbench app id='mana' with Crown icon (amber). The page shows the
SubscriptionPage component from @mana/subscriptions.

- Delete routes/(app)/mana/+page.svelte
- Update PillNavigation manaHref to /?app=mana

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:03:20 +02:00
Till JS
5d46aa19a0 refactor(help): drop standalone /help route, use workbench app
The help workbench module (lib/modules/help/ListView.svelte) already
renders the same HelpPage component with identical props. The
standalone route was redundant.

- Delete routes/(app)/help/+page.svelte
- Update PillNavigation helpHref to /?app=help

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:01:35 +02:00
Till JS
1266b583e4 feat(ai-tools): unlock create_note + create_journal_entry + habit tools for agents
Closes the three biggest tool-coverage gaps so the shipped agent
templates can actually do their job end-to-end. Before this, the
Recherche-Agent couldn't create notes (only edit), the Today-Agent
couldn't create journal entries, and no habit-related tool was
server-proposable at all.

shared-ai (proposable-tools.ts):
- create_note (notes) — key unlock: Recherche-Agent now creates
  per-source notes and the summary report.
- create_journal_entry (journal) — key unlock: Today-Agent proposes
  a poem as a journal entry with optional mood.
- create_habit (habits) — agent can suggest new habits.
- log_habit (habits) — agent can log a habit completion for today.

Organized the list with per-module section comments for readability
now that we're at 15 proposable tools.

mana-ai (planner/tools.ts):
- 5 new tool definitions with full parameter schemas:
  * create_note (title, content?)
  * create_journal_entry (content, title?, mood? enum)
  * create_habit (title, icon, color)
  * log_habit (habitId, note?)
- Drift-guard contract test passes (41/41) — confirms the mana-ai
  tool list is in sync with the shared-ai canonical set.

Webapp (policy.ts):
- get_habits added to AUTO_TOOLS (read-only; agent can inspect
  which habits exist without nagging the user for approval).
- list_notes added to AUTO_TOOLS (was already used in the reasoning
  loop but missing from the explicit auto-list; the planner default
  fell through to 'propose' which was wasteful for a read op).

Module coverage after this change:
   todo (5 tools)   calendar (2)   notes (5 incl. create)
   places (4)       drink (3)      food (2)
   news (1)         journal (1)    habits (3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:00:17 +02:00
Till JS
bc5c15096c feat(spiral): migrate to workbench app, delete standalone route
Extract the /spiral route into lib/modules/spiral/ListView.svelte
(same content minus the standalone PageHeader — the workbench card
provides its own chrome). Register as workbench app id='spiral' with
the Phosphor Spiral icon.

- Delete routes/(app)/spiral/+page.svelte
- Update command menu + PillNavigation spiralHref to /?app=spiral
- deep-link scheme works out of the box (/?app=spiral)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:58:25 +02:00
Till JS
0af1dd7ec6 feat(workbench): section deep-links + migrate profile & themes to workbench
Section deep-links: /?app=settings#ai-options now switches the Settings
ListView to the KI tab and scrolls to the ai-options anchor. ListView
reads the URL hash on mount and maps it to a category via the existing
searchIndex anchors. The AI-tier dropdown "KI-Einstellungen" link now
targets /?app=settings#ai-options instead of just /?app=settings.

Profile & Themes workbench consolidation — same pattern as Settings:
- Delete standalone /profile and /themes routes (redundant with the
  workbench apps registered in app-registry)
- Migrate all links: PillNavigation profileHref/themesHref, dashboard
  QuickActionsWidget, +layout theme-switcher "Alle Themes", and the
  scene context-menu "Hintergrund ändern"

Credits stays as a standalone route — no workbench app registered for it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:52:25 +02:00
Till JS
334c36a68e docs: document reasoning loop, research pre-step, debug log, new tools
Updates apps/mana/CLAUDE.md AI Workbench section with:
- Reasoning loop (5-round auto→propose chain)
- Cross-module proposal inbox in mission detail
- Kontext auto-inject
- Web-research pre-step (RSS via news-research)
- Debug log (local-only _aiDebugLog + AiDebugBlock panel)
- New proposable tools: save_news_article, list_notes, update_note,
  append_to_note, add_tag_to_note

Adds §23 to COMPANION_BRAIN_ARCHITECTURE.md covering the full
architecture: loop algorithm pseudocode, research pre-step rationale
(RSS over deep-research), kontext auto-inject privacy boundary,
debug log schema + UI + toggle mechanics, and new tool inventory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:50:21 +02:00
Till JS
9161c0b3ab feat(templates): two more non-AI templates + split gallery into two sections
Closes out T1 with three templates per category as discussed. The
gallery now renders agent-templates and workbench-templates as two
distinct labeled sections — the earlier implicit "everything's a
template for an agent" framing is gone.

Seed handlers (new):
- apps/mana/apps/web/src/lib/modules/habits/seed.ts — title-based
  idempotency (there's no description column on LocalHabit). If a
  non-deleted habit with the same title exists, the seed is skipped.
- apps/mana/apps/web/src/lib/companion/goals/seed.ts — title-based
  idempotency on companionGoals where status !== 'abandoned'.
- Both pulled in via side-effect imports in missions/setup.ts so the
  handler registry is populated before any apply.

New templates:
- 🏋️ Fitness (wellness) — scene body/habits/stretch/sleep + 3 habit
  seeds (Täglich 30min Bewegung, 3× Woche Training, 2L Wasser) + 1
  goal seed (3 Workouts pro Woche). No agent.
- 💻 Deep Work (work) — scene todo/calendar/notes/times + 2 habit
  seeds (1 wichtigste Aufgabe pro Tag, 4h Deep Work pro Tag) + 1
  goal seed (20h Deep Work pro Woche). No agent.

Gallery two-section layout:
- Title "Templates" (not "Agent-Templates") — broader framing.
- Section 1: "🤖 Agent-Templates" — filters ALL_TEMPLATES where
  category ∈ {'ai','delight'}: Recherche-Agent, Kontext-Agent,
  Today-Agent.
- Section 2: "🎨 Workbench-Templates" — filters to the rest:
  Calmness, Fitness, Deep Work.
- Each section gets a short intro paragraph so users understand the
  distinction before scanning the cards.
- Cards themselves unchanged; rendering extracted into a
  {#snippet templateCard(t)} shared between both sections.
- Per-category arrays computed once at module-load time (const in
  <script>); no per-render filter cost.

Result: each section has 3 templates, categorised by "does this
create an AI agent" rather than by use-case. Keeps the separation
honest — Agent-Templates set up autonomous work; Workbench-Templates
set up the user's own workspace.

Tests: shared-ai 26/26, webapp svelte-check 0 errors, 0 warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:45:40 +02:00
Till JS
4f76d3926e feat(workbench): ?app=<appId> deep-links into the active scene
After consolidating Settings into a workbench app, links from the
command menu, pill-nav, AI-tier dropdown, onboarding CTAs, and the
sub-route back-buttons had nowhere specific to go — they pointed at
`/` and dumped users at their home scene with no way to auto-open the
settings app.

- Home (+page.svelte) reads ?app=<id> on mount. If the id is a
  registered workbench app and not already in the active scene,
  addApp() it. Then scroll the carousel to that page. Strip the
  query out of history.replaceState so refresh doesn't re-open.
- Update all settings redirects (command menu, onboarding,
  AI-settings dropdown, settings/sync + settings/my-data back-links
  and breadcrumbs) to `/?app=settings`.

Unlocks: future deep-links to any app (profile, themes, spiral,
credits, …) without needing a standalone route. `?app=X&section=Y`
is the natural next step — left for when an app needs it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 01:10:10 +02:00
Till JS
a08e45ca16 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>
2026-04-16 01:07:41 +02:00
Till JS
a524997a2f refactor(tailwind): centralize @source list in @mana/shared-tailwind/sources.css
Each consuming app was duplicating eight @source directives with hand-
counted relative paths (../../../../../packages/…). The mana web app's
were off-by-one for months before anyone noticed, silently disabling the
scan for every shared-ui file.

Tailwind v4 resolves @source paths relative to the CSS file that declares
them, so we can drop the list once into packages/shared-tailwind/src/
sources.css. Consumer apps now just add one more @import next to themes.css:

  @import "tailwindcss";
  @import "@mana/shared-tailwind/themes.css";
  @import "@mana/shared-tailwind/sources.css";

New package.json export: "./sources.css". Drop the local paths from the
mana web app's app.css.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:59:33 +02:00
Till JS
fc028fa8f0 chore(lint): audit:theme-tokens guard against bare --muted / --theme-* drift
Three naming conventions had drifted through the monorepo (--muted, --theme-*,
--color-*). Only the last is defined in the Mana theme; the others silently
fell back to nothing and stopped tracking theme variants. Today's cleanup
migrated ~100 files, but nothing stopped the drift from creeping back.

- scripts/audit-theme-tokens.mjs scans ~3k source files and fails if any
  references a bare shadcn token or a --theme-* prefix, with an allowlist
  for known-literal module brand colors (news-research, agent templates)
- wire into pnpm script and lint-staged (runs once per commit touching
  *.{svelte,css}, ignores per-file args)
- design-ux.md guideline: fix stale --color-destructive entry (Mana uses
  --color-error), add explicit "never bare tokens" warning with examples

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:58:13 +02:00
Till JS
8a5d200c84 fix(ai): bump planner maxTokens 1024→4096 + teach prompt about the loop
Debug log from a "tag 4 notes" mission showed the planner's second-round
response truncated mid-step: it was proposing one add_tag_to_note per
listed note but ran out of tokens halfway through note #2. Parser
rejected the malformed JSON → loop exited with 0 staged, user saw
nothing to approve.

Raising maxTokens to 4096 fits ~15-20 step objects, which covers the
batch-tagging / batch-save pattern the reasoning loop is designed for.

Also updating the system prompt so the planner actually knows about
the loop it's running inside: read-only tools are announced as
auto-executing with outputs visible next turn, and a new rule makes
explicit that batch jobs must emit all write-steps in one plan (because
staging a propose-tool ends the turn). Step count raised 1-5 → 1-10.

Prompt snapshot tests still pass (they check structure, not text).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:55:18 +02:00
Till JS
8299bf004d feat(ai): reasoning loop — agent chains auto tools before asking for approval
The runner was one-shot: one planner call per iteration, no feedback
from tool outputs. "Lies alle Notizen und tagge sie" needed two manual
runs (list_notes, then tagging) because the planner never saw the
list_tasks output.

Now runMission loops up to MAX_REASONING_LOOP_ITERATIONS (5):

  loop: plan → classify steps by policy
        │
        ├─ auto  → execute inline, capture {message, data}, feed back
        │          as a synthetic ResolvedInput for the next planner call
        │
        ├─ propose → stage proposal, mark humanInLoop, EXIT after this round
        │            (human has to approve before we plan further — we don't
        │             know what they'll accept yet)
        │
        └─ none/0-steps → agent considers the task done, EXIT

Tool outputs become a ResolvedInput titled "Zwischenergebnisse (Runde N)"
so the planner sees them structured and labelled. StageOutcome gains
`autoData` + `autoMessage` so the loop can thread the executor's
payload back through without a second call.

AiDebugEntry now holds `plannerCalls[]` and `loopSteps[]` instead of a
single planner snapshot — so Debug-Panel shows every LLM round + every
auto-tool output, each collapsible. Summary chip shows "3× LLM · 4200ms
· 2× Auto-Tool" when a loop ran.

Side-effects for existing use cases:
- One-shot missions (single propose tool) behave identically (loop
  exits after round 1 with humanInLoop=true).
- "Tag all notes" missions now finish in a single run: loop iter 1
  runs list_notes auto, iter 2 stages N add_tag_to_note proposals,
  exits.
- Server-side mana-ai runner NOT touched — this is foreground-only
  for now; the server still runs one plan/tick.

All 8 runner.test.ts tests pass unchanged (the existing test suite
only exercises the single-step path, which is a subset of the loop).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:43:52 +02:00
Till JS
e440f13867 feat(workbench): welcome placeholder for the Home scene description
When the seeded default scene ("Home") has no description yet, the
empty contenteditable placeholder shows "Willkommen Zuhause im Mana
Hub" instead of the generic "Beschreibung hinzufügen…". Rename the
scene → generic prompt returns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:41:07 +02:00
Till JS
531190953f chore(theme): theme-track shared-auth-ui primaryColor + drop dead tailwind.config.js
shared-auth-ui components (PasskeyManager, SessionManager, TwoFactorSetup,
AuditLog, ChangePassword, SecurityOnboarding) take a primaryColor prop
that gets written as inline --primary-color on the component root. The
mana app was passing a literal "#6366f1" (indigo) everywhere, so the
Security tab and auth pages used a fixed indigo accent that ignored the
user's theme. Pass "hsl(var(--color-primary))" instead — the nested var
resolves live, so theme switches carry through.

tailwind.config.js in apps/mana/apps/web was fully vestigial:
- no @config directive in app.css, no reference from vite/svelte configs
- imported @mana/shared-tailwind/preset, which the package doesn't export
- only themes.css is exported, and it's loaded directly from app.css
Tailwind v4 with CSS-first config is the real setup. Delete the file
and remove its entry from SETUP.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:37:11 +02:00
Till JS
7822340ea0 feat(ai-agents): Template gallery — 3 ready-to-use agent bundles
First pass of the Multi-Agent discoverability UX. A new /agents/
templates route showcases pre-configured agents; clicking one creates
agent + scene + starter mission(s) as a single bundle. Addresses the
"blank form anxiety" + "user doesn't know what agents are for"
observations from the UX brainstorm.

Three templates for v1 (shared-ai/src/agents/templates/):
- 🔍 Recherche-Agent — reads sources one by one, writes a note per
  source, summarizes into a report. Manual-cadence mission; all
  writes propose so user curates.
- 🧭 Kontext-Agent — learns about the user via a weekly check-in.
  Reads kontext/notes/goals, asks 2-3 questions, proposes a diff-
  style context update. Weekly Sunday cadence.
- 🌅 Today-Agent — researches "on this day" history each morning,
  writes a 4-8 line German poem, proposes a journal note. Daily 7am
  cadence. A "delight" agent, not a productive one.

Each template packs (agent config, scene layout, starter mission):
- AgentTemplate type lives in @mana/shared-ai — pure data, no runtime
  imports. Adding a new template = drop a file in templates/ and
  extend ALL_TEMPLATES.
- Template-specific policies derive from the proposable-tool list so
  drift-guard catches divergence from the canonical set.
- Starter missions default to startPaused=true — user sees the
  mission ready-to-go and hits Play when ready. Prevents surprise
  autonomous work on first apply.

Applicator (data/ai/agents/apply-template.ts):
- Creates agent → scene (if template defines one) → missions in
  order. Agent failure = abort; scene/mission failures surface as
  warnings in the result without blocking.
- Duplicate-name handling: falls through to findByName, returns
  existing agent with wasExisting=true; scene is skipped in that
  case to avoid clone-proliferation.

Gallery page /(app)/agents/templates/+page.svelte:
- Three large cards side-by-side (stacks on mobile) with avatar /
  label / tagline / meta chips (Scene, N Missionen).
- Click opens detail panel with full description, scene preview
  (app-ids + widths), mission preview (title / objective / cadence),
  and override checkboxes (create scene, create missions, start
  active vs paused).
- Success panel shows what landed with warnings inline; CTA back to
  workbench.

Discoverability in /ai-agents module:
- Bar now has two buttons: "Aus Template" (primary, goto templates
  route) + "Eigener Agent" (secondary, opens the existing blank-form
  create mode).
- When only the default "Mana" agent exists, render a dashed promo
  banner at the top linking to the template gallery. Disappears as
  soon as the user has a second agent.

Tests: webapp svelte-check 0 errors, 0 warnings. shared-ai 26/26.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:36:39 +02:00
Till JS
4d9b16a683 feat(notes): list + update + append + add_tag tools for the AI
Makes the "read all notes and tag them #Natur/#Technologie/…" use case
fully functional. Four new ModuleTool entries in notes/tools.ts:

- list_notes(limit?, query?, includeArchived?) — auto, read-only. Returns
  id + title + excerpt so the planner can reference concrete notes
  without dumping full bodies.
- update_note(noteId, title?, content?) — proposable. Destructive full
  overwrite. Docstring nudges toward append_to_note when applicable.
- append_to_note(noteId, content) — proposable, non-destructive. Handles
  the trailing-newline separator so markdown stays clean.
- add_tag_to_note(noteId, tag) — proposable, idempotent, case-insensitive.
  Strips leading #, replaces spaces with _, skips if already present.
  Exactly the categorization primitive the user asked for.

All three writes are added to AI_PROPOSABLE_TOOL_NAMES so both the
webapp policy and mana-ai's boot-time drift guard agree (now 11 tools).
Mirrored in services/mana-ai/src/planner/tools.ts.

AiProposalInbox mounted on /notes so approvals land inline in the
notes module too (already appears in the mission-detail cross-module
inbox via the earlier commit).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:24:48 +02:00
Till JS
fdc1c0023a refactor(theme): migrate --theme-* tokens in shared-auth-ui
Third naming convention uncovered: six shared-auth-ui components
(PasskeyManager, SessionManager, TwoFactorSetup, AuditLog,
ChangePassword, SecurityOnboarding) use --theme-muted, --theme-border,
etc. These tokens are not defined anywhere in the Mana theme system —
they only rendered because of inline raw-channel fallbacks, so they
never tracked the active theme variant.

Map to the canonical --color-* tokens:
  --theme-background       → --color-background
  --theme-border           → --color-border
  --theme-foreground       → --color-foreground
  --theme-muted            → --color-muted
  --theme-muted-foreground → --color-muted-foreground
  --theme-surface          → --color-surface

Visible on the Security tab in the unified settings page, where the
inner passkey/session/2FA/audit cards can now pick up theme changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:16:39 +02:00
Till JS
cd22e42afc refactor(theme): migrate all remaining bare shadcn tokens to --color-*
Follow-up to the shared-packages migration. Covers 61 more files
across the mana web app (lib/components, lib/modules, routes) and
the same handful of packages, including surface / error / success /
warning tokens that were missed in the first pass.

Two patterns migrated:
1. hsl(var(--X[, raw-channels])) → hsl(var(--color-X[, raw-channels]))
2. var(--X, #hex)               → hsl(var(--color-X))
   (the hex fallback was only doing work because the CSS var was
   undefined; now that the theme resolves cleanly, the fallback is
   unnecessary and actively wrong — it never tracked the active theme)

Module-literal accents (news-research's #0891b2 / #10b981) left
untouched per the themes.css convention for brand-semantic colors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:56:59 +02:00
Till JS
115afea519 chore(dev): wire SearXNG + mana-search into dev:mana:all
News Research's web-search backend (mana-search → SearXNG) was missing
from the standard dev stack — a "Finden" click failed with a connect
error until the standalone services/mana-search/docker-compose.dev.yml
was started by hand.

- docker-compose.dev.yml: add `searxng` (Port 8080), config mounted
  read-only from the service tree. Reuses the shared mana-redis,
  no second cache instance needed.
- package.json: docker:up + docker🆙infra include searxng;
  dev:mana:servers spawns dev:search alongside the other 6 servers;
  dev:search now passes PORT=3021 + REDIS auth so it talks to the
  shared password-protected mana-redis instead of defaulting to a
  no-auth localhost:6379

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:31:29 +02:00
Till JS
fdd643f4b4 feat(news-research): RSS feed discovery, filter, and AI-context export
New sibling module to news/. Discovers topic-matched RSS feeds via
SearXNG (mana-search) or rel="alternate" probing of a site URL,
filters articles by keyword with a recency + title-match boost,
and exports the top hits as a markdown context block for the AI.

- API: /api/v1/news-research/{discover,validate,search,extract}
- Frontend: /news-research route + workbench ListView (compact card)
- Tool: research_news LLM tool (read-only, runs auto)
- Pin feeds → newsPreferences.customFeeds (encrypted) — covers the
  long-missing custom-RSS subscription gap; reading-list saves still
  go through articlesStore.saveFromUrl into the existing newsArticles
- shared-branding: new news-research entry + binoculars icon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:31:07 +02:00
Till JS
b768a0ffce refactor(shared-rss): extract RSS parsing + Readability into one package
news-ingester and apps/api both shipped their own copy of rss-parser
+ jsdom + Readability glue. Single source now in packages/shared-rss.
Adds discoverFeeds (rel=alternate + common-paths probe) and validateFeed
which News Research will use. JSDOM virtualConsole is silenced once,
in the package, instead of in two parallel call sites.

- packages/shared-rss: parse, extract, discover, validate
- services/news-ingester: drop local parsers, depend on @mana/shared-rss
- apps/api: drop @mozilla/readability + jsdom direct deps, use shared

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:30:44 +02:00
Till JS
5ae7f99fe1 fix(css): correct @source paths — Tailwind was scanning no shared packages
app.css lives at apps/mana/apps/web/src/app.css — five directory
levels below the repo root. All existing @source directives used
four ../ segments, resolving to apps/packages/... which does not
exist. Tailwind silently scanned nothing.

Consequence: arbitrary-value utilities only used inside shared
packages (e.g. bg-[hsl(var(--color-muted))] in GlobalSettingsSection)
were never generated. Standard utilities kept working because they
also appear in app sources, but the language / week-start / sounds
buttons in the settings Allgemein tab rendered transparent.

- Bump every @source to 5x ../ so it points into /packages
- Drop the non-existent shared-subscription-ui entry
- Add subscriptions and credits, whose .svelte files also use
  arbitrary-value classes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:17:15 +02:00
Till JS
e8077a44b4 docs: flesh out Multi-Agent plan shipping log + Team Workbench forward plan
The Multi-Agent Workbench shipped end-to-end (commits 1771063df through
7c89eb625). This commit turns the plan doc into a proper history + post-
mortem and captures the deferred Team-Workbench as its own forward plan
so the architectural breadcrumbs don't rot.

docs/plans/multi-agent-workbench.md:
- Status bumped to  Shipped; every phase checkbox flipped.
- Open-questions section rewritten with the decisions that were
  actually made (name-unique via store write-time check, per-source
  system principalIds, policy fully migrated, scene binding default-
  empty with smart suggestion).
- New "Shipping-Historie" table mapping each phase to its commit, the
  number of files touched, and the test outcome.
- New "Lessons Learnt + Follow-Up Ideen" with:
  * What went better than expected (L3 Actor cutover, getOrCreate
    instead of unique index, displayName caching)
  * Thin spots worth revisiting (avatar not on Actor, missing token
    counter for budget, no missions list on agent detail, no
    drag-reassign, scene binding doesn't drive filters yet)
  * Five deferred follow-up projects (team features, agent memory
    self-update, agent-to-agent messaging, meta-planner, per-agent
    encryption domains)

docs/plans/team-workbench.md (NEW):
- Full forward-looking plan for the deferred Team-Workbench.
- Two use-cases (human multi-user vs multi-agent sharing team
  context) with the observation that they share the same infra.
- Decision candidates table (still open — meant as T0 RFC fodder,
  not baked in).
- Architecture sketch with data-model deltas over the current
  single-user shape.
- Encryption subsection dedicated to the hardest problems: team-key
  wrapping per member (reuses Mission-Grant pattern), member-removal
  rotation (lazy vs eager), Zero-Knowledge-mode incompatibility.
- T0..T6 phasing (~7 weeks for a clean first-pass).
- Section "Wie Multi-Agent dafür den Weg geebnet hat" enumerating
  the four invariants the shipped Phase 0-7 deliberately preserved
  to make this plan cheap when it lands.

docs/plans/README.md (NEW):
- Index doc with the AI/Workbench roadmap as an ASCII flow so future
  contributors can locate themselves in the sequence without reading
  three 400-line plans first.

docs/future/AI_AGENTS_IDEAS.md:
- Header marks Point 1 (encrypted tables) as shipped via the Mission
  Grant plan; points 2-8 stay relevant. Cross-link to all three plan
  docs so this stays the go-to backlog.

services/mana-ai/CLAUDE.md:
- Design-context header expanded to link to all four related docs
  (arch §20-22, both shipped plans, forward team plan, ideas backlog).

No code changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:17:04 +02:00
Till JS
6da317d071 refactor(theme): migrate shared packages to --color-* token naming
Several shared-ui / shared-auth-ui / subscriptions / credits
components used shadcn-style bare CSS variables (--muted, --primary,
--foreground, etc.), but the Mana theme system standardized on
--color-*. The mismatch meant bg-[hsl(var(--muted))] classes
resolved to an invalid color and rendered transparent — most
visible on the Allgemein settings tab where language and week-start
buttons had no background.

Mechanical prefix across ~30 files. Two semantic renames:
- --destructive → --color-error (Mana uses "error" as the token name)
- --popover     → --color-card  (no popover token; card is the closest)

With shared packages on the correct naming, drop the shadcn-compat
alias shim from app.css.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:11:42 +02:00
Till JS
7c89eb625e feat(ai): workbench agent filter + proposal agent chip + docs (Phase 6+7)
Phase 6 — Multi-Agent observability:
- AI Workbench timeline gets a per-agent filter (dropdown with avatars)
  alongside module + mission. TimelineBucket gains agentId +
  agentDisplayName, projected off the bucket's first AI actor.
- Bucket header now leads with the agent's avatar + name (lookup via
  the live useAgents query so renamed agents reflect instantly) and
  falls back to Actor.displayName for deleted agents.
- AiProposalInbox card header replaces the generic Sparkle + "KI
  schlägt vor" with an agent chip "🤖 Cashflow Watcher schlägt vor"
  using the cached Actor.displayName. Ghost-agent label preserved
  via the cached displayName even when the agent record is gone.

Phase 7 — Docs:
- docs/architecture/COMPANION_BRAIN_ARCHITECTURE.md §22 added:
  data model, identity flow, tick gate order, Scene-Agent binding
  semantics, non-goals.
- services/mana-ai/CLAUDE.md status bumped to v0.5 (Multi-Agent
  Workbench) with the per-agent runner features + metrics listed.
- apps/mana/CLAUDE.md AI Workbench section rewritten to cover the
  Agent primitive, per-agent policy, scene lens, and the updated
  timeline header.

Multi-Agent rollout is code-complete end-to-end:
  Phase 0 Plan ✓  Phase 4 Policy-per-agent ✓
  Phase 1 Actor identity ✓  Phase 5 Agent UI + Scene lens ✓
  Phase 2 Agent CRUD ✓  Phase 6 Observability ✓
  Phase 3 Tick agent-aware ✓  Phase 7 Docs ✓

Tests: webapp svelte-check 0 errors, 0 warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:08:42 +02:00
Till JS
98668b69a2 fix(ai): swap web-research pre-step from deep-research → news-research RSS
Debug log on a "Recherchiere News über Adult Learning" mission showed
the deep-research pipeline (mana-search + LLM synthesis) returned 0
sources but reported success — planner then either hallucinated or
fell back to create_task. The webapp already has a documented
RSS-based research path in news-research/{discoverByQuery,searchFeeds}
that's faster, free (no credits), and matches the companion-flow
contract written in news-research/tools.ts: "research_news → save_news_article".

Now:
- Pre-step calls discoverByQuery + searchFeeds directly.
- Empty discovery / empty results throw an explicit error so the
  failure-injection branch surfaces it to the planner instead of
  silently feeding a "0 sources" success message.
- Injected ResolvedInput now carries explicit instructions ("rufe für
  jeden relevanten Artikel save_news_article auf — erfinde keine
  URLs") so the planner doesn't have to infer the next move.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:07:29 +02:00
Till JS
cda70b6a81 fix(css): alias bare --muted/--primary etc. to --color-* tokens
GlobalSettingsSection (and a few other shared-ui/auth-ui components)
reference shadcn-style bare CSS variables like --muted and --primary,
but this app standardized on --color-muted/--color-primary. The
mismatch meant classes like bg-[hsl(var(--muted))] resolved to an
invalid color → buttons in the Allgemein settings tab rendered
without a background.

Add one-way aliases in :root so the bare names resolve to the
color-prefixed ones. No changes to shared-ui required.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:57:29 +02:00
Till JS
51e6a20daf feat(ai-agents): Agents UI + Scene binding + Mission picker (Phase 5)
The Multi-Agent Workbench becomes visible. User can now create named
agents with their own persona (name, avatar, role), policy, memory,
and budgets; missions are created against a specific agent; scenes
can be bound to an agent so the Workbench tab shows who's at home.

New UI:
- /ai-agents module (ListView with list/create/detail modes, mirroring
  the ai-missions pattern). Detail view exposes:
  * Profile (name, avatar emoji, role) + pause/resume/archive/delete
  * Behavior (systemPrompt + memory — both encrypted at rest per the
    registry)
  * Limits (maxConcurrentMissions, maxTokensPerDay)
  * Policy editor: global default (auto/propose/deny) + per-module
    overrides for the usual suspects (todo / calendar / notes / …).
    Three quick-apply templates: Standard, Cautious, Aggressive.
  * Clear save path with duplicate-name handling from the store.
- Registered under the 'ai' category alongside the existing AI apps.

New component: AgentPicker — compact <select> over active agents plus
an optional "— keiner —" slot. Reused in:
- ai-missions create flow (new "Agent" fieldset — who executes this
  mission; passes agentId through to createMission so the very first
  server-iteration writes land under the right principal).
- BindAgentDialog — scene context-menu entry "An Agent binden…"
  opens this dialog. Purely a UI lens: scene.viewingAsAgentId ends up
  set, SceneAppBar now renders the agent's avatar on the scene tab
  next to the name (tooltip on hover). No data-scope change.

Store updates:
- WorkbenchScene gains viewingAsAgentId?; patchScene accepts it;
  workbenchScenesStore.setSceneAgent(id, agentId|undefined) helper.
- CreateMissionInput gains agentId?; the ai-missions create form
  passes it. MissionPatch also extended so future editors can reassign
  a mission to a different agent.

Tests: webapp svelte-check 0 errors, 0 warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:56:02 +02:00
Till JS
cacbfb0764 fix(settings): wire ListView to GeneralSection instead of inlining
ListView rendered GlobalSettingsSection directly for the 'general' tab,
so the header unification in GeneralSection.svelte never took effect —
the sticky "App-Einstellungen" pill still leaked through.

- Swap inline block for <GeneralSection />
- Carry showTheme={false} into GeneralSection (Themes is its own app)
- Drop now-unused GlobalSettingsSection/userSettings/onMount/SettingsPanel imports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:52:18 +02:00
Till JS
aebbcdd1c3 refactor(settings): unify section headers across tabs
Every tab now leads with the same SettingsSectionHeader
(icon-circle + title + description), matching Credits and Data:

- AiSection wraps AiSettings with SettingsSectionHeader (Robot, indigo);
  AiSettings's inline icon+title is removed
- GeneralSection wraps GlobalSettingsSection with SettingsSectionHeader
  (Gear); suppresses the inner sticky pill header via title=""
- SecuritySection adds one top-level SettingsSectionHeader
  (ShieldCheck, blue) above the four sub-panels

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:48:41 +02:00
Till JS
f2faaf1387 refactor(pill-nav): drop Settings entry, guard on settingsHref
Settings lives in the Workbench now — no longer needs its own pill.
settingsHref becomes optional; both places that render the entry
(user-menu link list + nav overflow dropdown) skip it when unset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:43:29 +02:00
Till JS
f7426ab40f feat(ai): policy is read from the owning agent (Phase 4)
Until now AiPolicy lived as a user-global setting consulted for every
AI action. With agents as the principal unit of AI behavior, policy
belongs on the agent — different agents can be aggressive about tasks
but conservative about calendar edits, etc.

Webapp (tools/executor.ts):
- When an AI actor invokes a tool, the executor looks up the owning
  agent via getAgent(actor.principalId) and passes agent.policy into
  resolvePolicy. Falls back to DEFAULT_AI_POLICY when the agent record
  is missing (legacy write, deleted agent, race) so no tool call can
  silently bypass the propose/deny path.
- resolvePolicy already accepted an optional policy arg, so the call
  site change is a single line plus the agent load.

Server (mana-ai):
- ServerAgent gains an optional policy field, projected off the same
  plaintext JSONB that the webapp writes.
- Tick loop filters AI_AVAILABLE_TOOLS through filterToolsByAgentPolicy
  before passing them to the planner prompt. Resolution order mirrors
  the webapp: tools[name] → defaultsByModule → defaultForAi; 'deny'
  drops the tool so the LLM never even sees it.

Phase 5 will surface a per-agent policy editor on the agent-detail
UI. Until then all agents inherit DEFAULT_AI_POLICY (baked in during
createAgent), which means no behavior change for existing users —
every tool that was 'propose' before is still 'propose' now, just
reached via agent.policy instead of the user-level singleton.

Tests: mana-ai 41/41, webapp svelte-check clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:43:04 +02:00