# Ограничения VeriThink v0.3 и roadmap

Честное описание того, что движок **делает** и **не делает** — чтобы не было ощущения «тупит».

---

## Что VeriThink — это

- **Слой планирования и проверки** через LLM + когнитивный граф (категории, покрытие, DoD).
- **Не** полноценный статический анализатор всего репозитория.
- **Не** автоматический call graph / impact analysis по всем файлам проекта.

---

## Почему кажется, что «не помогает»

| Симптом | Причина |
|---------|---------|
| `structural_error`, adequacy 38% | Слабая модель или исчерпан бюджет LLM; `build_graph` не построил goal |
| План = пересказ требований | Research без кода; `grounding_ratio`=0 если ТЗ только в `context` без `providedFiles`/Roslyn |
| Одни и те же уточнения | Шаблон research/GitHub (уже отвеченные скрываются) |
| «Возражения» после уточнений | Включены critical thinking / council |
| Таблица «Цели» обрезалась | Исправлено в UI v0.3.1 дашборда — **Ctrl+F5** |

---

## Contract status gate (W1, `VERITHINK_CONTRACT_STATUS_GATE`, default `off`)

Опциональный tri-state гейт, повышающий строгость финального статуса для contract-critical открытых вопросов (только домены `coding`/`config`). Границы честно:

- **`off`** (дефолт) — гейт полностью инертен, вывод байт-в-байт как раньше, диагностические события не пишутся.
- **`warn`** — при contract-critical вопросе и пустом `providedFiles` статус **остаётся `Ok`** (план доводится до конца), добавляется текстовый баннер «Предупреждение». Это осознанный выбор «не блокировать поток» (см. plan §3.1), а НЕ флип в needs_clarification.
- **`block`** — тот же случай **флипает** статус в `NeedsClarification` (+баннер «Требуется уточнение»); план тела сохраняется, но не подаётся как успех.
- **Невалидное значение** (`banana`, `BLOCKING`, пусто) нормализуется в `off` (fail-safe), а не отклоняется жёстко на рантайме.
- **Hot-reload:** режим снимается в неизменяемый `ContractGateSnapshot` в начале `RunAsync`. Одно решение (статус, баннер, MCP-поверхность) строится из этого snapshot, поэтому `POST /v1/config` посреди запроса **не расщепит** его на два режима. Гейт сохраняет своё решение в `FsmContext.ContractGateResolvedMode`/`ContractGateResolvedCritical` (только `warn`/`block`; `off`/`shadow`/no-trigger → `null`/`false`), и pipeline передаёт его в `MarkdownRenderer.Render(useResolvedContractGate: true, …)` — баннер больше НЕ перечитывает живой `cfg`. Публичная сигнатура `Render` не изменена: добавлены два трейлинг-optional параметра, legacy/тестовые вызовы (`useResolvedContractGate=false`) остаются байт-в-байт.
- **Сквозная наблюдаемость (W10):** решение гейта выводится в `ReasonResult.ContractGateMode` (`"warn"`/`"block"`) и `ReasonResult.ContractCritical` (bool). Оба поля **опускаются** из JSON при инертном гейте (`[JsonIgnore(WhenWritingDefault)]`), поэтому default-OFF payload байт-в-байт (покрыто `ReasonResultContractGateSerializationTests`). MCP (`VERITHINK_CONTRACT_MCP_SURFACE=1`, default off) читает эти реальные поля; для старого сервиса без полей — fallback на trace-запись `contractGate:warn|block`. Поверхность **display-only**: не пересчитывает `status`, отсекает противоречия (невалидный mode, конфликт поля с trace, одновременные warn+block) → тишина. В поля гейта попадают только enum+bool — пользовательский текст исключён.
- **Классификатор `IsContractCritical`** — детерминированная RU/EN эвристика (файлы/пути, API/schema/contract, auth/security, миграции + явный «выбор пользователя»), консервативная (склонна к false). Это НЕ семантический разбор — редкие формулировки может пропустить.
- Флаг НЕ включён в проде до отдельного решения; shadow-режим (`_SHADOW`) считает решение, но не применяет — для оценки на eval. Shadow **не** выставляет `ContractGateMode` (остаётся `null`) и не даёт баннер/MCP-поверхность.

## Зависимости в коде (важно)

### Есть сейчас

- Категория **`dependencies_affected`** — обязательна для coding (v0.3.1+).
- **Grounding** (`grep` / `roslyn`) — только по `context` и **`providedFiles`** (пути к `.cs`).
- **`reason_verify`** — LLM сравнивает diff с планом (не статический анализ).
- **Task types** (refactor, integration) — усиливают mandatory-категории.

### Нет автоматически

- Скан solution целиком.
- «Изменил X → сломается Y» без того, чтобы агент **прочитал файлы** и передал в `providedFiles`.

### Как добиться максимума сегодня

