opencode-config/.opencode/skills/memory/SKILL.md
Sergey 52343e2a78
feat(memory): rotate repo memory files by size without compaction (#239)
* feat(memory-syncer): rotate files by 50KB size, dedup across files

* docs(memory-skill): document file rotation, remove inline compaction

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-08-03 18:01:41 +03:00

8 KiB
Raw Blame History

name description
memory Instructions for opencode-memory file-based memory system (search + save + retro). Also when user says "память", "memory", "запомни", "найди в памяти".

File Memory (opencode-memory)

Графовая память (Graphiti/FalkorDB) удалена — была нестабильна и забагована. Память работает через файловую систему с keyword + semantic search — 5 TS tools (.opencode/tools/memory-*.ts), вызывают python3 -m src.memory напрямую (без wrapper-hop, без MCP-плагина).

Архитектура (progressive enhancement)

  • Keyword search — всегда работает (ripgrep по .md файлам). Не требует env vars, не требует индекса.
  • Semantic search — включается если set OPENAI_BASE_URL + OPENAI_API_KEY. Embeddings через OpenRouter (qwen/qwen3-embedding-8b, 4096-dim), индекс в .rag/index.json (Python формат, meta.json с version key).
  • Fallback: OpenRouter недоступен / упал → semantic возвращает []memory-search деградирует к keyword-only (работает, но semantic enhancement потерян). Не блокирует работу.
  • Auto-setup: первый memory-save всё создаёт — mkdir категорий, git init (или clone если OPENCODE_MEMORY_REMOTE set), post-commit hook (auto-push) если remote set. Zero-config: новый пользователь без remote может начать писать память сразу.
  • memory-doctor — read-only диагностика: проверяет ripgrep, Python src.memory, env vars, индекс. Не модифицирует ничего.

Инструменты

Инструмент Назначение
memory-search({ query, category? }) Гибридный поиск (ripgrep keyword + Python semantic)
memory-list({ category? }) Список категорий / файлов
memory-save() Commit + reindex после записи/редактирования (auto-setup: git init/clone + hook если OPENCODE_MEMORY_REMOTE set)
memory-access({ path }) Отметить файл как прочитанный (bump last_accessed/access_count)
memory-doctor() Read-only диагностика: ripgrep, Python src.memory, env vars, index

Категории

preferences · repos · technical · people · workflows · snippets · notes

Как работать

  1. Перед началом работыmemory-search по теме
  2. В процессе — сохранять находки сразу (контекст свежий)
  3. В конце сессии — retrospective: что узнал → сохранить, что было в памяти → обновить, чего не хватало → создать

Когда сохранять

  • gotcha / workaround (неочевидное поведение)
  • структура репозитория, команды сборки/тестов
  • quirks инструментов
  • коренные причины багов (root cause)
  • указатели: «для X используй Y, осторожно с

Когда НЕ сохранять

  • данные, которые живой API возвращает свежими каждый раз
  • текущий статус тасок / PR / спринтов
  • копии вики-страниц и API-документации
  • то, что находится за <1 минуты из первых принципов

Структура файла

---
title: Человекочитаемый заголовок
tags: [tag1, tag2]
summary: Описание в одну строку
created: YYYY-MM-DD
updated: YYYY-MM-DD
importance: high | medium | low
source: откуда информация
source_date: YYYY-MM-DD
related: [category/file.md]
---

Путь для репозиториев

Default: /root/.local/share/opencode/opencode-memory (переопределяется через OPENCODE_MEMORY_DIR).

{memory-dir}/repos/{host}/{org}/{repo}.md

Используй один путь последовательно во всех примерах — default (/root/.local/share/opencode/opencode-memory) или override (OPENCODE_MEMORY_DIR), но не оба сразу.

Формат записей

- [YYYY-MM-DD, PR#N] <суть>

Дата и PR-номер в тексте — для RAG-поиска и верификации (какой PR принёс знание).

Что дистиллировать (durable-only)

  • gotchas / workaround (неочевидное поведение)
  • паттерны, конвенции репозитория
  • указатели: «для X используй Y, осторожно с
  • коренные причины багов (root cause)

НЕ дистиллировать: статусы, «сейчас делаем», текущие таски, ephemeral контекст.

ADR — только указатель

- [date, PR#N] ADR-NN: <суть> → docs/decisions/NN-title.md

Не копируй содержание ADR — только указатель на файл.

Править вместо дублирования (ОБЯЗАТЕЛЬНО)

Перед добавлением записи — прочитай существующий файл. Если факт уже записан — обнови запись (bump updated в frontmatter, дополни детали если нужно). НЕ создавай дубликаты. Дубликаты раздули файлы до 600+ KB. Каждая гоча/паттерн/root cause = одна запись, не по одной на каждый PR где упоминалась.

Ротация файлов (50 KB)

Память репо ротируется по размеру вместо inline compaction:

  • один репо → один или несколько файлов по пути {memory-dir}/repos/{host}/{org}/{repo}*.md
  • первый файл: {repo}.md; последующие (когда первый заморожен): {repo}-002.md, {repo}-003.md, ... (3-значный sequential, не по дате)
  • порог ротации: 50 KB (soft). Файл с размером ≥ 50 KB считается замороженным — новые записи в него НЕ пишутся, открывается следующий файл
  • замороженные файлы остаются редактируемыми для dedup (обновление существующих гоч, bump updated в их frontmatter); новые записи в замороженный файл — НЕ пишутся
  • memory-syncer выбирает активный файл (первый существующий с размером < 50 KB) перед каждой записью и ищет дубликаты по всем repo*.md (включая замороженные) — см. memory-syncer agent

Inline compaction удалён: память = durable выжимка (сжимать некуда), git = бесконечный backup (без отдельных archive-файлов). Receipts остаются в файлах (audit trail). Существующие большие файлы (youtube-soft.md 112 KB, opencode.md 80 KB, opencode-config.md 64 KB) миграции не требуют — при следующей записи откроется -002.md.

Квитанция ставится всегда

Даже если durable-записей нет, квитанция обязательна:

- [date, PR#N] — (нет durable-записей)

Это подтверждает, что memory-sync фаза выполнена (audit trail).