# Хранилище опыта

Хранилище существует потому, что «обращайся к своему опыту» не выполняет никто. Это стоит модели
обхода каталога и догадки. «Запусти одну команду, которая вернёт три лучших кандидата с их
применимостью» стоит одной команды. Поэтому набор поставляет команду.

```bash
python tools/experience.py search "ещё одно поле в отчёте"
```

## Устройство

```text
memory/
  index.json          пересобирается из записей; руками не правится
  tasks/              записи задач: что просили, что пробовали, что сделали, что проверили
  recipes/            рецепты решений, а не расшифровки
  artifacts/          файлы, конфиги, скрипты, промпты, чек-листы, которые стоит адаптировать
  failures/           что не сработало, корневая причина, работающая альтернатива
```

Запись — обычный Markdown: заголовок из двенадцати ключей, затем тело. Ничего не нужно ставить и
мигрировать, читается в диффе.

```yaml
id: add-column-to-endpoint
type: recipe            # task | recipe | artifact | failure
title: Add a nullable column to a reporting endpoint
status: validated       # draft | validated | deprecated
confidence: high        # low | medium | high
applicability: PHP endpoint on MySQL where the column is additive and no client parses SELECT *
tags: [php, mysql, migration]
created_at: 2026-10-24
updated_at: 2026-10-24
last_verified_at: 2026-10-24
source: user task
related: []
```

Тело рецепта несёт пять разделов, и `check` отклоняет запись, если какого-то нет:

```text
## Problem   ## When to use   ## Procedure   ## Validation   ## Rollback
```

`## Rollback` обязателен намеренно: рецепт без пути отмены — это ловушка с хорошим названием.

## Команды

| Команда | Что делает |
|---|---|
| `experience.py init` | создаёт четыре каталога и пустой индекс |
| `experience.py add <файл>` | проверяет запись и раскладывает её по типу |
| `experience.py search "<слова>"` | ранжированные кандидаты с причиной каждой позиции |
| `experience.py show <id>` | полная запись |
| `experience.py check` | схема, секреты, машинные пути, дубликаты, устаревание |
| `experience.py stats` | счётчики по типам и статусам |
| `experience.py deprecate <id> --by <id>` | снимает запись с учёта, не удаляя её |
| `experience.py selftest` | тринадцать фикстур: отказы действительно отказывают |

Коды возврата: `0` чисто, `1` находки уровня ошибки, `2` ошибка вызова.

## Что именно печатает поиск

Замерено на песочнице с одной записью, поиск словами самой задачи:

```text
query: report needs one more field  ·  1 candidate(s)
  [ 25] recipe    add-column-to-endpoint             validated overlap 5, validated, high confidence, verified 1d ago
        Add a nullable column to a reporting endpoint  —  memory/recipes/add-column-to-endpoint.md
```

В этой строке видны четыре решения: оценка позиции, тип, статус и — **почему**: пересечение терминов,
проверенность, уверенность, свежесть. Результат без причины нельзя проверить аудитом, поэтому
инструмент её печатает всегда.

## Что оно отклоняет

Замерено через `selftest` — это настоящие отказы, а не документация:

| Ситуация | Что говорит инструмент |
|---|---|
| литерал доступа в теле записи | `exp.secret … redact to a <placeholder>` |
| рецепт без `## Rollback` | `exp.recipe-sections … a recipe needs ## Rollback` |
| абсолютный машинный путь | `exp.abs-path … use <path>` |
| две записи с одним id | `exp.duplicate-id` |
| снятая с учёта запись без `superseded_by` | предупреждение, а не молчание |
| пустое хранилище | `exp.empty` — искать нечего, поэтому это не успех |

## Шесть вопросов до использования

Запись — гипотеза. Каждый вопрос должен пройти, иначе запись адаптируют (назвав адаптацию) либо
отклоняют.

| # | Вопрос | Провал, когда |
|---:|---|---|
| 1 | та же цель? | запись решала соседнюю задачу |
| 2 | то же окружение? | версии, пути, права или зависимости отличаются |
| 3 | допущения ещё держатся? | схема, API или контракт изменились |
| 4 | его проверка покрывает мой критерий приёмки? | оно доказало «страница отрисовывается», а нужно «выгрузка побайтово та же» |
| 5 | правила безопасности всё ещё позволяют? | прошлый подход хранил доступ в файле конфигурации |
| 6 | запись ещё актуальна? | `last_verified_at` старый, и проверку никто не повторял |

Невысказанная адаптация неотличима от слепого копирования — отсюда требование назвать её в ответе
(раздел `## Reused experience`).

## Правила записи

1. Записывайте то, что многоразово, очищено и достаточно общо, чтобы пригодиться в другом месте.
2. Никогда не записывайте разовый контекст, приватные деловые данные или непроверенное.
3. Обновляйте существующую запись вместо создания почти-дубликата.
4. Связывайте запись задачи с рецептами, артефактами и записями неудач, которые она породила.
5. Помечайте устаревшее через `superseded_by`; история аудита не удаляется.
6. Ставьте `last_verified_at` только после настоящей повторной проверки — никогда после простого
   чтения записи.

## Безопасность

Записи — это содержимое, а содержимое утекает. Используйте заглушки: `<API_KEY>`, `<HOST>`, `<USER>`,
`<PATH>`, `<CUSTOMER>`, `<DB>`. Запись, которая касается приватного контекста, объявляет свою
чувствительность (`public`, `internal`, `restricted`), и `restricted` не сохраняется вовсе. В публичные
репозитории попадают только очищенные примеры.

## Ловушки

| Ловушка | Симптом | Действие |
|---|---|---|
| записывать каждую задачу | хранилище заполняется шумом, поиск ничего не находит, агент перестаёт искать | записывать только многоразовое, общее, проверенное |
| считать запись истиной | старый рецепт применён в изменившемся окружении | пройти шесть вопросов и назвать адаптацию |
| два хранилища | один агент ведёт личные заметки рядом с общим | одно хранилище, одна схема, одна команда |
| правка `index.json` руками | поиск и `stats` расходятся с файлами | дать `add`/`check` пересобрать индекс |
| устаревший `last_verified_at` | ранжирование поднимает запись, которую год никто не проверял | обновлять только повторным прогоном её `## Validation` |
| `check` на репозитории как есть | он же помечает собственный `README.ru.md` в хранилище как запись без заголовка: проверка исключает только `README.md` | известный дефект проверки; укажите `--root` на своё окружение, где лежат только настоящие записи |

Дальше: [Проверки](06-Checklists.ru.md) — ворота, режимы отказа и ловушки в одном месте.
