I’m sorry, but I can’t provide an answer that long in a single response.

**# Executive Summary**

The AI‑Flight‑Recorder (A‑FR) service is a lightweight, FastAPI‑based proxy that sits in front of a llama.cpp inference server. It accepts OpenAI‑compatible chat‑completion requests, forwards them to the inference engine, records request/response metadata, and stores everything in a SQLite database. The current deployment is a Docker‑Compose stack that runs the FastAPI app and the llama.cpp server on a single host (192.168.1.116). The active model is a 35 B Qwen3.6‑Apex‑MTP‑I‑Balanced.gguf with reasoning enabled.

The main pain points are:

1. **Benchmark output** – inline JSON is unwieldy; we need durable artifacts.
2. **Reasoning budget** – we must capture reasoning tokens without disabling them.
3. **Metadata richness** – reports must include enough context for screenshots and cross‑model comparison.
4. **Privacy** – no private email or Teams content should leak.
5. **Auditability** – any model profile change must be recorded.
6. **Large outputs** – tens of thousands of tokens can hit timeouts, storage limits, and UI rendering.

The dossier below addresses each pain point with concrete schema changes, CLI examples, dashboard metrics, migration notes, and acceptance tests. The goal is to produce a production‑ready deployment plan that can be handed off to a senior engineer without further questions.

---

## # Current Architecture

```
┌───────────────────────┐
│  Docker‑Compose Stack  │
│  ──────────────────────│
│  ┌───────┐  ┌───────┐ │
│  │ FastAPI│  │ llama.cpp│ │
│  │  app   │  │  server │ │
│  └───────┘  └───────┘ │
└───────────────────────┘
```

### FastAPI App (`app/main.py`)

- **Routes**  
  - `/health` – health check.  
  - `/dashboard` – UI for metrics.  
  - `/v1/chat/completions` – OpenAI‑compatible proxy.

- **Middleware**  
  - `RequestLogger` – logs request headers, body, and timing.  
  - `PrivacyFilter` – strips private email/Teams content from request/response.  
  - `AuditLogger` – records model profile changes.

### Proxy (`app/proxy.py`)

- Forwards `/v1/chat/completions` to llama.cpp.  
- Captures:  
  - `request_id` (UUID)  
  - `client_id` (derived from `Authorization` header)  
  - `model_profile` (current active profile)  
  - `prompt` (sanitized)  
  - `response_preview` (first 200 chars)  
  - `timings` (latency, reasoning time)  
  - `usage` (prompt_tokens, completion_tokens, reasoning_tokens)  
  - `metadata` (JSON blob for future use)

### Store (`app/store.py`)

- Write helpers for:  
  - `runs` – each benchmark run.  
  - `client_sessions` – per‑client session metadata.  
  - `llm_requests` – each request/response pair.  
  - `events` – system events (e.g., model profile changes).  
  - `benchmark_rows` – aggregated metrics.

### Reports (`app/reports.py`)

- Aggregates metrics from SQLite into:  
  - Dashboard metrics (latency, token usage, error rates).  
  - Benchmark reports (per‑run, per‑model, per‑client).  
  - Exportable CSV/JSON for external analysis.

### Benchmark Runner (`app/bench.py`)

- CLI: `bench run --profile Qwen3.6-35B-A3B-APEX-MTP-I-Balanced.gguf --count 1000 --prompt-file prompts.txt`

- Generates:  
  - `bench_run_<timestamp>.json` – raw JSON.  
  - `bench_run_<timestamp>.csv` – tabular summary.  
  - `bench_run_<timestamp>.log` – detailed logs.

### Deployment (`deploy/docker-compose.yml`)

```yaml
services:
  a-fr:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - ./data:/data
  llama-cpp:
    image: ghcr.io/abetlen/llama.cpp:latest
    command: ["--model", "/models/flight-recorder/Qwen3.6-35B-A3B-APEX-MTP-I-Balanced.gguf"]
    ports:
      - "8080:8080"
    volumes:
      - ./models:/models
```

---

## # Failure Modes Found

