DarkRiDDeR14 мин

Год сопровождения: что остановить, что продолжить, что перепроверить

НадёжностьПрактика

Год сопровождения легко превратить в историю с аккуратным финалом: «мы нашли долг, исправили процесс и стали устойчивее». Такая фраза опасна, если под ней нет timeline, evidence boundary и отдельного решения, что именно остановили. Цена ошибки — следующий квартал начинает с ложной уверенности: cleanup уже считают безопасным, ownership считают назначенным, а повторяемый symptom считают закрытым, хотя была только договорённость на встрече.

Поэтому ниже нет ретроспективы неизвестной команды и нет выдуманных incidents, savings или метрик. Вместо этого три fixed synthetic cases. Они нужны как полевая тренировка decision flow: один case требует продолжить маленький runbook experiment, второй — остановиться на owner boundary, третий — перепроверить cleanup до разговора об удалении. Все даты в timeline — T0–T3, а не история реальной системы.

В этой статье timeline — последовательность точек T0–T3, а не календарь команды; case — учебная карточка; recheck — повторная проверка границы; stop — прекращение черновика до отдельного решения. Fixed synthetic означает, что примеры записаны в коде и не описывают реальный сервис. Термины нужны только для различения состояний одной проверки.

Сначала соберите timeline изменения, а не список впечатлений

Timeline отвечает на четыре простых вопроса: что было замечено, какое ограниченное изменение знания предложено, где его нужно перепроверить и что происходит, если scope растёт. Без этих точек «в прошлом квартале решили» становится доказательством само по себе. С timeline видно, что decision был только draft, а не выполненный deploy; recheck был условием, а не подтверждённым результатом.

Горизонтальный timeline T0–T3: capture symptom, draft one experiment, recheck evidence boundary, decide stop, continue or revise for the next quarter. Под всеми точками стоит запрет превращать synthetic review в production change.
Timeline показывает порядок знаний, а не хронологию реальных событий. Каждая точка имеет отдельный смысл: наблюдение, draft, recheck и решение.
Три fixed synthetic case для годового review
CaseЧто зафиксированоЧто не известноВердикт следующего шага
repeated-runbook-gapповторяемый manual explanation и отсутствующая diagnostic boundaryреальная частота, пользовательский эффект и усилие реализацииcontinue: один bounded runbook experiment
ownerless-compatibility-riskrisk у contract boundary и пустая принимающая рольреальные consumers, traffic и право на принятие рискаstop scope growth: сначала owner question
recheck-before-removalcleanup-shaped proposal и сохранённый restore questiondependency graph, data compatibility и успешность rollbackrecheck before human removal review

Case 1. Продолжить: repeated runbook gap

Первый case не говорит, что runbook в реальном сервисе плохой. В fixed card есть только observation: один diagnostic step приходится снова объяснять на трёх synthetic review points. Риск узкий — reviewer может не знать, где прекращать проверку. Цена выражена классом: repeated interrupt и slower review. Этого достаточно, чтобы продолжить one experiment, но недостаточно для решения о переписывании support process.

Действие также узкое: записать один diagnostic boundary и прогнать его по fixed failing path. Ожидаемый evidence — другой reviewer может назвать symptom, boundary, check и stop condition без обращения к реальной системе. Если note разрастается до redesign или начинает утверждать, что он уменьшит actual support load, срабатывает stop condition. Draft возвращается к текущей карточке, а новый scope оформляется отдельно.

Case 2. Остановить: риск есть, owner boundary нет

Во втором case важен не score, а отсутствие роли, которая принимает residual risk. У карточки есть compatibility boundary и фиксированное описание опасности. Но не существует реального списка consumers и нет права угадать их отсутствие. Если команда на этой точке пишет «продолжаем миграцию», она заменяет решение по риску намерением.

Правильное действие — остановить расширение scope и задать один question: какая role может accept или reject statement о residual risk для одного contract boundary? Это не перекладывание работы на формального owner. Это способ отделить исследование от решения. Пока role не названа или не может принять вопрос, timeline не должен переходить в removal, rollout или обещание совместимости.

Case 3. Перепроверить: cleanup ещё не rollback plan

