diff --git a/rules/patterns/testing-policy/contract.md b/rules/patterns/testing-policy/contract.md
new file mode 100644
index 0000000..c84dd89
--- /dev/null
+++ b/rules/patterns/testing-policy/contract.md
@@ -0,0 +1,82 @@
+# Contract: Testing Policy
+
+Version: 1.0
+
+## Purpose
+
+Определяет когда писать тесты, когда не писать, и как их поддерживать.
+Применяется ко всем проектам на Go. Агенты следуют этим правилам самостоятельно, без запроса подтверждения.
+
+---
+
+## Когда тест обязателен
+
+Тест пишется всегда, когда код делает нетривиальное преобразование данных или реализует бизнес-логику:
+
+- **Парсеры** — любой код, читающий внешний формат (XML, JSON, CSV, бинарный)
+- **Трансформации** — конвертация единиц, нормализация, маппинг полей
+- **Бизнес-правила** — расчёты, фильтрация, агрегация, приоритизация
+- **Граничные случаи** — пустой ввод, нулевые значения, переполнение, отсутствующие поля
+- **Регрессии** — если баг был найден, тест фиксирует его до исправления
+
+Тест пишется в том же коммите, что и функциональность. Функциональность без теста (там где он обязателен) — неполный коммит.
+
+---
+
+## Когда тест не нужен
+
+Тест не пишется на код, где он не даёт ценности:
+
+- Геттеры и сеттеры: `func (s *Server) Port() int { return s.port }`
+- Конфиг-структуры и константы
+- Тривиальный клей: передача параметров, инициализация, dependency wiring
+- Логирование и форматирование вывода
+- HTTP-хендлеры без бизнес-логики (только роутинг и вызов сервиса)
+
+---
+
+## Структура теста
+
+Использовать стандартный Go `testing`. Табличные тесты (`[]struct{ ... }`) — когда случаев больше двух.
+
+```go
+func TestParseGPUSensor(t *testing.T) {
+ tests := []struct {
+ name string
+ xml string
+ want int
+ }{
+ {"normal", `290`, 29},
+ {"zero", `0`, 0},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := parseGPUTemp(tt.xml)
+ if got != tt.want {
+ t.Fatalf("got %d, want %d", got, tt.want)
+ }
+ })
+ }
+}
+```
+
+Фикстуры (XML, JSON, бинарные данные) — инлайн-константы или файлы в `testdata/`.
+Не использовать реальные сетевые вызовы и реальную БД в юнит-тестах.
+
+---
+
+## Мейнтейнс
+
+- Сломанный тест — чинится или удаляется в том же коммите где сломался.
+- Закомментированный тест — не допускается. Если тест неактуален — удалить.
+- Тест, проверяющий удалённую функциональность — удалить вместе с функциональностью.
+
+---
+
+## Инструкция для агентов (Codex, Claude)
+
+1. При добавлении функциональности — проверь по списку выше, попадает ли код в категорию "обязателен".
+2. Если да — напиши тест в том же коммите, без запроса подтверждения.
+3. Если нет — не пиши тест, не упоминай его отсутствие.
+4. При удалении функциональности — удали соответствующие тесты.
+5. При обнаружении закомментированных или сломанных тестов — удали или почини.