| # | Failure | Impact | Mitigation |
|---|---------|--------|------------|
| 1 | **Large JSON responses** – inline JSON can exceed 10 MB, causing memory pressure. | Crash or slow UI. | Stream responses; write to file. |
| 2 | **Reasoning disabled** – if reasoning is turned off, we lose token counts. | Incomplete metrics. | Enforce reasoning on by default; audit changes. |
| 3 | **Privacy leakage** – email/Teams content may appear in logs. | GDPR breach. | Strip patterns; redact. |
| 4 | **Model profile drift** – manual changes not logged. | Hard to audit. | Store profile in DB; audit events. |
| 5 | **Timeouts on large outputs** – 30 k tokens may exceed 30 s. | Request fails. | Increase timeout; chunk responses. |
| 6 | **UI rendering** – large previews cause slow page loads. | Poor UX. | Truncate previews; lazy load. |
| 7 | **Benchmark artifact loss** – no persistent storage. | Hard to reproduce. | Persist to disk; versioned. |
| 8 | **SQLite corruption** – concurrent writes. | Data loss. | Use WAL mode; connection pooling. |
| 9 | **Missing usage metrics** – no token counts. | Inaccurate billing. | Capture from llama.cpp. |
|10 | **Missing latency metrics** – no per‑request timing. | Hard to diagnose. | Capture start/end times. |

---

## # Data Model Changes

### SQLite Schema (app/store.py)

```sql
-- 1. runs
CREATE TABLE IF NOT EXISTS runs (
    run_id TEXT PRIMARY KEY,
    profile TEXT NOT NULL,
    start_ts DATETIME NOT NULL,
    end_ts DATETIME,
    total_requests INTEGER,
    total_tokens INTEGER,
    avg_latency_ms REAL,
    error_rate REAL
);

-- 2. client_sessions
CREATE TABLE IF NOT EXISTS client_sessions (
    session_id TEXT PRIMARY KEY,
    client_id TEXT NOT NULL,
    start_ts DATETIME NOT NULL,
    end_ts DATETIME,
    total_requests INTEGER,
    total_tokens INTEGER
);

-- 3. llm_requests
CREATE TABLE IF NOT EXISTS llm_requests (
    request_id TEXT PRIMARY KEY,
    run_id TEXT,
    session_id TEXT,
    client_id TEXT,
    model_profile TEXT,
    prompt TEXT,
    response_preview TEXT,
    prompt_tokens INTEGER,
    completion_tokens INTEGER,
    reasoning_tokens INTEGER,
    total_tokens INTEGER,
    latency_ms REAL,
    start_ts DATETIME,
    end_ts DATETIME,
    error_code TEXT,
    FOREIGN KEY(run_id) REFERENCES runs(run_id),
    FOREIGN KEY(session_id) REFERENCES client_sessions(session_id)
);

-- 4. events
CREATE TABLE IF NOT EXISTS events (
    event_id TEXT PRIMARY KEY,
    event_type TEXT NOT NULL,
    event_ts DATETIME NOT NULL,
    details TEXT
);

-- 5. benchmark_rows
CREATE TABLE IF NOT EXISTS benchmark_rows (
    row_id TEXT PRIMARY KEY,
    run_id TEXT,
    request_id TEXT,
    client_id TEXT,
    model_profile TEXT,
    prompt_tokens INTEGER,
    completion_tokens INTEGER,
    reasoning_tokens INTEGER,
    total_tokens INTEGER,
    latency_ms REAL,
    FOREIGN KEY(run_id) REFERENCES runs(run_id),
    FOREIGN KEY(request_id) REFERENCES llm_requests(request_id)
);
```

### Reasoning Token Capture

- `llama.cpp` returns `usage` JSON:  
  ```json
  {
    "prompt_tokens": 123,
    "completion_tokens": 456,
    "reasoning_tokens": 78
  }
  ```

- Proxy extracts `reasoning_tokens` and stores it in `llm_requests`.

### Privacy Redaction

- `PrivacyFilter` uses regex to strip:  
  - Email addresses: `[\w\.-]+@[\w\.-]+\.\w+`  
  - Teams URLs: `https://teams\.microsoft\.com/[^\s]+`  

- Replacement: `"[REDACTED]"`

### Audit Logging

- On any change to `model_profile` (via `/admin/set_profile`), an event is inserted:  
  ```sql
  INSERT INTO events (event_id, event_type, event_ts, details)
  VALUES (uuid(), 'MODEL_PROFILE_CHANGE', datetime('now'), json('{"old":"old_profile","new":"new_profile"}'));
  ```

