Ответ лежал в системе 51 день
Заводя находку «есть сайт вне зон, и пересечение тем никто не сравнивал», мы ошиблись дважды. Документ от 10.06 говорил жёстче: одну и ту же тему делят три наших сайта, вывод сформулирован как «выбрать ОДИН из трёх». Правило проекта велит перед задачей прогонять поиск «не делали ли это уже». Прогнали задним числом на том же запросе — не поймал бы.
| Причина молчания | Механика | Починка |
|---|---|---|
| Доска читалась с диска | рабочее дерево стояло на чужой ветке: 591 задача против 996 в общей, и задача владельца от 29.07 просто не существовала для поиска | чтение состояния только из общей ветки |
| Стеммер не знал прилагательных | в списке окончаний не было -ый/-ым/-ых, поэтому «паразитный» не сходился с «паразитным» | окончания добавлены |
| Область поиска — один каталог | системные документы фабрики сайтов не сканировались вообще, а стратегический слой лежит там; окно поиска 45 дней, документу было 51 | область расширена, окно перестало отсекать неустаревающее |
| Читались первые 1200 символов | нужное упоминание почти всегда в середине файла, а не в шапке | читается 20 000 символов |
Каждой причины хватило бы в одиночку — и это типично: у инструмента поиска нет способа сообщить «я посмотрел не туда». Ответ «ничего не найдено» выглядит одинаково при пустой базе, сломанном стеммере и неверной области.
Две поведенческие правки, которые важнее кода
Кроме четырёх причин мы поменяли то, как инструмент разговаривает:
- Открытая задача теперь тоже даёт «следы есть». Раньше найденная живая задача показывалась в выводе, а итоговая строка печатала «работа новая» — и дубль заводился поверх неё. Заголовок читают, тело списка — нет.
- Найденное ранжируется по плотности упоминаний. Широкий запрос выдавал 135 файлов; список такой длины перестают читать целиком, и он равен пустому.
Приёмка поисковика — три прогона, а не один. (а) Запрос по реальной задаче обязан дать «следы есть» и показать саму задачу. (б) Запрос по заведомо выдуманной теме — «интеграция криптоплатежей биткоин» — обязан остаться чистым, иначе инструмент просто кричит на всё. (в) Широкий запрос: сверху должны идти профильные документы, а не случайные.
Один прогон из трёх ничего не доказывает: зелёный на реальном запросе бывает у инструмента, который срабатывает всегда, а чистый на выдуманном — у того, который молчит всегда.
Ссылка внутри отчёта — такой же факт, как число
В сводке зоны колонка «Вердикт» отправляла исполнителей в пакеты «П5, П9», хотя раздел назначений того же файла содержал только П1–П8, а по содержанию нужны были П4 и П7. Сбита была вся колонка целиком: работа по фабрике сайтов уезжала в П7 вместо П6, свод незалитых веток — в П6 вместо П5, раздел решений — в П4 вместо П3.
Почему это опаснее ошибки в факте. Факты в отчёте были верны, значит доверие к нему высокое — и исполнитель по такой ссылке молча уходит в чужой пакет, к чужим файлам. Ровно так ломается правило непересечения зон, причём обе стороны уверены, что действуют по инструкции.
Правило, которое мы из этого поставили: в документе, который читают исполнители, голый номер запрещён — только «П5 (инструменты и проверки)». Номер без темы невозможно опровергнуть на глаз, номер с темой опровергается сразу же, как только тема не совпала с остатком работы.
Идентификатор, который меняется под руками
Журнал уроков пишут четыре человека одновременно, и нумерация разделов конфликтует при каждой отправке. Один и тот же урок ехал в общую ветку как У7, потом У8, потом У10 и приехал У13 — три перебазирования подряд, пока соседи занимали номера. Всё это время на него уже стояли ссылки.
- Перед дописыванием — забрать свежую общую ветку и брать номер от максимума в ней, а не в своей копии.
- При конфликте — оставлять чужие разделы и сдвигать свои.
- Не разрешать такой конфликт выбором одной стороны целиком. Любая из сторон теряет чужой урок полностью, и потеря выглядит как чистое слияние: ни красного, ни следа.
Отсюда же общий вывод про ссылки: пока идентификатор нестабилен, ссылаться надо на тему, а не на номер. Номер удобен пишущему и бесполезен читающему.
Что мы из этого сделали
- Поиск по своей базе знаний принимается как прибор: позитивный контроль, негативный контроль, проверка порядка выдачи. До этой приёмки его ответ «новое» не считается ответом.
- Область и глубина чтения — часть настройки, а не деталь реализации. Каталог, который не сканируется, и хвост файла, который не читается, дают одинаковый результат: знание есть, доступа нет.
- Ссылки в рабочих документах проверяются как факты: пройти по каждой и убедиться, что адресат существует и его тема совпадает с тем, что туда отправляют.
- Общие файлы знаний пишутся с расчётом на одновременных авторов: номер берётся от общей ветки, конфликт разрешается слиянием обоих кусков.
Проверка «а не решали ли мы это уже» окупается только вместе с приёмкой самой проверки — иначе она добавляет уверенности, не добавляя знания.