Третий case выглядит спокойнее: fixed score попадает в watch-and-recheck, есть action, похожий на cleanup, и сохранена restore question. Именно здесь легко назвать карточку «низким риском» и пропустить recheck. Но синтетическая карта прямо говорит другое: evidence labels старые, а real dependency graph, data compatibility и rollback success неизвестны.

Поэтому результатом является recheck gate. Он спрашивает: какая boundary будет повторно проверена, какой факт остановит proposal и куда вернуться до реального change? Ответ «у нас есть rollback» не проходит, пока неизвестно, кто восстановит route, какие data/schema conditions сохранятся и как проверить client recovery. В этой статье stop operation только отбрасывает draft; она не откатывает deployment и не читает систему.

Компактный учебный прогон stop path

Следующий пример показывает именно эту разницу. В нём draft создаётся из canonical fixed report, затем безопасно останавливается. Это не test production rollback. Его задача — проверить форму review: change proposal не должен получить скрытое право на deploy, delete или network request.

import {
  createFixedSyntheticMaintenanceInput,
  inspectSyntheticMaintenance,
  planSyntheticMaintenanceReview,
  stopSyntheticMaintenanceReview,
} from './upgrade-2024-12.mjs';

const report = inspectSyntheticMaintenance(
  createFixedSyntheticMaintenanceInput('recheck-before-removal'),
);
const draft = planSyntheticMaintenanceReview(report);
const stopped = stopSyntheticMaintenanceReview(draft);

console.log(draft.decision.code); // keep-visible-and-recheck-before-expansion
console.log(stopped.stopped);      // true
console.log(stopped.realChange);   // no-system-change

Fixture покрывает отрицательные ветки: extra keys, missing report field, forged score, sparse nested array, cyclic report, sparse actions и cyclic draft. Все такие objects должны быть rejected without throw. Это редакторская защита от очень знакомого сбоя: summary выглядит тем же, но внутри уже появился факт или action, которые модель не умеет обосновать.

Reassessment loop: не все продолжения одинаковы

После T2 задача не получает автоматически статус done. Есть три допустимых исхода. Continue означает оставить одну bounded experiment до следующего review. Revise означает изменить card, потому что evidence boundary или owner question стали точнее. Stop означает отбросить draft до отдельного решения, потому что scope вырос или need for external evidence стал очевиден. None of these is a production outcome. Это только порядок работы с knowledge.

Decision после recheck
СостояниеЧто сохраняемЧто останавливаемПлан следующего квартала
Continueone experiment, owner question и current boundaryрост scope за пределы cardпроверить ожидаемый artefact на следующем review point
Reviseисходный symptom и known evidenceстарую формулировку риска или actionпереписать card, затем снова пройти human review
Stoplast documented boundary и explicit unknowndraft, который обещает change или полноту данныхоткрыть отдельное authorized investigation или сохранить compatibility

Что взять из года, а что не переносить

Продолжать стоит только то, что оставляет воспроизводимый artefact: короткий runbook boundary, owner question, recheck gate, stop condition. Останавливать стоит ложную точность: всеобщую формулировку «долг закрыт», округлённый score без inputs, обещание rollback без restore boundary. Перепроверять стоит место, где evidence стареет или scope меняется: contract, config, data migration, dependency или decision owner.

Здесь полезна рамка preventive maintenance из NIST SP 800-40: идентификация, приоритизация, внедрение и verification не должны склеиваться в один глагол «исправить». Наша timeline признаёт только первые два и preparation for recheck. Реальные внедрение и verification требуют иного контекста: права, тесты, change controls, зависимости и измерения. Нельзя добавлять их задним числом в retrospective paragraph.

План следующего квартала должен быть уже прошлогоднего списка

Хороший next-quarter plan короче исходного maintenance list. В него входят one card per boundary, owner role, next experiment, recheck condition и stop condition. Если в плане есть «улучшить платформу», «устранить риски» или «сделать cleanup», он ещё не готов. План должен позволять на следующем review увидеть разницу: появилась ли boundary, принят ли question, описан ли recheck.