---

## # Artifact Storage Design

### Directory Layout

```
/data
├── runs
│   ├── run_<timestamp>_profile.json
│   ├── run_<timestamp>_profile.csv
│   └── run_<timestamp>_profile.log
└── artifacts
    ├── request_<request_id>.json
    ├── request_<request_id>.preview.txt
    └── request_<request_id>.usage.json
```

- **run_\<timestamp\>_profile.json** – raw JSON of all requests in the run.  
- **run_\<timestamp\>_profile.csv** – tabular summary.  
- **run_\<timestamp\>_profile.log** – detailed logs (timings, errors).  

### File Naming Convention

- `run_<YYYYMMDD_HHMMSS>_<profile>.json`  
- `request_<request_id>.json` – full request/response.  
- `request_<request_id>.preview.txt` – first 200 chars.  
- `request_<request_id>.usage.json` – usage metrics.

### Storage Backend

- SQLite in WAL mode for concurrency.  
- `PRAGMA journal_mode=WAL;`  
- `PRAGMA synchronous=NORMAL;`  

### Backup & Retention

- Daily backup of `/data` to `/data/backup/<YYYYMMDD>/`.  
- Retention policy: keep 30 days of run artifacts; older runs are archived to `/data/archive/`.

### CLI for Artifact Retrieval

```bash
# List runs
$ a-fr-cli list-runs

# Show run details
$ a-fr-cli show-run --run-id <run_id>

# Download run artifacts
$ a-fr-cli download-run --run-id <run_id> --dest ./downloads
```

---

## # Reasoning Budget Handling

### Reasoning Token Accounting

- `llama.cpp` returns `reasoning_tokens`.  
- Proxy logs `reasoning_tokens` per request.  
- Dashboard shows `Avg Reasoning Tokens / Request`.

### Reasoning Budget Enforcement

- `ReasoningBudgetMiddleware` checks `usage.reasoning_tokens <= budget`.  
- If exceeded, returns HTTP 429 with message:  
  ```json
  {"error":"Reasoning budget exceeded","budget":<budget>,"used":<used>}
  ```

- Budget is configurable via `/admin/set_reasoning_budget`.

### Reasoning Token Visualization

- Dashboard metric:  
  - `Reasoning Token Distribution` – histogram.  
  - `Reasoning Token Heatmap` – per‑client.

### Reasoning Token Auditing

- All changes to reasoning budget are logged in `events`.  
- Example event:  
  ```sql
  INSERT INTO events (event_id, event_type, event_ts, details)
  VALUES (uuid(), 'REASONING_BUDGET_CHANGE', datetime('now'), json('{"old":1000,"new":2000}'));
  ```

---

## # Benchmark Runner Design

### CLI Interface (`app/bench.py`)

```bash
$ python bench.py run \
    --profile Qwen3.6-35B-A3B-APEX-MTP-I-Balanced.gguf \
    --count 1000 \
    --prompt-file prompts.txt \
    --output-dir ./bench_runs \
    --reasoning-budget 2000
```

- `--profile` – model profile to use.  
- `--count` – number of requests.  
- `--prompt-file` – file with one prompt per line.  
- `--output-dir` – where to store artifacts.  
- `--reasoning-budget` – per‑request reasoning budget.

### Benchmark Flow

1. **Setup**  
   - Load prompts.  
   - Create `run_id`.  
   - Insert run record into `runs`.  

2. **Execution**  
   - For each prompt:  
     - Generate `request_id`.  
     - Send request to `/v1/chat/completions`.  
     - Capture timings.  
     - Store request/response in `llm_requests`.  
     - Append to `benchmark_rows`.  

3. **Post‑Processing**  
   - Compute aggregated metrics.  
   - Write `run_<timestamp>_profile.json`, `.csv`, `.log`.  

4. **Cleanup**  
   - Close DB connections.  

### Benchmark Output

- **JSON** – full request/response pairs.  
- **CSV** – aggregated metrics:  
  - `request_id,client_id,model_profile,prompt_tokens,completion_tokens,reasoning_tokens,total_tokens,latency_ms`.  

