diff --git a/services/mana-ai/CLAUDE.md b/services/mana-ai/CLAUDE.md index 3675bca56..1b27ac918 100644 --- a/services/mana-ai/CLAUDE.md +++ b/services/mana-ai/CLAUDE.md @@ -97,6 +97,15 @@ Bewusst nicht gemacht (offen): Details zum Deep-Research-Flow: [`docs/reports/gemini-deep-research.md`](../../docs/reports/gemini-deep-research.md) §3.2. +## Status: v0.8 (Agent-Loop Improvements M1, 2026-04-23) + +Claude-Code-inspirierte Primitive in `runPlannerLoop` (live in `@mana/shared-ai`, siehe [`docs/plans/agent-loop-improvements-m1.md`](../../docs/plans/agent-loop-improvements-m1.md)) und deren Konsumierung hier: + +- [x] `reminderChannel` wired via `buildReminderChannel()` in `src/planner/reminders.ts`. Erster Live-Producer: `tokenBudgetReminder` — warnt ab 75% Tagesbudget, eskaliert ab 100% mit "JETZT abschliessen"-Prompt. Round-usage wird on-the-fly drauf addiert, so dass der Warn-Level mitwandert. +- [x] `retryLoopReminder` — Shape fertig, aber dormant: LoopState exponiert heute nur `lastCall`, nicht ein Failure-Window. Aktiviert automatisch sobald shared-ai LoopState um `recentResults` erweitert. +- [x] `POLICY_MODE` env (off/log-only/enforce, default log-only) für die mana-ai-seitige Freitext-Inspection (`detectInjectionMarker`). Rate-Limit und destructive-opt-in sind hier NICHT aktiv — tools werden nur als PlanSteps aufgezeichnet, die echte Enforcement passiert im Webapp-Client. +- [ ] Parallel-Reads im Server-Tick haben keinen Effekt, weil `SERVER_TOOLS` per Konstruktion propose-only ist. Könnte relevant werden sobald mana-ai die vollständige tool-registry absorbiert (M4 des Personas-Plans). + ## Status: v0.6 (Server-side Web-Research + erweiterte Tools) Der Runner kann jetzt vor dem Planner-Call eigenstaendig Web-Recherche ausfuehren (ohne Browser). Serverseitig werden 31 propose-Tools ueber 16 Module vom Planner vorgeschlagen (auto-Tools laufen ausschliesslich in der Webapp-Reasoning-Loop — der Server sieht nur propose). diff --git a/services/mana-mcp/CLAUDE.md b/services/mana-mcp/CLAUDE.md index 79b1789af..75e092eb8 100644 --- a/services/mana-mcp/CLAUDE.md +++ b/services/mana-mcp/CLAUDE.md @@ -91,6 +91,29 @@ The MCP server picks up the tool on next restart — no service code change need **Policy gating reminder:** `scope: 'admin'` tools never reach MCP clients. `policyHint: 'destructive'` tools are exposed but should be rare; prefer `policyHint: 'write'` with a soft-delete semantic. +## Policy gate + +Every tool call is evaluated by `evaluatePolicy()` from `@mana/tool-registry` before reaching the handler (see [`docs/plans/agent-loop-improvements-m1.md`](../../docs/plans/agent-loop-improvements-m1.md) for the design, and [`docs/reports/claude-code-architecture.md`](../../docs/reports/claude-code-architecture.md) for the Claude-Code `UH1` precedent). + +| `POLICY_MODE` | Behaviour | +|---|---| +| `off` | Gate disabled. Legacy path. | +| `log-only` | **Default.** Evaluates, increments metrics, never blocks. Used during soak. | +| `enforce` | Deny decisions abort the call with the reminder payload attached to the MCP error. | + +Decisions are emitted as `mana_mcp_policy_decisions_total{decision, reason, mode}` on `/metrics`. During log-only soak, watch `decision="deny"` — those are the calls that WOULD have been blocked. If false-positive rate stays below ~1 % over a week, flip to `enforce`. + +### What the gate decides today + +1. `scope: 'admin'` → deny outright (defense-in-depth; `isExposable` already filters these, but mana-ai consuming the registry doesn't). +2. `policyHint: 'destructive'` not in user's `allowDestructive` list → deny. Today the list is hard-coded to `[]` in `settingsFor()`; next PR sources it from the user profile. +3. Rolling 30 calls / 60 s per tool per user → deny. Ring buffer in `invocation-log.ts`. +4. Prompt-injection markers in freetext args → allow with `decision=flagged`. Non-blocking; signal only. + +## Metrics + +`GET /metrics` exposes the `mana_mcp_` registry (prom-client default metrics + policy + tool counters). Scraped by Prometheus at 30 s via the `mana-mcp` job in `docker/prometheus/prometheus.yml`. + ## Local smoke test (M1 exit gate) Manual end-to-end check that proves: external client → MCP → mana-sync → Postgres.