Понять трёхслойную модель памяти ControlFlow: что куда писать, что откуда читать, и почему такое разделение существует.
- Session memory — кратковременная, ограничена текущей беседой.
- Task-episodic memory — память одной задачи (одного плана).
- Repo-persistent memory — долгосрочная, переживающая разные задачи.
- NOTES.md — repo-persistent active-objective state.
flowchart TD
subgraph Session["Session Memory"]
S[Текущий разговор<br/>/memories/session/]
end
subgraph Task["Task-Episodic Memory"]
T[plans/artifacts/<task>/<br/>Per-plan record]
end
subgraph Repo["Repo-Persistent Memory"]
N[NOTES.md<br/>active objective + phase]
R["/memories/repo/<br/>conventions, commands, invariants"]
end
Question[Вопрос или задача] -->|read order 1| Task
Question -->|read order 2| Session
Question -->|read order 3| Repo
Action[Запись] -.->|task-specific| Task
Action -.->|cross-plan fact| Repo
Action -.->|temporary| Session
Источник: docs/agent-engineering/MEMORY-ARCHITECTURE.md.
Каждая запись в /memories/repo/ должна быть классифицирована по одному из четырёх типов:
| Тип | Что хранит |
|---|---|
user |
Персональные предпочтения и workflow, применимые ко всему окружению |
feedback |
Исторические корректировки: прошлые ошибки, ограничения, которые агент должен учитывать |
project |
Ключевые архитектурные решения, структура и соглашения проекта |
reference |
Проверенные CLI-команды, значения конфигурации, инструкции по сборке |
Что никогда не записывать в repo-persistent память:
-
Производимое состояние кода (то, что можно перечитать прямо из репо).
-
Git-история (commit messages, ветки, merge records).
-
Эфемерное состояние задачи (однотёрновые заметки, scratch-инструментов, «итерация 3 прошла в 14:32»).
-
Для длинных orchestration-сессий используйте шаблон session notes:
plans/templates/session-notes-template.md. Он содержит пять разделов:Current State,Files and Functions,Errors & Corrections,Key Results,Worklog. Проверять перед использованием: любое утверждение о конкретном файле или функции, извлечённое из памяти, должно быть перепроверено по текущей кодовой базе, прежде чем на него опираться. Память — подсказка, а не источник истины для конкретных местоположений в коде.
Где живёт: /memories/session/ (виртуальный путь, реализуется через memory tool).
Что хранит:
- Текущая задача.
- В прогрессе — гипотезы и черновики.
- Промежуточные scratch-заметки.
- Состояние, нужное только до конца беседы.
Жизненный цикл: ограничен одной беседой. После reset — стерто.
Правила:
- Не использовать для cross-task фактов.
- Не использовать для invariants.
- Использовать для только текущего turn-а или серии turns.
Где живёт: plans/artifacts/<task-slug>/.
Что хранит:
- Per-plan history (verdicts, iterations, evidence).
- Verified items list для regression tracking.
- Final review log.
- Observability NDJSON (
plans/artifacts/observability/<task>.ndjson).
Жизненный цикл: живёт сколько живёт plan-артефакт. Архивируется вместе с планом.
Правила:
- Если факт применим к одному плану — сюда.
- Хранит «эпизодическую» историю задачи.
- Не дублирует план — план в
plans/<task>-plan.md, артефакты — рядом.
Самый интересный — разделён на два подслоя.
Что хранит: active-objective state only.
- Текущая задача (что мы делаем сейчас).
- Текущая фаза.
- Blockers и unresolved risks.
Не хранит: task-specific историю (это в episodic), invariants (это в /memories/repo/).
Обновляется: на границах фаз. Stale entries удаляются при superseding.
Цитата из политики:
«
NOTES.mdholds repo-persistent active-objective state only — keep it terse, update at phase boundaries, prune stale entries.»
Где живёт: управляется через repo memory tool (Copilot).
Что хранит:
- Conventions (например, «используем Python typing»).
- Verified commands (например, «
cd evals && npm testзапускает eval-харнесс»). - Invariants (например, «P.A.R.T. order is mandatory»).
- Лучшие практики, не очевидные из кода.
Поддерживается только create (per memory architecture). Для repo memory — JSON-объект с полями subject, fact, citations, reason, category.
Что НЕ хранить:
- Секреты.
- Изменчивые факты (например, версии).
- Task-specific детали.
Read order (рекомендованный):
- Task-episodic first — самое актуальное для текущей задачи.
- Session — текущий контекст беседы.
- Repo-persistent — общие факты как fallback.
Write rules:
| Факт | Куда |
|---|---|
| Применим к одному плану | Task-episodic |
| Применим cross-plan | Repo-persistent |
| Не переживёт turn | Session |
| Active objective | NOTES.md |
«If a fact applies to exactly one plan, it belongs in task-episodic memory. If it applies across plans, it belongs in repo-persistent memory. If it will not outlive the current turn, leave it in session memory.»
Задача: Добавить экспорт CSV в страницу отчётов.
| Что | Куда |
|---|---|
| Текущая фаза «design API» | NOTES.md (repo-persistent) |
План plans/csv-export-plan.md |
Plan artifact (отдельно) |
| Verdict от PlanAuditor для итерации 1 | Task-episodic (plans/artifacts/csv-export/) |
| Гипотеза «возможно, использовать stream API» | Session |
Факт «cd evals && npm test — каноническая верификация» |
Repo-persistent (/memories/repo/) |
Что это: загрязнение repo-persistent памяти fact-ами, которые на самом деле task-specific.
Симптомы:
- В
/memories/repo/появляются ссылки на конкретные plan-артефакты. - NOTES.md разрастается до многостраничного документа.
- Stale entries не удаляются.
Профилактика:
- Регулярно пересматривать NOTES.md (на границах фаз).
- Перед записью в repo — спросить: «применимо ли это к будущим задачам?»
- Удалять/обновлять устаревшие memory entries. Дисциплина использования памяти (Memory Use Discipline)
Два поведенческих инварианта (покрываются evals/tests/prompt-behavior-contract.test.mjs):
-
Verify before use — любое утверждение о конкретном файле или функции, извлечённое из памяти (session notes,
/memories/repo/илиNOTES.md), должно быть перепроверено по текущей кодовой базе, прежде чем действовать на его основе. Устаревшая память — подсказка, а не источник истины о конкретных местах в коде. -
Ignore memory on request — если пользователь явно говорит «ignore memory» (или эквивалентно: «don't use memory», «fresh context»), агент не должен обращаться к
/memories/repo/, NOTES.md или session notes в этом turn-е. Действие per-turn, не сохраняется.
Источник: docs/agent-engineering/PROMPT-BEHAVIOR-CONTRACT.md → §7 Memory Use Discipline.
plans/artifacts/observability/<task-id>.ndjson — это task-episodic, но с особым форматом (NDJSON для трассировки). Содержит gate-events с trace_id для корреляции.
См. docs/agent-engineering/OBSERVABILITY.md.
Не путайте логические слои с физическим хранилищем:
| Логический слой | Физическое хранилище |
|---|---|
| Session | Memory tool (/memories/session/) |
| Task-episodic | Файлы в plans/artifacts/<task>/ |
| Repo-persistent — active state | NOTES.md (commit-tracked) |
- Записывать неклассифицированные или производимые факты в
/memories/repo/. Сначала классифицируйте по типологии; отбрасывайте derivable code state, git-историю и эфемерное состояние задачи. - Действовать на основе устаревшей памяти без верификации. После рефакторинга claims о конкретных файлах/функциях становятся ложными. Всегда перепроверяйте.
- (новичок) Откройте
NOTES.mdв репо. Какая там сейчас active objective? - (новичок) Сколько слоёв в модели памяти ControlFlow?
- (средний) Куда вы запишете факт: «Для проекта X используется PostgreSQL 16 с расширением pgvector»?
- (средний) Что произойдёт, если NOTES.md не обновлён две недели?
- (продвинутый) Объясните, почему repo memory поддерживает только
create, а неupdate/delete. - (средний) Фаза только что завершилась. CoreImplementer-subagent обнаружил новое API-соглашение. Пройдите через Checklist C (в
skills/patterns/repo-memory-hygiene.md) и решите, стоит ли продвигать этот факт в/memories/repo/. - (продвинутый) В
<repository_memories>вы видите шесть записей с незначительно различающимися описаниями одной и той же командыcd evals && npm test. Запустите Checklist D (периодический аудит) и составьте Audit Report для этой ситуации
- Не обновлять NOTES.md на границах фаз. Stale state ведёт к рассинхрону.
- Хранить session-state в repo-persistent. Память не должна расти от коротких заметок.
- Помещать секреты в repo memory. Никогда.
- (новичок) Откройте
NOTES.mdв репо. Какая там сейчас active objective? - (новичок) Сколько слоёв в модели памяти ControlFlow?
- (средний) Куда вы запишете факт: «Для проекта X используется PostgreSQL 16 с расширением pgvector»?
- (средний) Что произойдёт, если NOTES.md не обновлён две недели?
- (продвинутый) Объясните, почему repo memory поддерживает только
create, а неupdate/delete.
- Перечислите 3 слоя памяти.
- Что хранится в NOTES.md?
- Куда писать invariants (например, P.A.R.T. order)?
- Какой read order рекомендован?
- Чем отличается task-episodic от session?