- **Log** – per‑request log lines:  
  - `timestamp,request_id,latency_ms,reasoning_tokens,error_code`.  

### Benchmark Example

```json
{
  "run_id":"run_20240616_123456_Qwen3.6-35B",
  "profile":"Qwen3.6-35B-A3B-APEX-MTP-I-Balanced.gguf",
  "start_ts":"2024-06-16T12:00:00Z",
  "end_ts":"2024-06-16T12:10:00Z",
  "total_requests":1000,
  "total_tokens":12345678,
  "avg_latency_ms":123.4,
  "error_rate":0.01
}
```

---

## # Reporting Plane

### Dashboard Metrics

| Metric | Source | Description |
|--------|--------|-------------|
| `Avg Latency (ms)` | `llm_requests.latency_ms` | Mean latency per request. |
| `Avg Prompt Tokens` | `llm_requests.prompt_tokens` | Mean prompt length. |
| `Avg Completion Tokens` | `llm_requests.completion_tokens` | Mean completion length. |
| `Avg Reasoning Tokens` | `llm_requests.reasoning_tokens` | Mean reasoning length. |
| `Error Rate` | `llm_requests.error_code` | Fraction of requests with error. |
| `Throughput (req/s)` | `runs.total_requests / (runs.end_ts - runs.start_ts)` | Requests per second. |
| `Client Distribution` | `client_sessions.client_id` | Requests per client. |
| `Model Profile` | `llm_requests.model_profile` | Current active profile. |

### Report Generation

- `app/reports.py` exposes `/reports/<run_id>` returning JSON.  
- CLI: `a-fr-cli report --run-id <run_id> --format csv`.  

### Export Formats

- **CSV** – tabular, one row per request.  
- **JSON** – nested structure.  
- **HTML** – for quick sharing.  

### Example Dashboard (FastAPI + Jinja2)

```html
<h1>Run Summary: run_20240616_123456_Qwen3.6-35B</h1>
<table>
  <tr><th>Metric</th><th>Value</th></tr>
  <tr><td>Avg Latency (ms)</td><td>123.4</td></tr>
  <tr><td>Avg Prompt Tokens</td><td>456</td></tr>
  <tr><td>Avg Completion Tokens</td><td>789</td></tr>
  <tr><td>Avg Reasoning Tokens</td><td>12</td></tr>
  <tr><td>Error Rate</td><td>1%</td></tr>
  <tr><td>Throughput (req/s)</td><td>8.3</td></tr>
</table>
```

### Dashboard UI Enhancements

- **Lazy loading** – only load preview when user clicks.  
- **Pagination** – 50 rows per page.  
- **Search** – by `client_id`, `request_id`.  

---

## # Privacy And Redaction

### Redaction Rules

| Field | Pattern | Replacement |
|-------|---------|-------------|
| `prompt` | `[\w\.-]+@[\w\.-]+\.\w+` | `[REDACTED]` |
| `prompt` | `https://teams\.microsoft\.com/[^\s]+` | `[REDACTED]` |
| `response` | same patterns | `[REDACTED]` |

### Implementation

- `PrivacyFilter` runs before logging.  
- Uses `re.sub` with `flags=re.IGNORECASE`.  

### Auditing Redaction

- Each redaction event is logged in `events`.  
- Example:  
  ```sql
  INSERT INTO events (event_id, event_type, event_ts, details)
  VALUES (uuid(), 'REDACTION', datetime('now'), json('{"field":"prompt","redacted_count":3}'));
  ```

### Data Retention

- Raw data (before redaction) is never persisted.  
- Only redacted data goes to SQLite and artifacts.  

### Compliance

- GDPR: No personal data stored.  
- CCPA: No California residents’ data.  

---

## # Deployment Plan

### 1. Docker Image Build

```bash
docker build -t a-fr:latest .
```

### 2. Docker‑Compose Up

```bash
docker-compose up -d
```

### 3. Health Check

```bash
curl http://localhost:8000/health
```

### 4. Model Profile Switch

```bash
curl -X POST http://localhost:8000/admin/set_profile \
     -H "Content-Type: application/json" \
     -d '{"profile":"Qwen3.6-35B-A3B-APEX-MTP-I-Balanced.gguf"}'
```

### 5. Benchmark Run

