Баг был в семнадцатой строке.
Нет, не кот. Кот по имени Баг сидел дома и, вероятно, методично выгрызал угол дивана, как делал каждый раз, когда Глеб задерживался на работе. А баг — настоящий, программный — засел в функции валидации платёжных данных и уже третий час отказывался обнаруживаться.
Глеб Корнев откинулся на спинку офисного кресла — дешёвого, скрипучего, с продавленной сеткой на спинке — и потёр глаза. На мониторе расплывались строки Python-кода, а в правом нижнем углу экрана мигал Slack с пометкой «URGENT!!!» от менеджера проекта Кирилла. Три восклицательных знака. Кирилл всегда ставил три, даже когда спрашивал, где лежит степлер.
— Глеб, ты на созвоне будешь? — крикнул из-за перегородки Стёпа, джуниор-фронтендер, который искренне верил, что ежедневные стендапы делают команду сильнее. — Заказчик из Астаны опять хочет обсудить «концепцию».
— Буду, — соврал Глеб.
Он не собирался на созвон. Не потому, что был бунтарём или ленивым. Просто за четыре года в «ДиджиталСофт» он усвоил железное правило: если баг в проде, а ты на созвоне — виноват будешь дважды. За баг и за то, что не исправил, пока разговаривал.
Офис «ДиджиталСофт» занимал половину третьего этажа бизнес-центра «Меркурий» — единственного в Серовске здания, которое можно было назвать бизнес-центром без ироничных кавычек. Хотя нет, кавычки всё-таки напрашивались. Лифт работал через раз, горячая вода в туалете — только до обеда, а кофемашина на общей кухне выдавала нечто, что формально содержало кофеин, но по вкусу напоминало жидкость для мытья посуды, прошедшую через мотор «Жигулей».
Серовск вообще был городом, где всё работало «почти». Маршрутки ходили почти по расписанию. Фонари горели почти каждый вечер. Люди жили почти нормально. Полумиллионник на краю Урала, зажатый между федеральной трассой и рекой Серой, от которой и получил название. Ничего выдающегося. Ничего примечательного. Город, который можно проехать насквозь и не запомнить.
Глеб здесь родился, здесь вырос, здесь же, судя по всему, и состарится. Если раньше не убьёт кофемашина.
Он вернулся к коду. Семнадцатая строка. Функция принимает словарь, проверяет наличие ключей, валидирует формат... Всё правильно. Логически — безупречно. Но на тестовом сервере падает с ошибкой, которая не должна существовать.
«Как в жизни, — подумал Глеб. — Вроде всё делаешь правильно, а результат — Internal Server Error».
Он посмотрел на часы в углу монитора. 17:42. За окном уже темнело — ноябрь в Серовске не церемонился с световым днём, отрубая его где-то в районе четырёх. Офис постепенно пустел: Стёпа ушёл, даже не попрощавшись, Маша из бухгалтерии прошуршала пуховиком мимо его стола, кто-то из тестировщиков хлопнул дверью.
Глеб остался один. Он часто оставался один. Не из мизантропии — просто так получалось. Когда ты тихий, не пьёшь на корпоративах и не обсуждаешь футбол у кулера, люди перестают тебя замечать. Не враждебно, не демонстративно — просто ты становишься частью интерьера. Как принтер. Или та пальма в горшке, которую никто не поливает, но она почему-то до сих пор живая.
Телефон загудел. Сообщение от мамы: «Ты ел?» Глеб набрал «Да» и стёр. Набрал «Нормально» и стёр. Написал «Скоро поем» — отправил. Три слова — идеальный баланс между правдой и заботой о материнских нервах.
Он встал, потянулся — позвоночник хрустнул в трёх местах, как азбука Морзе от организма: «Хватит. Сидеть. Восемь. Часов.» — и подошёл к окну.
Третий этаж «Меркурия» выходил на проспект Строителей — главную артерию Нового берега. Внизу ползли машины, горели вывески «Пятёрочки» и «Красного & Белого», на остановке толпились люди в ожидании маршрутки, которая, может быть, придёт.
Глеб скользнул взглядом по привычному пейзажу — и остановился.
Небо было неправильным.
Не то чтобы грозовым или необычно тёмным — ноябрьское серовское небо и так представляло собой одну сплошную серую массу, как будто кто-то размазал мокрый бетон по потолку мира. Но сейчас в этой массе было нечто.
Тень.
Вертикальная.
Глеб моргнул. Прижался лбом к холодному стеклу, пытаясь рассмотреть получше. Тень была тонкая, тёмная — темнее облаков, темнее сумерек, темнее чего бы то ни было в ноябрьском небе. Она шла от земли вверх, сужаясь, как... шпиль. Или игла. Или трещина в экране реальности, через которую просвечивало что-то изнанки.
Она была далеко — где-то над центром города, над Старым берегом. И она была огромной.
Глеб простоял у окна, может быть, минуту. Может быть, пять. Тень не двигалась. Не мерцала. Просто была — абсолютно неподвижная вертикальная полоса тьмы посреди неба.
Он достал телефон и попытался сфотографировать. Экран показал обычное небо — серые облака, крыши домов, ничего больше. Глеб сделал ещё один снимок. И ещё. Тень на фото не появлялась.
— Ладно, — сказал он вслух. Пустой офис не ответил.
Он посмотрел на улицу. Люди на остановке стояли как обычно — уткнувшись в телефоны, переминаясь с ноги на ногу, ругаясь на маршрутку. Никто не смотрел вверх. Никто не показывал пальцем в небо. Никто не замечал.
«Или нечего замечать», — подумал Глеб.
Он отошёл от окна, сел обратно за стол и уставился в код. Семнадцатая строка. Прямо, Корнев. Соберись. У тебя баг в проде, дедлайн завтра, а ты пялишься в небо, как астролог на сессии.
Пальцы легли на клавиатуру. Глеб перечитал функцию. И вдруг увидел — не в небе, а в коде. Проблема была не в семнадцатой строке. Она была в двенадцатой. Невидимый символ — Unicode BOM, застрявший в начале строки после копирования из чужого файла. Символ, которого не видно глазом, но который ломал весь парсинг.
«Вот ты где, — мысленно произнёс Глеб, удаляя невидимку. — Прятался на виду».
Он запустил тесты. Зелёная полоса. Всё прошло. Коммит, пуш, сообщение в Slack: «Баг пофиксен. Был невидимый символ в двенадцатой строке. Тесты зелёные.»
Кирилл ответил через секунду: «Красавчик!!! Завтра на стендапе расскажешь!!!»
Три восклицательных знака. Как всегда.
На улице было минус восемь. Ветер с реки — тот особенный серовский ветер, который не просто холодный, а какой-то лично оскорблённый твоим существованием — ударил в лицо, едва Глеб вышел из «Меркурия».
До дома — пятнадцать минут пешком. Маршрутка — быстрее, но стоять на остановке в такой ветер означало замёрзнуть до состояния, когда уже неважно, приехала она или нет.
Глеб шёл быстрым шагом по проспекту Строителей, мимо «Пятёрочки» с вечно мигающей буквой «ч», мимо аптеки «Здоровье» (название звучало как насмешка над окружающей реальностью), мимо ларька с шаурмой, от которого шёл запах, вызывающий одновременно голод и экзистенциальные вопросы.
Он не смотрел вверх. Специально не смотрел.
Его дом — панельная шестнадцатиэтажка по адресу Строителей, 48 — стоял в глубине микрорайона, за «Магнитом» и детской площадкой, на которой никто не играл с октября. Подъезд встретил запахом кошек и сигарет, лифт — привычным стоном и рывком на девятый этаж.
Однушка. Тридцать шесть квадратов. Кухня пять метров. Балкон, который он использовал как морозилку с октября по апрель.
Баг — настоящий, рыжий, трёхлетний — ждал у двери. Не из любви. Из голода. Кот посмотрел на Глеба с выражением, которое можно было перевести как «Ты что, совсем?» — и требовательно мяукнул.
— Знаю, знаю, — Глеб скинул куртку, ботинки и пошёл на кухню.
Корм в миску. Чайник на плиту. Пельмени из морозилки (с балкона). Ужин человека, который может написать нейросеть для распознавания образов, но так и не научился готовить что-либо сложнее яичницы.
Пока пельмени булькали в кастрюле, Глеб открыл ноутбук и полистал новости. Ничего интересного. Курс доллара опять полез. Какой-то депутат сказал что-то глупое. Сериал, который он смотрел, продлили на второй сезон — единственная хорошая новость за день.
Он открыл местный паблик «Серовск | Новости». Пост про ремонт дороги на Ленина. Пост про собак у мусорки. Пост: «Кто видел странную хрень в небе???»
Глеб замер.
Пост был от пользователя «Дима_Серовск_228». Текст: «Выходил покурить на балкон, смотрю — а в небе какая-то палка торчит. Типа антенна, только огромная. Может, военные что-то строят? Или мне кажется?»
Три комментария. Первый: «Ты обкурился, Дима)))) еби спать». Второй: «Фото?» Третий от Димы: «Не снимается на фото!!! Я серьёзно!!!»
Глеб медленно закрыл ноутбук. Посмотрел на окно. За стеклом — ночной Серовск, огни панелек, тёмное небо.
Он не хотел подходить к окну. Прямо сейчас, в этот конкретный момент, Глеб Андреевич Корнев, двадцати восьми лет, backend-разработчик, кормилец одного рыжего кота, хотел только одного: съесть пельмени, посмотреть серию и лечь спать.
Потому что пока он не подошёл к окну — всё можно было списать на усталость, на оптический обман, на проделки невидимых символов в коде реальности.
Баг запрыгнул на подоконник и уставился в темноту. Его зрачки расширились до предела.
— Ну что ты там увидел? — спросил Глеб кота. Кот не ответил. Он кот.
Глеб встал.
Подошёл к окну.
И увидел.
Шпиль стоял посреди города.
Не тень. Не намёк. Не оптическая иллюзия уставшего мозга. Шпиль — чёрный, массивный, абсолютный — поднимался откуда-то из района Старого берега и уходил вверх, в облака, и дальше, за облака, туда, где его верхушка терялась в непроглядной ноябрьской тьме.
Днём это была тень. Сейчас — объём. Чёрная поверхность не отражала свет фонарей. Не отражала свет луны. Не отражала ничего. Как будто кто-то вырезал из мира прямоугольник и оставил пустоту.
Но не совсем пустоту. Если смотреть долго — а Глеб смотрел долго, забыв про пельмени, забыв про всё — можно было заметить тонкие линии на поверхности. Бирюзовые. Едва различимые. Они шли вертикально, иногда ветвились, как вены. Или как трещины в чёрном камне, сквозь которые просвечивал другой свет.
Не электрический. Не природный. Другой.
Глеб стоял у окна. Баг сидел на подоконнике. Оба смотрели.
В голове было пусто — как бывает, когда реальность выдаёт такую ошибку, что мозг вместо паники уходит в синий экран. Нет интерпретации. Нет реакции. Просто наблюдение.
Рука сама потянулась к телефону. Камера, фото, фото, ещё фото. На экране — ночной Серовск. Панельки. Небо. Ни одного Шпиля.
Глеб перевёл взгляд с телефона на окно. Шпиль стоял. Посмотрел в телефон. Шпиля нет. Окно — есть. Телефон — нет.
— Интересно, — сказал он.
Голос прозвучал нормально. Руки не дрожали. Сердце билось чуть быстрее обычного, но не колотилось. Глеб удивился собственному спокойствию — и тут же понял, почему он спокоен.
Потому что паника — это реакция на то, что ты не можешь контролировать и не можешь понять. А он — он привык к багам. К системным сбоям. К вещам, которые не должны существовать, но существуют. Каждый день, восемь часов в день, четыре года подряд.
Баг в семнадцатой строке оказался в двенадцатой. Невидимый символ, ломающий всю систему. Прятался на виду.
Шпиль посреди города, которого не видят камеры и не замечают люди.
«Тот же принцип, — подумал Глеб. — Что-то есть, но не регистрируется стандартными средствами. Значит, проблема не в объекте. Проблема в средствах регистрации».
Он постоял ещё минуту. Шпиль не исчез. Не мигнул. Не пошевелился. Стоял — как стоял, вероятно, уже несколько часов, а может, и дней. Просто раньше Глеб не смотрел достаточно внимательно.
А Дима_Серовск_228 — смотрел.
Глеб вернулся на кухню. Пельмени разварились в бесформенную массу. Он съел их всё равно — залив сметаной и кетчупом, маскируя кулинарную катастрофу, как обычно маскировал всё неприятное в жизни. Вымыл тарелку. Покормил Баг ещё раз — кот смотрел так, будто его не кормили неделю, и Глебу было проще сдаться, чем спорить.
Почистил зубы. Лёг в кровать. Достал телефон.
Открыл «Серовск | Новости». Пост Димы удалён. Или утонул. Глеб пролистал — нет, удалён. Ни одного упоминания странного объекта в небе.
Открыл Telegram. Чаты — рабочий, семейный, «Серовск — ЧП». В последнем — тишина. Ни одного поста о Шпиле.
Открыл Google. Набрал: «странный объект в небе Серовск». Ноль результатов.
«Ладно», — подумал Глеб.
Закрыл телефон. Закрыл глаза. Баг устроился в ногах, свернувшись тёплым рыжим кольцом.
«Надо к окулисту записаться, — подумал Глеб. — И к психиатру. На всякий случай».
Он уснул быстро. Обычно засыпал долго, прокручивая в голове рабочие задачи, непрочитанные сообщения, невыполненные обещания. Но сегодня уснул за минуту, будто мозг решил: хватит, квота на обработку информации исчерпана, уходим в спящий режим.
Он проснулся в 3:17.
Не от звука. Не от света. Не от кошмара.
От ощущения.
Как будто кто-то положил ладонь ему на затылок — но не физически, а... внутри. Где-то между мыслями и сном, в том месте, где обычно звенит тишина, появился звук. Тихий, ровный, постоянный. Как гул серверной. Как шум дата-центра за закрытой дверью. Белый шум, у которого была структура.
Глеб сел в кровати. Баг не спал — сидел на подоконнике, уставившись в окно, и его хвост мерно двигался из стороны в сторону. Не игриво. Напряжённо.
Гул не прекращался. Глеб прислушался. Звук шёл не из-за стены, не с улицы, не из трубы отопления. Он шёл изнутри. Из головы. Как если бы внутри черепа заработал крошечный вентилятор охлаждения.
«Мне двадцать восемь, — подумал Глеб. — Рано для инсульта. Наверное».
Он встал и подошёл к окну. Баг потеснился, не отрывая взгляда от темноты.
Шпиль стоял.
Но сейчас он был другим.
Бирюзовые линии на его поверхности стали ярче. Намного ярче. Они пульсировали — медленно, ритмично, как сердцебиение. И с каждым пульсом гул в голове Глеба усиливался на долю секунды, а потом стихал. Синхронно.
Он стоял у окна, а Шпиль пульсировал, и гул пульсировал вместе с ним, и Глеб понял одну очень простую вещь, от которой ему стало очень холодно.
Шпиль знал, что на него смотрят.
И отвечал.
* * *
Глеб не отошёл от окна. Не задёрнул шторы. Не вернулся в кровать.
Он смотрел на Шпиль, а Шпиль — если это можно было назвать «смотреть» — смотрел на него.
Гул выровнялся. Стал тише, ровнее. Почти комфортным. Как фоновая музыка, которую перестаёшь замечать через десять минут.
Баг мяукнул. Негромко, коротко. Не требовательно и не испуганно. Скорее — констатируя.
«Да, — подумал Глеб. — Я тоже это вижу».
Он потянулся за телефоном. Не для фото — уже понял, что бесполезно. Открыл заметки. Набрал:
«1. Объект виден с вечера. На фото не фиксируется. 2. Виден мне и минимум одному другому человеку (Дима, паблик). 3. Пост Димы удалён — кем? 4. Пульсация ночью. Возможная реакция на наблюдение. 5. Звук в голове — синхронен с пульсацией. Субъективный? Физический? 6. Кот тоже видит».
Он перечитал список. Шесть пунктов. Чётко. Структурно. Как тикет в Jira.
И добавил седьмой:
«7. Записаться к окулисту. И к психиатру. Серьёзно».
За окном Шпиль продолжал пульсировать. Тихо. Терпеливо. Как что-то, у чего есть всё время в мире.
Глеб положил телефон. Посмотрел на часы: 3:24.
Завтра четверг.
Нет. Уже четверг.
Просто четверг.
Буду рад вашей подписке и комментарию!