From 25c3bb6cdfe8d9242e146ca2d519c09a8b69cb37 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 23 Apr 2026 14:25:14 +0200 Subject: [PATCH] docs(mana-mcp,mana-ai): CLAUDE.md coverage for M1 agent-loop primitives mana-mcp: - Policy-gate section: POLICY_MODE semantics, the four decision rules, where to find soak metrics during log-only burn-in. - /metrics section pointing at the Prometheus job. mana-ai: - New v0.8 status block: reminderChannel wiring, the two live producers (tokenBudgetReminder active, retryLoopReminder dormant pending LoopState extension), why POLICY_MODE here is limited to freetext inspection, why parallel-reads have no effect until the tool-registry absorbs the full AI_TOOL_CATALOG (M4 of personas). Co-Authored-By: Claude Opus 4.7 (1M context) --- services/mana-ai/CLAUDE.md | 9 +++++++++ services/mana-mcp/CLAUDE.md | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) 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.