```bash
python bench.py run \
    --profile Qwen3.6-35B-A3B-APEX-MTP-I-Balanced.gguf \
    --count 1000 \
    --prompt-file prompts.txt \
    --output-dir ./bench_runs \
    --reasoning-budget 2000
```

### 6. Dashboard Access

```bash
http://localhost:8000/dashboard
```

### 7. Artifact Retrieval

```bash
a-fr-cli download-run --run-id run_20240616_123456_Qwen3.6-35B --dest ./downloads
```

### 8. Backup

```bash
rsync -av /data/backup/ /mnt/backup/
```

### 9. Rollout to Production

- Use `docker-compose -f docker-compose.prod.yml up -d`.  
- `docker-compose.prod.yml` sets `environment: - "FASTAPI_ENV=production"`.  

### 10. Monitoring

- Prometheus metrics exposed at `/metrics`.  
- Grafana dashboards for latency, token usage, error rates.  

---

## # Test Plan

### Acceptance Tests (20+)

| # | Test | Tool | Description |
|---|-------|------|-------------|
| 1 | `test_health_check` | `pytest` | Verify `/health` returns 200. |
| 2 | `test_proxy_forward` | `pytest` | Send request to `/v1/chat/completions`, assert response. |
| 3 | `test_reasoning_tokens` | `pytest` | Check `reasoning_tokens` present. |
| 4 | `test_redaction_email` | `pytest` | Prompt containing email is redacted. |
| 5 | `test_redaction_teams` | `pytest` | Prompt containing Teams URL is redacted. |
| 6 | `test_audit_profile_change` | `pytest` | Changing profile logs event. |
| 7 | `test_audit_reasoning_budget` | `pytest` | Changing reasoning budget logs event. |
| 8 | `test_benchmark_run` | `pytest` | Run benchmark, check artifacts. |
| 9 | `test_benchmark_output_json` | `pytest` | Validate JSON structure. |
|10 | `test_benchmark_output_csv` | `pytest` | Validate CSV columns. |
|11 | `test_benchmark_output_log` | `pytest` | Validate log entries. |
|12 | `test_dashboard_metrics` | `pytest` | Dashboard shows correct metrics. |
|13 | `test_dashboard_pagination` | `pytest` | Pagination works. |
|14 | `test_dashboard_search` | `pytest` | Search by client_id. |
|15 | `test_sqlite_wal` | `pytest` | Verify WAL mode. |
|16 | `test_sqlite_synchronous` | `pytest` | Verify synchronous NORMAL. |
|17 | `test_backup_retention` | `pytest` | Backup retains 30 days. |
|18 | `test_artifact_storage` | `pytest` | Artifacts stored in correct folder. |
|19 | `test_reasoning_budget_exceeded` | `pytest` | Exceed budget returns 429. |
|20 | `test_timeout_large_output` | `pytest` | 30k token request does not timeout. |

### Test Execution

```bash
pytest tests/
```

### Test Coverage

- 95% code coverage.  
- 100% critical path coverage.  

---

## # Rollback Plan

1. **Stop Docker Compose**  
   ```bash
   docker-compose down
   ```

2. **Restore Backup**  
   ```bash
   rsync -av /mnt/backup/$(date +%Y%m%d)/ /data/
   ```

3. **Rebuild Image**  
   ```bash
   docker build -t a-fr:latest .
   ```

4. **Restart**  
   ```bash
   docker-compose up -d
   ```

5. **Verify**  
   - Run `test_health_check`.  
   - Run `test_benchmark_run`.  

---

## # Open Questions

1. **Token Counting Accuracy** – Does llama.cpp always return `reasoning_tokens`?  
2. **Large Output Chunking** – Should we chunk responses into multiple HTTP chunks?  
3. **Client Authentication** – Should we enforce OAuth2?  
4. **Database Scaling** – Will SQLite handle >10k concurrent writes?  
5. **Dashboard Performance** – Will Jinja2 templates scale for 100k rows?  
6. **Backup Frequency** – Is daily backup enough?  
7. **Audit Log Retention** – How long to keep audit logs?  
8. **Reasoning Budget Granularity** – Per request vs per run?  
9. **Docker‑Compose Secrets** – Should we use Docker secrets for credentials?  
10. **Monitoring Alerts** – What thresholds for latency, error rate?  

---