Шаблон plan на следующий квартал
ПолеКороткая формаКритерий готовности
Cardодин symptom и один boundaryreader не додумывает scope из заголовка
Owner rolerole для одного decision questionrole может принять, отклонить или передать вопрос
Experimentодин review artefactрезультат не требует live deployment
Recheckone observable conditionпонятно, когда card вернётся на review
Stopone fact that blocks scope growthdraft можно отбросить без ложного rollback claim

Короткий порядок закрытия года

  1. Сузьте scope. Выберите одну карточку и не объединяйте её с архитектурной программой или миграцией.
  2. Восстановите T0–T3. На каждой точке оставьте только known artefact и явно назовите unknown.
  3. Сверьте stop rule. Если draft обещает deployment, deletion или полноту данных, остановите его до следующей встречи.
  4. Выберите один исход. Continue, revise или stop должны менять только план review, а не состояние живой системы.
  5. Запишите следующий recheck. Он должен проверять конкретную boundary, owner question или evidence label в следующем квартале.

Почему maintenance retro не заменяет postmortem

Google описывает postmortem как запись события, его воздействия, причин, ответа и follow-up. Maintenance retro похож тем, что фиксирует обучение и следующий шаг, но не должен притворяться incident analysis. Если не было подтверждённого incident, нельзя писать последствия. Если нет timeline с evidence, нельзя придумывать recovery. Мы берём структуру ответственности и follow-up, а не чужую историю и цифры.

То же относится к toil. Повторяемая ручная работа может быть кандидатом на устранение источника, но не всякая ручная проверка является waste. Некоторые ручные проверки нужны именно потому, что boundary зависит от риска и полномочий. Поэтому fixed model предлагает не «автоматизировать всё», а сначала установить, какая часть действия повторяется без создания нового знания.

Ограничения и следующий проверяемый шаг

Три cases, T0–T3, labels, roles, scores, actions, stop rules и expected outcomes существуют только как versioned fixed in-memory objects. Они не используют исходный код, историю команды, deployment, production telemetry, tickets, logs, customer data, incident archive, Git, files, CI или network. Источники не подтверждают, что какая-либо конкретная система имеет такие же риски или что любой rollback сработает.

Следующий шаг: выберите одну завершённую или остановленную maintenance task и восстановите только четыре точки T0–T3 из памяти и разрешённых artefacts. В каждой точке разделите known от unknown. Если action обещает real change, добавьте stop condition и вынесите его в отдельный authorized plan. Ожидаемый результат: следующий квартал получает не праздничный список, а одну короткую проверяемую границу для каждого выбранного item.

Историческая граница декабря 2024

В материале использованы официальные главы первого издания Google SRE Book (2016), NIST SP 800-30 Rev. 1 от сентября 2012 года и NIST SP 800-40 Rev. 4 от апреля 2022 года. Все источники появились до декабря 2024. Они поддерживают дисциплину learning, risk-informed action и preventive maintenance, но не доказывают synthetic timeline и не дают разрешения на реальное изменение.

Проверяемые источники

  • Google SRE Book, Chapter 15: Postmortem Culture: Learning from Failure, first edition 2016 — Первичный официальный текст Google. Он описывает postmortem как запись влияния, причин, действий и follow-up, а также требует заранее определять триггеры. Он не предписывает конкретный backlog score, состав команды или частоту годового review.
  • Google SRE Book, Chapter 5: Eliminating Toil, first edition 2016 — Первичный официальный текст Google. Он отличает повторяемую ручную операционную работу от устойчивой инженерной ценности и показывает, почему источник toil полезно устранять, а не только фиксировать. Он не даёт универсальной оценки цены одного maintenance item.
  • NIST SP 800-30 Rev. 1: Guide for Conducting Risk Assessments, final September 2012 — Официальная финальная публикация NIST. Она задаёт риск-оценку как вход для выбора курса действий и требует учитывать контекст и неопределённость. Она не утверждает, что произведение нескольких баллов является достоверной вероятностью.
  • NIST SP 800-40 Rev. 4: Guide to Enterprise Patch Management Planning, final April 2022 — Официальная финальная публикация NIST. Она описывает preventive maintenance как идентификацию, приоритизацию, внедрение и проверку обновлений. Она не заменяет локальные ownership rules, change approval или проверку конкретной системы.