Поиск по разделам v1

Перевод для чтения человеком. Сверен с английским оригиналом ревизии 61e75e9 (на английском). Перевод не является новой редакцией нормативного контракта. Текущая английская страница.

okf search <bundle> --query TEXT [--limit N] [--json] и MCP-инструмент search_sections используют общий Go-пакет retrieval. Они добавлены к существующим интерфейсам; search_concepts сохраняет контракт поиска буквальной подстроки.

Вход: доступный для чтения набор документов, запрос из 1–512 символов Unicode, содержащий хотя бы одну букву или цифру, limit от 1 до 100 (по умолчанию 20). Разрешено не более 32 различных терминов. Каждый нормализованный термин ограничен 4096 символами Unicode независимо от ограничения исходного запроса: приведение регистра может увеличивать число символов, например для ß. Выделение терминов применяет приведение регистра по правилам Unicode и нормализацию NFC, разделяя по всему, кроме букв, цифр и комбинируемых знаков. Повторяющиеся термины удаляются. Все термины должны встречаться в исходном Markdown раздела, его заголовке или названии понятия (AND). Нет выделения основ слов, синонимов, перевода, регулярных выражений, семантического поиска или удаления стоп-слов. Markdown-код доступен поиску как пассивный текст; псевдозаголовки внутри ограждённых блоков никогда не создают разделы. Зарезервированные файлы index.md/log.md служат навигации и исключены из поиска.

Разделы — непересекающиеся диапазоны: вступление, затем каждый заголовок, распознанный разборщиком, до строки перед следующим заголовком. Пустые диапазоны пропускаются. Заголовки, включая Setext и вложенные уровни, определяются AST Goldmark; границы метаданных — общим разборщиком documentlayout. Строки источника считаются с 1 по физическим разделителям LF в исходном захваченном файле (CRLF считается одной строкой); обе границы включены. Заголовок принадлежит своему разделу. Документ без заголовков имеет один раздел тела. Заголовок и название ограничены 1024 байтами UTF-8 каждый.

Ранжирование использует BM25, k1=1.2, b=0.75 по разделам с весами частоты термина: исходный Markdown раздела — 1, заголовок — 3, название понятия — 2. Документная частота — число разделов, содержащих термин; длина — сумма взвешенных частот. Оценки идут по убыванию; равные оценки упорядочиваются по идентификатору понятия, затем по начальной строке. Оценки показывают только лексическую релевантность. Достоверность, наличие проверки и актуальность не выводятся автоматически.

Выход: query, нормализованные различные термины, snapshot_revision, total, truncated и hits. Каждый результат содержит concept_id, path относительно корня, heading, locator (путь с процентным кодированием плюс #Lstart-Lend), line_start, line_end, content_sha256 всего исходного файла, точный snippet (не более 512 символов из диапазона источника, по возможности расположенный около первого совпавшего термина тела), score и matched_terms. locator обозначает диапазон и не обещает поддержки якорей строк каждым средством отображения Markdown. JSON всегда содержит массивы, в том числе при отсутствии результатов. Текстовый вывод CLI показывает путь, строки и фрагмент; JSON — машинный контракт.

snapshot_revision — SHA-256 в нижнем регистре от канонического JSON отсортированных записей захваченных файлов {path,size,sha256} с указанным порядком ключей структуры. Это отпечаток снимка чтения, а не ревизия хранилища, доказательство или токен аутентификации. Результаты получаются из захваченных байтов без повторного чтения живого источника. После любого изменения повторите поиск или сравните контрольную сумму файла перед использованием locator: тот же номер строки в изменённом файле не служит доказательством. CLI и MCP используют одинаковый отпечаток снимка для одинаковых байтов независимо от абсолютного расположения корня.

Постоянного индекса и курсора нет. total считает все совпавшие разделы; truncated обозначает пропущенные результаты. Увеличьте limit до 100 или уточните термины. Если и это не позволяет перечислить все результаты, сообщите об ограничении. Каждый вызов заново строит индекс в памяти. Ограничения: 10 000 файлов видимой ревизии, 64 MiB суммарных захваченных байтов, 16 MiB на файл, 100 000 разделов, 1 000 000 индексированных токенов, глубина 64, путь 4096 байт, ответ JSON 1 MiB. Превышение ограничения или отмена завершают операцию отказом без частичного успеха. Ошибки разбора блокируют поиск. Загрузка использует существующий FileSystemSource без следования по символическим ссылкам: ссылки внутри дерева исключаются, корень-ссылка и попытки выхода за корень отклоняются. Содержимое никогда не исполняется.

Схемы входа и выхода MCP в internal/mcpserver/contracts/search_sections.* задают контракт передачи данных. Существующие оболочки ошибок передают schema_validation для неверного входа, resource_limit для ограничений и установленные коды загрузки набора и отмены. Ошибки CLI дают ненулевой код завершения и не записывают данные набора.