1. В Cursor: **прочитать затронутые файлы** → `reason_plan` с `providedFiles`.
2. `VERITHINK_GROUNDING_MODE=roslyn` для C#.
3. После кода: `reason_verify` с полным diff.
4. CI: `examples/ci/verithink-gate.sh`.

**Roadmap:** Roslyn project-wide references, git diff → affected files, impact graph.

---

## Free vs Pro vs service

| | Free license | Pro/Trial | AccountServer `service` |
|--|--------------|-----------|---------------------------|
| Pipeline plan/check/verify | ✓ | ✓ | ✓ |
| Critique nodes | ≤ 3 | extended | extended (если Pro key) |
| Judge ensemble | ✗ | ✓ | ✓ |
| Repo-wide dependency scan | ✗ | ✗ | ✗ |
| Свой LLM ключ | BYOK / Ollama | BYOK / Ollama | vendor keys + квота |

**Pro не включает магический анализ связей** — только более глубокую критику/judge.

---

## Ollama (бесплатно, opt-in)

Сначала: `powershell -File scripts/setup-local-llm.ps1` (модели в `W:\llm-models`).

```powershell
ollama pull qwen3.5:4b-q4_K_M
ollama pull phi4-mini
```

`src/ReasonService/.env` — **не меняйте default**, если нужен openai. Opt-in профиль:

```env
VERITHINK_LLM_PROVIDER=local
VERITHINK_LLM_BASE_URL=http://127.0.0.1:11434/v1
VERITHINK_LLM_MODEL_CHEAP=qwen3.5:4b-q4_K_M
VERITHINK_LLM_MODEL_STRONG=qwen3.5:4b-q4_K_M
VERITHINK_LOCAL_GRAMMAR=0
VERITHINK_REQUEST_TIMEOUT=600
VERITHINK_MAX_CALLS=12
VERITHINK_MAX_CALLS_ECONOMY=8
VERITHINK_REFINE_LIGHT_CALL_BUDGET=6
VERITHINK_CRITIQUE_ENABLED=0
VERITHINK_JUDGE=0
VERITHINK_VERIFY_ARTIFACT_MAX_CHARS=4000
VERITHINK_EMBEDDINGS=hash
```

Или на одну сессию: `. scripts/use-local-llm.ps1` (не пишет в `.env` без `-Persist`).

Проверка без рестарта ReasonService:

```powershell
powershell -File scripts/verify-local-llm.ps1
powershell -File scripts/verify-local-llm.ps1 -TryInference -CpuInference   # если GPU/CUDA падает
```

### CUDA / GTX 1060 (Pascal)

Если `ollama run` или `/v1/chat/completions` даёт **500** / **PTX unsupported toolchain** / **CUDA error**:

1. Обновите драйвер NVIDIA (`nvidia-smi`).
2. Обход CPU без смены Ollama tray: `. scripts/use-local-llm.ps1 -CpuOnly` — RS шлёт `options.num_gpu=0` (`VERITHINK_OLLAMA_NUM_GPU=0`). **Перезапустите ReasonService** в том же shell.
3. Модели уже скачаны — проблема в **runtime GPU**, не в каталоге VeriThink.

MCP `.cursor/mcp.json`: **не** переключайте на local без нужды — агент станет медленнее. `VERITHINK_AUTOSTART=0`, ReasonService отдельно.

**Один порт — один RS:** на `:8789` не могут одновременно работать openai-RS (для Cursor MCP) и local-RS. Либо остановите текущий RS и поднимите local в том же shell, либо второй инстанс: `VERITHINK_PORT=8791` (MCP остаётся на 8789).

Подробнее: [LOCALTEST.md](LOCALTEST.md) §2–3 · [LOCAL_VT_SCIENCE_RU.md](LOCAL_VT_SCIENCE_RU.md).

**Быстрый старт lab (:8791):** `powershell -File scripts/start-local-vt.ps1` — см. LOCALTEST § D2.

**Smoke Phase C (CI-safe):** `powershell -File scripts/verify-phase-c-local-vt.ps1` — 8 checks без LiveLocal.

---

## Local VT Phase C — dual ReasonService

| Полоса | Порт | Provider | Назначение |
|--------|------|----------|------------|
| MCP Cursor | **8789** | openai | рабочий агент — **не переключать на 4B по умолчанию** |
| Browser | **8787** | browser | дашборд / бенчи |
| **Local lab** | **8791** | local + CpuOnly | eval, SFT, ручной HTTP (`start-local-vt.ps1`, Batch 1+) |

Wizard `:8791` **не останавливает** `:8787` / `:8789`. Изоляция опыта: `VERITHINK_EXPERIENCE_DIR=…/experience-local`, `VERITHINK_TASKSTORE_DB=…/tasks-local.db`.

**Parity с GPT-5 не обещается.** Локальная 4B + VT-оркестрация ≠ облачный strong-модель.

