Files
progcode/editorial/agent-rewrites/109.json
T
huncode 2d914b543f
Build and deploy / deploy (push) Failing after 15s
Publish rewritten technical article archive
2026-08-02 22:19:34 +03:00

8 lines
18 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"index": 109,
"slug": "editorial-2024-12-field-maintenance-retro",
"title": "Год сопровождения: как решить, продолжить, остановить или перепроверить",
"excerpt": "Повторяемая ошибка в сопровождении редко требует немедленной переделки. Сначала отделите симптом от причины, назовите владельца риска и поставьте проверяемую границу для следующего действия.",
"contentHtml": "<p>В конце квартала список сопровождения выглядит знакомо: одна и та же ручная проверка, старый риск совместимости и задача на удаление, которую откладывают. Симптомы повторяются, но решение каждый раз начинается с нуля. Цена ошибки — не только лишний час инженера. Команда может удалить ещё используемый маршрут, принять риск без владельца или назвать договорённость исправлением.</p>\n<p>Тезис этой статьи простой: годовое сопровождение нужно вести как последовательность проверяемых решений. Для каждой проблемы сначала фиксируют симптом и границу, затем решают: продолжить узкий эксперимент, остановить рост области работ или перепроверить устаревшее свидетельство. Это не обещает результата в production. Такой порядок не даёт черновому решению получить права на изменение живой системы.</p>\n<h2>Начните с наблюдаемого симптома</h2>\n<p>Запись «в системе накопился технический долг» ничего не проверяет. Запись «при диагностике одного типа отказа инженер каждый раз ищет один и тот же параметр в трёх местах» уже задаёт наблюдение. У него есть действие, граница и возможный следующий шаг.</p>\n<p>Ретроспектива сопровождения не заменяет postmortem. Postmortem описывает подтверждённое событие, воздействие, причины и follow-up. Если инцидента не было, нельзя добавлять в текст ущерб, время восстановления или результат исправления. Для годового обзора достаточно назвать повторяемый симптом, неизвестное и решение, которое можно проверить отдельно.</p>\n<h2>Механизм: timeline и граница решения</h2>\n<p>Полезная карточка сопровождения содержит четыре точки. <code>T0</code> — наблюдение. <code>T1</code> — ограниченная гипотеза или эксперимент. <code>T2</code> — повторная проверка свидетельства. <code>T3</code> — решение продолжить, изменить формулировку или остановиться. Такая шкала не изображает календарь реальной команды. Она показывает порядок знаний.</p>\n<figure><img src=\"/assets/editorial/2024/maintenance-retro-2024-change-timeline.svg\" alt=\"Лента T0–T3: симптом, ограниченный эксперимент, повторная проверка границы и решение остановить, продолжить или изменить работу\" loading=\"lazy\"><figcaption>Схема показывает порядок проверки. Она не описывает реальные события, deployment или rollback.</figcaption></figure>\n<p>Граница решения отвечает на вопрос «что именно мы сейчас можем утверждать». Например, можно утверждать, что диагностический шаг повторяется в учебной карточке. Нельзя утверждать, что он уже уменьшил нагрузку на поддержку. Можно увидеть отсутствие роли-владельца. Нельзя считать риск принятым. Можно сохранить вопрос о восстановлении. Нельзя объявлять cleanup безопасным до проверки зависимостей.</p>\n<table><caption>Симптом → причина → проверка → действие</caption><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Причина</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>Один диагностический шаг снова объясняют вручную</td><td>У runbook нет явной границы остановки</td><td>Другой инженер находит symptom, check и stop condition по одной записи</td><td>Продолжить один узкий runbook-эксперимент</td></tr><tr><td>Риск совместимости описан, но owner не назван</td><td>Наблюдение приняли за решение</td><td>Проверить роль, которая может принять residual risk</td><td>Остановить расширение scope</td></tr><tr><td>Cleanup выглядит безопасным по старой карточке</td><td>Неизвестны consumers и путь восстановления</td><td>Перепроверить dependency graph, data conditions и restore boundary</td><td>Не переходить к удалению</td></tr><tr><td>В отчёте появился измеренный эффект без источника</td><td>Учебный вывод смешали с production-фактом</td><td>Найти trace, метрику, журнал или убрать утверждение</td><td>Оставить только подтверждённое наблюдение</td></tr></tbody></table>\n<h2>Три решения на одном годовом обзоре</h2>\n<h3>Продолжить: повторяемый пробел в runbook</h3>\n<p>Представьте учебную карточку: на трёх проверках инженер повторно спрашивает, где заканчивается диагностический путь. Это не доказывает частоту проблемы в реальной системе. Но факт повторения в карточке оправдывает небольшой эксперимент: добавить один boundary, один способ проверки и один stop condition.</p>\n<p>Эксперимент готов, если другой читатель проходит фиксированный failing path и получает тот же порядок действий без доступа к авторским пояснениям. Если задача разрастается до redesign поддержки или начинает обещать экономию времени, её нужно остановить и оформить как отдельное решение. Runbook не должен незаметно стать программой перестройки.</p>\n<h3>Остановить: риск без владельца</h3>\n<p>Вторая карточка описывает границу контракта, но не содержит роли, которая принимает остаточный риск. В такой ситуации фраза «продолжаем миграцию» подменяет решение намерением. Отсутствие известных consumers тоже не равно доказанному отсутствию consumers.</p>\n<p>Правильный следующий шаг — остановить рост области работ и задать один вопрос: кто может принять или отклонить утверждение о совместимости именно этой границы? Пока роль не названа и не имеет полномочий, карточка не должна переходить в rollout, removal или обещание обратной совместимости.</p>\n<h3>Перепроверить: cleanup ещё не план отката</h3>\n<p>Третья карточка выглядит спокойной: есть предложение удалить старый объект и короткое описание риска. Но неизвестны зависимости, совместимость данных и успешность восстановления. Слово «cleanup» скрывает изменение состояния. Его нельзя считать обратимым только потому, что действие кажется маленьким.</p>\n<p>Recheck должен назвать boundary, факт остановки и путь возврата. Для маршрута это может быть прежняя конфигурация и проверка ответа клиента. Для данных — совместимая схема и проверка чтения. Для зависимости — список потребителей и подтверждённый владелец. Если эти условия неизвестны, draft не превращается в rollback plan.</p>\n<h2>Учебный пример stop path</h2>\n<p>Ниже — намеренно маленькая модель. Она не читает репозиторий, не вызывает сеть, не выполняет deployment и не откатывает изменения. Её задача — показать, что решение остановиться меняет только статус черновика.</p>\n<pre><code>const card = {\n symptom: 'cleanup proposed',\n known: ['restore question exists'],\n unknown: ['consumers', 'data compatibility', 'rollback check'],\n};\n\nfunction plan(card) {\n const needsRecheck = card.unknown.length &gt; 0;\n return { decision: needsRecheck ? 'recheck' : 'continue', realChange: false };\n}\n\nconst draft = plan(card);\nconsole.log(draft.decision); // recheck\nconsole.log(draft.realChange); // false</code></pre>\n<p>Пример учебный. Он не определяет риск автоматически и не доказывает, что список неизвестных полон. В реальном проекте поля нужно связать с разрешёнными источниками, владельцем решения и конкретным тестом. Если код начинает сам удалять, менять или откатывать состояние, он вышел за границу этой модели.</p>\n<h2>Как отличить факт от решения</h2>\n<p>Факт можно показать другому человеку: записью события, конфигурацией, тестовым входом, ссылкой на код или повторяемым действием. Решение добавляет владельца и условие следующего шага. Гипотеза связывает факт с возможной причиной. Нельзя заменить один тип другим.</p>\n<pre><code>Факт: один шаг диагностики повторяется в учебной карточке.\nГипотеза: runbook не показывает boundary.\nПроверка: другой читатель проходит тот же failing path.\nРешение: продолжить один эксперимент, не менять production.</code></pre>\n<p>Если подтверждающего источника нет, пишите «неизвестно». Это полезнее, чем округлённая оценка. Неизвестное задаёт следующий вопрос. Выдуманная точность создаёт ложное разрешение на действие.</p>\n<h2>Порядок работы с одной карточкой</h2>\n<ol><li><strong>Сузьте scope.</strong> Оставьте один симптом и одну границу. Не объединяйте cleanup, миграцию и изменение контракта в одну карточку.</li><li><strong>Восстановите T0–T3.</strong> Для каждой точки запишите только известный артефакт и отдельный список неизвестного.</li><li><strong>Назовите цену ошибки.</strong> Укажите, что произойдёт при неверном решении: повторная ручная работа, отказ потребителя, потеря совместимости или невозможность восстановления.</li><li><strong>Проверьте owner boundary.</strong> Найдите роль, которая может принять риск или остановить действие. Если роли нет, остановите расширение scope.</li><li><strong>Выберите один исход.</strong> Continue оставляет ограниченный эксперимент. Revise меняет карточку после новой проверки. Stop отбрасывает draft до отдельного разрешённого решения.</li><li><strong>Запишите отрицательный путь.</strong> Укажите факт, который блокирует rollout, removal или обещание результата. Не заменяйте его словом «проверим позже».</li><li><strong>Повторите проверку.</strong> Используйте тот же вход и ту же границу. Если условия изменились, это новая карточка, а не тихое продолжение старой.</li></ol>\n<h2>Ограничения</h2>\n<p>Эта схема не измеряет надёжность и не ранжирует весь backlog. Она не заменяет incident response, change control, threat model, интеграционные тесты и право владельца на изменение системы. Один runbook-эксперимент не доказывает снижение toil. Один найденный owner не доказывает совместимость. Один restore question не доказывает успешный rollback.</p>\n<p>Учебные карточки, T0–T3 и код выше вымышлены. В статье нет production-метрик, истории конкретной команды, данных клиентов, deployment или результата исправления. Переносить вывод можно только после замены учебного входа фактическими источниками и проверки условий среды.</p>\n<h2>Проверяемый критерий готовности</h2>\n<p>Карточка готова к следующему решению, если читатель видит один наблюдаемый симптом, одну границу, цену ошибки, известное и неизвестное, роль владельца, отрицательный путь и один следующий эксперимент. Для cleanup дополнительно указаны зависимости, условия данных и проверка восстановления. Для риска без owner итогом должен быть stop, а не скрытое продолжение.</p>\n<p>Год сопровождения не закрывается красивым списком исправлений. Он закрывается набором границ, которые можно повторно проверить. Если новая проверка не может изменить решение, она не проверяет механизм.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://sre.google/sre-book/postmortem-culture/\" target=\"_blank\" rel=\"noopener noreferrer\">Google SRE Book: Postmortem Culture</a> — критерии postmortem, фиксация воздействия, причин и preventive actions; источник не подтверждает учебные карточки этой статьи.</li><li><a href=\"https://csrc.nist.gov/pubs/sp/800/40/r4/final\" target=\"_blank\" rel=\"noopener noreferrer\">NIST SP 800-40 Rev. 4: Guide to Enterprise Patch Management Planning</a> — официальная рамка preventive maintenance и планирования сопровождения; она не даёт разрешения на конкретное удаление или rollback.</li><li><a href=\"https://csrc.nist.gov/pubs/sp/800/30/r1/final\" target=\"_blank\" rel=\"noopener noreferrer\">NIST SP 800-30 Rev. 1: Guide for Conducting Risk Assessments</a> — официальный подход к фиксации угроз, воздействий и неопределённости; он не превращает оценки из примера в production-метрики.</li></ul>"
}