Тестирование в эпоху AI агентов ч2/3
...
Теперь к некоторым техникам.
Хочу поделится парой моментов.
‼️ Эфемерная БД: сейчас модно и молодежно использовать в проектах штуки типа Neon / Supabase. Это postgres но с сервисами. Гонять облачную БД для тестов - немного неспешно.
Возможное решение: эфемерной локальная БД. Мы поднимаем локальную БД докером, делаем для нее volume в оперативной памяти, и гоняем тесты в этой базе. Почему такой термин - эфемерная? Потому что как только отключим том или гасим докер, то база просто пропадает. Для тестов - самое оно. Раз в 8-10 быстрее бегает, чем с облачной БД. Рекомендую.
‼️ World ID. Задача: для каждого теста хотим свой набор данных, чтобы реализовывать задуманный сценарий с детерминированным состоянием БД. Хотим чтобы тесты выполнялись параллельно. Как обеспечить?
Предлагаю такое решение: небольшое "Начало" / мультиверс, а если без художественных аналогий, то "мягкое шардирование".
Мы добавляем в каждую табличку БД поле world-id, идентификатор "мира". И индексы PK каждой таблички переделываем на использование world-id + id. Для чтения используем WHERE world-id = нужный нам мир.
Суть в том, чтобы получить возможность параллельно хранить в БД разные наборы данных. Чтобы для каждого теста мочь быстро создать такой набор данных.
🟢 Плюсы такого подхода:
- создать мир ничего не стоит - просто новый ключ для world-id.
- нет заморочек с миграциями - используем одну БД;
- нет проблем с коннектами; используем основной коннект;
🔴 Минусы:
- в каждый запрос добавляем world-id;
- я обычно добавляю такую штуку в слой доступа к данным (repository pattern), чтобы это было автоматом и прозрачно; тогда использовать очень просто;
- можно использовать RLS (row level security) для автоматизации на уровне БД :
- ALTER TABLE users ENABLE ROW LEVEL SECURITY;
- CREATE POLICY isolate_worlds ON users USING (world_id = current_setting('app.current_world_id')::uuid);
- SET app.current_world_id = 'uuid-вашего-мира';
- ключи обязательно включают world-id, но я использую UUID как ключи - поэтому все проще;
- чистить БД чуть дольше, но эфемерную БД после тестов можно просто погасить, без очистки;
▶️ Альтернативные варианты:
* делать отдельные БД для каждого теста: жирновато и медленно - делаем БД, накатываем схему, накатываем сид; просто чистить - дропаем базу;
* делать отдельную схему для каждого теста - SCHEMAS (Namespaces); почти так же муторно как создавать БД, та же проблема с миграциями; зато для очистки простой DROP SCHEMA;
* транзакции - сложность с кодом, который использует транзакции, потому что вложенные транзакции это немного больно и надо переходить на SAVEPOINTS (и переделать все хуки если они имеются - по мне так рефакторинг немаленький); мне не очень подходит чтобы переделывать транзакции; сложность с обработкой запросов в разных подключениях, например в интеграционных тестах апи;
В общем, если важно быстро сделать новый мир - тогда world-id. В проде world-id всегда null.
...
...
Теперь к некоторым техникам.
Хочу поделится парой моментов.
‼️ Эфемерная БД: сейчас модно и молодежно использовать в проектах штуки типа Neon / Supabase. Это postgres но с сервисами. Гонять облачную БД для тестов - немного неспешно.
Возможное решение: эфемерной локальная БД. Мы поднимаем локальную БД докером, делаем для нее volume в оперативной памяти, и гоняем тесты в этой базе. Почему такой термин - эфемерная? Потому что как только отключим том или гасим докер, то база просто пропадает. Для тестов - самое оно. Раз в 8-10 быстрее бегает, чем с облачной БД. Рекомендую.
‼️ World ID. Задача: для каждого теста хотим свой набор данных, чтобы реализовывать задуманный сценарий с детерминированным состоянием БД. Хотим чтобы тесты выполнялись параллельно. Как обеспечить?
Предлагаю такое решение: небольшое "Начало" / мультиверс, а если без художественных аналогий, то "мягкое шардирование".
Мы добавляем в каждую табличку БД поле world-id, идентификатор "мира". И индексы PK каждой таблички переделываем на использование world-id + id. Для чтения используем WHERE world-id = нужный нам мир.
Суть в том, чтобы получить возможность параллельно хранить в БД разные наборы данных. Чтобы для каждого теста мочь быстро создать такой набор данных.
🟢 Плюсы такого подхода:
- создать мир ничего не стоит - просто новый ключ для world-id.
- нет заморочек с миграциями - используем одну БД;
- нет проблем с коннектами; используем основной коннект;
🔴 Минусы:
- в каждый запрос добавляем world-id;
- я обычно добавляю такую штуку в слой доступа к данным (repository pattern), чтобы это было автоматом и прозрачно; тогда использовать очень просто;
- можно использовать RLS (row level security) для автоматизации на уровне БД :
- ALTER TABLE users ENABLE ROW LEVEL SECURITY;
- CREATE POLICY isolate_worlds ON users USING (world_id = current_setting('app.current_world_id')::uuid);
- SET app.current_world_id = 'uuid-вашего-мира';
- ключи обязательно включают world-id, но я использую UUID как ключи - поэтому все проще;
- чистить БД чуть дольше, но эфемерную БД после тестов можно просто погасить, без очистки;
▶️ Альтернативные варианты:
* делать отдельные БД для каждого теста: жирновато и медленно - делаем БД, накатываем схему, накатываем сид; просто чистить - дропаем базу;
* делать отдельную схему для каждого теста - SCHEMAS (Namespaces); почти так же муторно как создавать БД, та же проблема с миграциями; зато для очистки простой DROP SCHEMA;
* транзакции - сложность с кодом, который использует транзакции, потому что вложенные транзакции это немного больно и надо переходить на SAVEPOINTS (и переделать все хуки если они имеются - по мне так рефакторинг немаленький); мне не очень подходит чтобы переделывать транзакции; сложность с обработкой запросов в разных подключениях, например в интеграционных тестах апи;
В общем, если важно быстро сделать новый мир - тогда world-id. В проде world-id всегда null.
...
❤🔥2🔥2👍1
Тестирование в эпоху AI агентов ч3/3
...
‼️ Агентный раннер. Всегда гоняю тесты "под агентом". Чем сложнее тесты, тем выгоднее гонять агентами. Если юнит тесты - это просто часть проверок в protocol из #deksdenFlow, то гонять сложные интеграционные тесты идеально агентами. По мне так чем сложнее тест, тем правильнее гонять его агентами.
Я делаю примерно так:
- пишу инструкцию по запуску теста: технически, что надо сделать чтобы запустить тест; в том числе - как поднять систему, как посмотреть что система корректно поднялась;
- обозначаю контрольные точки тестов в документе;
- агент запускает тесты, контролирует систему, решает мелкие проблемы с работой теста;
- агент контролирует прохождение теста; падение интеграционного теста - всегда повод для фиксов или рефакторинга;
- интеграционные тесты - самые хрупкие, так как очень много всего в них задействовано, агент помогает решать возникающие сложности, что надежнее чем просто детерминированный тест без агента;
- самая важная часть агента как раннера тестов - провести расследование отклонений в тесте: чтобы понять суть бага нужно грамотно и полно собрать информацию - агент это делает самостоятельно, особенно если его промптить именно на это;
- отчет агента об обнаруженных отклонениях с итогами проведенного расследования - это отличное начало для фикса бага.
▶️ Такие приемчики.
Остался еще один неописанный, но имеющийся блок - работа с UI тестами через штуки типа Playwright, но это отдельная большая тема.
В ближайшее время выберусь из бэкэнда и обновлю методику. Надо внимательно погонять разные MCP для контроля браузера, посмотреть как там data-testid поживает, сравнить с браузером в антигравити, посмотреть на новые мультимодальные модели. В общем, тема требует проработанного апдейта - поэтому в свое время.
(ц) вот такое мы практикуем!
#post
@deksden_notes
...
‼️ Агентный раннер. Всегда гоняю тесты "под агентом". Чем сложнее тесты, тем выгоднее гонять агентами. Если юнит тесты - это просто часть проверок в protocol из #deksdenFlow, то гонять сложные интеграционные тесты идеально агентами. По мне так чем сложнее тест, тем правильнее гонять его агентами.
Я делаю примерно так:
- пишу инструкцию по запуску теста: технически, что надо сделать чтобы запустить тест; в том числе - как поднять систему, как посмотреть что система корректно поднялась;
- обозначаю контрольные точки тестов в документе;
- агент запускает тесты, контролирует систему, решает мелкие проблемы с работой теста;
- агент контролирует прохождение теста; падение интеграционного теста - всегда повод для фиксов или рефакторинга;
- интеграционные тесты - самые хрупкие, так как очень много всего в них задействовано, агент помогает решать возникающие сложности, что надежнее чем просто детерминированный тест без агента;
- самая важная часть агента как раннера тестов - провести расследование отклонений в тесте: чтобы понять суть бага нужно грамотно и полно собрать информацию - агент это делает самостоятельно, особенно если его промптить именно на это;
- отчет агента об обнаруженных отклонениях с итогами проведенного расследования - это отличное начало для фикса бага.
▶️ Такие приемчики.
Остался еще один неописанный, но имеющийся блок - работа с UI тестами через штуки типа Playwright, но это отдельная большая тема.
В ближайшее время выберусь из бэкэнда и обновлю методику. Надо внимательно погонять разные MCP для контроля браузера, посмотреть как там data-testid поживает, сравнить с браузером в антигравити, посмотреть на новые мультимодальные модели. В общем, тема требует проработанного апдейта - поэтому в свое время.
(ц) вот такое мы практикуем!
#post
@deksden_notes
👍5🔥5❤🔥2
Ну и тут такой Z.ai выбегает со своим AI Slides - и такой: я тоже в теме!
Вот пруф: https://chat.z.ai/space/n093jap4utt0-ppt
Вот пруф: https://chat.z.ai/space/n093jap4utt0-ppt
👍1😁1
Jules теперь - свободный агент!
Omfg. Они отвязали агента от репо, и теперь с жульесом можно просто чатится! А там, напомню, снова Гемини 3 про.
Любопытно! Это получается тут под боком есть свободный агент, с vm впридачу, и без требования подключить репо... Это в очередной раз заставляет меня задуматься - а как бы его в оркестратор включить, как удаленную ноду! Масштабирование тогда дешевое и на чужих мощностях - круто же!
Ух.. Надо думать
https://jules.google/docs/changelog/#start-from-scratchinstantly
Omfg. Они отвязали агента от репо, и теперь с жульесом можно просто чатится! А там, напомню, снова Гемини 3 про.
Любопытно! Это получается тут под боком есть свободный агент, с vm впридачу, и без требования подключить репо... Это в очередной раз заставляет меня задуматься - а как бы его в оркестратор включить, как удаленную ноду! Масштабирование тогда дешевое и на чужих мощностях - круто же!
Ух.. Надо думать
https://jules.google/docs/changelog/#start-from-scratchinstantly
❤5🔥5
Background process manager proposal
▶️ Запускаю щас всякие процессы в разных LLM. Вообще жесть - из методики трекинга выполнения - только спамить запросами.
В лучшем случае - это sleep 60, чтобы подождать.
Не понимаю - почему нету тула правильного для отслеживания запущенных фоновых башей: ты пускаешь кучу процессов, единый менеджер их трекает. Родилась некая идея.
🟢 Менеджер устроен как тул (например, пакован в MCP). Когда модель запускает некий процесс - она обозначает чего ждать: либо ей сразу отдать сгенерированную строку, либо собирать логи в батч, либо логи игнорировать и ждать когда в логах встретится ключевая подстрока, либо дать когда процесс в терминал чего то спросит, либо вообще стримить терминал в модель. В общем - подумать в каких режимах нам запускать надо процессы. Может, при апдейтах отдавать Stdout / stderr - посмотреть чего там надо модели.
Менеджер процессов в итоге трекает все, и по этой логике чего то возвращает в модель. Можно сразу вызвать нужный тул - чтобы он подготовил следующую пачку данных.
Для логов сжелать хранение и обработку - чтобы можно было запрос делать к логам: по подстроке, по времени и тп.
В общем, какие то такие мысли! Надо при случае выгрузить в какого то PMa буржуйского CLI агента. Жаль это реализует скорее какой нибудь дроид/opencode чем gemini/codex
А пока мучамся в кодексе как в пустыне - нифига нету. Хорошо хоть модель изворотливая относительно.
#post
@deksden_notes
▶️ Запускаю щас всякие процессы в разных LLM. Вообще жесть - из методики трекинга выполнения - только спамить запросами.
В лучшем случае - это sleep 60, чтобы подождать.
Не понимаю - почему нету тула правильного для отслеживания запущенных фоновых башей: ты пускаешь кучу процессов, единый менеджер их трекает. Родилась некая идея.
🟢 Менеджер устроен как тул (например, пакован в MCP). Когда модель запускает некий процесс - она обозначает чего ждать: либо ей сразу отдать сгенерированную строку, либо собирать логи в батч, либо логи игнорировать и ждать когда в логах встретится ключевая подстрока, либо дать когда процесс в терминал чего то спросит, либо вообще стримить терминал в модель. В общем - подумать в каких режимах нам запускать надо процессы. Может, при апдейтах отдавать Stdout / stderr - посмотреть чего там надо модели.
Менеджер процессов в итоге трекает все, и по этой логике чего то возвращает в модель. Можно сразу вызвать нужный тул - чтобы он подготовил следующую пачку данных.
Для логов сжелать хранение и обработку - чтобы можно было запрос делать к логам: по подстроке, по времени и тп.
В общем, какие то такие мысли! Надо при случае выгрузить в какого то PMa буржуйского CLI агента. Жаль это реализует скорее какой нибудь дроид/opencode чем gemini/codex
А пока мучамся в кодексе как в пустыне - нифига нету. Хорошо хоть модель изворотливая относительно.
#post
@deksden_notes
👍1
Инструкции агентам
Немного ассоциаций!
Работая с агентами, я замечаю что часто начинаю общаться как в свое время с специфическими сотрудниками, знаете таких? Которые типа хитрые, но косят под простачков и могут сильно буквально исполнять инструкции. Типа "ну вы же сказали - ..." или "а нам никто не говорил, что ...", или, что хуже "а в инструкции сказано - ... ". Ведь даже такой вид забастовки есть - итальянская забастовка, когда работаем строго по инструкции.
В итоге, следишь за словами, за указаниями - чтобы и так, и эдак "не дать ему вывернутся".
▶️ Смешаные ощущения, конечно. Зато все больше убеждаюсь что отрасль движется в сторону большей доли менеджмента
У вас так же? Или это сугубо персональный контекст?
#post
@deksden_notes
Немного ассоциаций!
Работая с агентами, я замечаю что часто начинаю общаться как в свое время с специфическими сотрудниками, знаете таких? Которые типа хитрые, но косят под простачков и могут сильно буквально исполнять инструкции. Типа "ну вы же сказали - ..." или "а нам никто не говорил, что ...", или, что хуже "а в инструкции сказано - ... ". Ведь даже такой вид забастовки есть - итальянская забастовка, когда работаем строго по инструкции.
В итоге, следишь за словами, за указаниями - чтобы и так, и эдак "не дать ему вывернутся".
▶️ Смешаные ощущения, конечно. Зато все больше убеждаюсь что отрасль движется в сторону большей доли менеджмента
У вас так же? Или это сугубо персональный контекст?
#post
@deksden_notes
🔥5❤3👍3
Подписочки для OpenCode для Codex
Вот такую штуку нарыл:
🔗 https://github.com/numman-ali/opencode-openai-codex-auth
плагин для openCode чтобы работать через подписку Plus/Pro. прикольно!
‼️ Это некоторое нарушение TOS, поэтому на основном акке я бы не тренировался с такими сетапами! Аккуратно
🔥 Upd: openCode Desktop готовится! скрин в комментах
#post
@deksden_notes
Вот такую штуку нарыл:
🔗 https://github.com/numman-ali/opencode-openai-codex-auth
плагин для openCode чтобы работать через подписку Plus/Pro. прикольно!
‼️ Это некоторое нарушение TOS, поэтому на основном акке я бы не тренировался с такими сетапами! Аккуратно
🔥 Upd: openCode Desktop готовится! скрин в комментах
#post
@deksden_notes
GitHub
GitHub - numman-ali/opencode-openai-codex-auth: OAuth authentication plugin for personal coding assistance with ChatGPT Plus/Pro…
OAuth authentication plugin for personal coding assistance with ChatGPT Plus/Pro subscriptions - uses OpenAI's official authentication method - numman-ali/opencode-openai-codex-auth
Google UX
К версии 0.18.4 в Gemini CLI появился email того аккаунта, через который ты авторизован. Всего было 219 релизов на гитхабе.
Лучше поздно
В принципе, все консистентно - это гугл! Он такой. Что то мега-крутое сочетается с лютой дичью местами в UX...
(ц) такое мы принимаем в дзене, так как изменить не в состоянии
#post
@deksden_notes
К версии 0.18.4 в Gemini CLI появился email того аккаунта, через который ты авторизован. Всего было 219 релизов на гитхабе.
Лучше поздно
В принципе, все консистентно - это гугл! Он такой. Что то мега-крутое сочетается с лютой дичью местами в UX...
(ц) такое мы принимаем в дзене, так как изменить не в состоянии
#post
@deksden_notes
👍1
DeepSeek - 3.2
Новость в деталях обсказали уже все каналы и пара утюгов, я лишь добавлю: модель продолжает тренд на interleaved thinking режим как в минимаксе м2 и кими. Ну и свежих соннетах!
так что не даром они все предоставлют антропик-стиль апи!
interleaved thinking к слову, способствует более мощной агентности.
(ц) тренд, однака!
1️⃣Upd : контекст в 128к смотрится архаично! Но мощный ризонинг формально на уровне gemini 3 pro - заставляет задуматься, что получится когда они это все опробуют на R2.
Я так понимаю нам дают результаты экспериментов по отработке разных фишек в пайплайне - но на старой базе.
Ждемс v4 + r2. Уже испытываю повышенные ожидания!)
#post
@deksden_notes
Новость в деталях обсказали уже все каналы и пара утюгов, я лишь добавлю: модель продолжает тренд на interleaved thinking режим как в минимаксе м2 и кими. Ну и свежих соннетах!
так что не даром они все предоставлют антропик-стиль апи!
interleaved thinking к слову, способствует более мощной агентности.
(ц) тренд, однака!
1️⃣Upd : контекст в 128к смотрится архаично! Но мощный ризонинг формально на уровне gemini 3 pro - заставляет задуматься, что получится когда они это все опробуют на R2.
Я так понимаю нам дают результаты экспериментов по отработке разных фишек в пайплайне - но на старой базе.
Ждемс v4 + r2. Уже испытываю повышенные ожидания!)
#post
@deksden_notes
🔥4
Модель не справляется
▶️ Наблюдение, но подтверждается многократно. Отлаживаю оркестратор, гонял его на разных моделях и часто - второго эшелона. Glm, qwen и m2, например. Хорошие модели!
И в 100% случаев когда воркфлоу падал по причине ошибок агента, когда он что=то не то делал - оказывалось проблема в контексте. Противоречивые инструкции, взаимоисключающие инструкции, недостаточно ясные формулировки, отсутствие информации, битые отсылки и тп.
То есть - все дело в промпте и контексте! Модели с понятными заданиями с нормальным контекстом справляются уверенно
👉 Поэтому: если у вас модель лажает в таком месте, где по вашим ощущениям должна справится - то скорее всего есть причина, и ее реально найти.
👌 как искать? Глазами, если вы старовер. Ну и агентами: у меня "старшие" модели проводили расследование и указывали на противоречия или иные проблемные моменты контекста! Модели такое видят. Конечно, контекст им надо предъявить.
#post
@deksden_notes
▶️ Наблюдение, но подтверждается многократно. Отлаживаю оркестратор, гонял его на разных моделях и часто - второго эшелона. Glm, qwen и m2, например. Хорошие модели!
И в 100% случаев когда воркфлоу падал по причине ошибок агента, когда он что=то не то делал - оказывалось проблема в контексте. Противоречивые инструкции, взаимоисключающие инструкции, недостаточно ясные формулировки, отсутствие информации, битые отсылки и тп.
То есть - все дело в промпте и контексте! Модели с понятными заданиями с нормальным контекстом справляются уверенно
👉 Поэтому: если у вас модель лажает в таком месте, где по вашим ощущениям должна справится - то скорее всего есть причина, и ее реально найти.
👌 как искать? Глазами, если вы старовер. Ну и агентами: у меня "старшие" модели проводили расследование и указывали на противоречия или иные проблемные моменты контекста! Модели такое видят. Конечно, контекст им надо предъявить.
#post
@deksden_notes
👍7❤4
Claude Select
Нашел небольшую утилиту:
🔗 https://github.com/aeitroc/claude-select
A unified launcher for Claude Code that lets you interactively choose which LLM backend to use.
Выбираем какая модель будет "под капотом" у СС
Возможно, кому то будет удобно такое!
#link
@deksden_notes
Нашел небольшую утилиту:
🔗 https://github.com/aeitroc/claude-select
A unified launcher for Claude Code that lets you interactively choose which LLM backend to use.
Выбираем какая модель будет "под капотом" у СС
Возможно, кому то будет удобно такое!
#link
@deksden_notes
GitHub
GitHub - aeitroc/claude-select: A unified launcher for Claude Code that lets you interactively choose which LLM backend to use.
A unified launcher for Claude Code that lets you interactively choose which LLM backend to use. - aeitroc/claude-select
🔥4👍2
Kimi Slides - free до 07.дек
Собственно, сабж! Бесплано, до 07 декабря - продлили
Пока это самые симпатичные слайды выходят из протестированных мною (Google NotebookLM, Z.ai Slides)
Собственно, сабж! Бесплано, до 07 декабря - продлили
Пока это самые симпатичные слайды выходят из протестированных мною (Google NotebookLM, Z.ai Slides)
1❤4
Словарик терминов (upd)
обновление от декабря 2025 (в конце), 2 штуки:
🔗 https://t.me/deksden_notes/174
Перечитывать, учить, повторять перед сном!
▶️ Upd : да, апдейт к апдейту - в такое вот время живем. Третий термин
.
обновление от декабря 2025 (в конце), 2 штуки:
🔗 https://t.me/deksden_notes/174
Перечитывать, учить, повторять перед сном!
▶️ Upd : да, апдейт к апдейту - в такое вот время живем. Третий термин
.
Telegram
DEKSDEN notes
О терминах
Пару раз за последнее время заходила речь об используемых терминах / жаргонных наименованиях. Вопрос не самый первостепенный, но словарик постепенно сформируем. Это не исчерпывающий словарик AI терминов, но это про те термины, в которых были…
Пару раз за последнее время заходила речь об используемых терминах / жаргонных наименованиях. Вопрос не самый первостепенный, но словарик постепенно сформируем. Это не исчерпывающий словарик AI терминов, но это про те термины, в которых были…
👍3🔥3😁1
Ноябрь, итоги
Кодекс: 15B токенов, $3k по апи ценам
Глм c китами: 1.7b, $62
Средненький месяц
А сами смотрите свою статистику?
#post
@deksden_notes
Кодекс: 15B токенов, $3k по апи ценам
Глм c китами: 1.7b, $62
Средненький месяц
А сами смотрите свою статистику?
#post
@deksden_notes
🔥5😭4
Словарик, часть 2 (продолжение)
Начало тут: https://t.me/deksden_notes/174
🆕 - Киты : китайские фронтирные опенсорсные модели (DeepSeek, GLM, Kimi K2, MiniMAx M2); скорее уважительное;
Начало тут: https://t.me/deksden_notes/174
🆕 - Киты : китайские фронтирные опенсорсные модели (DeepSeek, GLM, Kimi K2, MiniMAx M2); скорее уважительное;
Telegram
DEKSDEN notes
О терминах
Пару раз за последнее время заходила речь об используемых терминах / жаргонных наименованиях. Вопрос не самый первостепенный, но словарик постепенно сформируем. Это не исчерпывающий словарик AI терминов, но это про те термины, в которых были…
Пару раз за последнее время заходила речь об используемых терминах / жаргонных наименованиях. Вопрос не самый первостепенный, но словарик постепенно сформируем. Это не исчерпывающий словарик AI терминов, но это про те термины, в которых были…
🔥3👍1
Opus - народу!
Свежий релиз СС (2.0.58), и:
... Add Opus 4.5 access for Pro users
OMFG, this is big! 💣 🔥 💥
Здравствуй подписка за 20 баксов )))
Что конкуренция животворящая исполняет!
#post
@deksden_notes
Свежий релиз СС (2.0.58), и:
... Add Opus 4.5 access for Pro users
OMFG, this is big! 💣 🔥 💥
Здравствуй подписка за 20 баксов )))
Что конкуренция животворящая исполняет!
#post
@deksden_notes
🔥10👍3