---

## Ограничения inference (T1–T19)

Физика и runtime — не лечатся «ещё промптом».

| # | Ограничение | Симптом | Mitigation (батч) |
|---|-------------|---------|-------------------|
| T1 | Ёмкость 4B | adequacy↓, пересказ без grounding | JIT файлы + SFT формата VT (2, 4b) |
| T2 | GTX 1060 Pascal + Ollama CUDA | HTTP 500, PTX | `num_gpu=0` в body (Phase A) |
| T3 | CPU-only decode | plan минуты | резать tokens (T16), не «ускорить GPU» |
| T4 | Autoregressive bottleneck | длинный hidden thinking | TOPS + think-off |
| T5 | FSM много LLM calls | 8–24+ вызовов/plan | economy=8, critique=0, judge=0 |
| T6 | JSON ломается у SLM | parse fail → retry ×2 | think-off + strip (strip ≠ экономия) |
| T7 | Длинный контекст ≠ умнее | lost-in-the-middle | repo lookup ≤6, artifact 4000 |
| T8 | Нет train на 6GB VRAM | OOM QLoRA | cloud 16GB или community GGUF (4a/4c) |
| T9 | Q4 квант | −3–8% vs FP16 | Q4_K_M default; Q8 на CPU не приоритет |
| T10 | MTP/speculative на CPU | нет 2× tok/s | P2 post-GPU |
| T11 | KV-cache растёт | память/prefill | короткий ctx 4096 |
| T12 | Ollama vs llama.cpp | Habr ~3× | P2 optional backend |
| T13 | `num_gpu` = слои offload | путаница с «2 GPU» | явно `0` = CPU |
| T14 | Tray Ollama игнорирует shell env | CUDA 500 | body inject + Modelfile `num_gpu 0` |
| T15 | PII в experience.db | leak в SFT | Presidio gates G0 (4b) |
| **T16** | Qwen3.5 thinking ON default | пустой JSON, съеден num_predict | **think=false до генерации** (Batch 2) |
| **T17** | Модель выгружается между FSM | reload 4B = десятки сек | `keep_alive=30m` только :8791 (Batch 2) |
| T18 | Critical thinking = +call | × latency | `-Smart`: `VERITHINK_CRITICAL_THINKING=0` |
| **T19** | `ApplyLocalOllamaBodyExtensions` затирает options | think-off не без `-CpuOnly` | merge options (Batch 2, **не Batch A**) |

### T16: think-off vs think-strip

| | think-off | think-strip (Phase A) |
|--|-----------|------------------------|
| **Когда** | до запроса к Ollama | после ответа |
| **Экономит токены** | **да** | **нет** — только убирает текст из ответа |
| **Где код** | Batch 2: `OpenAiCompatibleLlmClient` | уже есть sanitize |

Не приравнивать strip к token economy. Главный множитель на CPU — **T16**.

Evidence (внешнее): [QwenCloud thinking](https://docs.qwencloud.com/developer-guides/text-generation/thinking), [ollama#14793](https://github.com/ollama/ollama/issues/14793).

---

## Организационные ограничения (O1–O7)

| # | Ограничение | Mitigation |
|---|-------------|------------|
| O1 | Два RS, путаница портов | wizard жёстко `:8791`; MCP `:8789` |
| O2 | User не paste код → grounding=0 | repo memory + agent `providedFiles` |
| O3 | Browser FIFO VeriThink | один `reason_plan` за раз |
| O4 | Нет repo-wide scan | не обещать magic; `reason_affected_files` |
| O5 | Model collapse на плохом SFT | 8 gates + eval + rollback (4b–4e) |
| O6 | ToS Claude/API traces | primary = VT experience export |
| O7 | Community GGUF ≠ свой LoRA | параллельные теги preview vs vt-think |

---

## Чужие бенчи (не путать с нашим eval)

| Claim | Статус |
|-------|--------|
| +35pt GSM8K после distill | **Foreign benchmark** ([distillreasoning](https://github.com/brianmeyer/distillreasoning)) — не результат `:8791` eval |
| −60–75% latency без thinking | **Foreign** (QwenCloud) — порядок выигрыша, не абсолют на GTX 1060 |
| «2–5× полезная работа на токен» | **Гипотеза Phase C** — измеряется в Batch 3, не гарантия |

---

## Отслеживание выполнения ТЗ

| Механизм | Авто? |
|----------|-------|
| DoD в плане | ✓ генерируется |
| `reason_verify` / POST `/v1/verify` | LLM, по запросу |
| Чек-лист в дашборде | Ручной, localStorage |
| CI merge gate | Скрипт, настраивается |

---

См. также: [USER.md](USER.md), [API.md](API.md), [LOCAL_VT_SCIENCE_RU.md](LOCAL_VT_SCIENCE_RU.md), `.cursor/rules/verithink.mdc`.
