Конвеєри¶
Чотири послідовності, які покривають майже всю роботу. Порядок у них не косметичний: кожен наступний крок дорожчий за попередній, тому дешеве йде першим, а око людини — останнім.
Кроки названо іменами операцій, а не іменами tool'ів: дістати їх можна з
командного рядка (nysh op cases.list) або переліком tool'ів, де таке ім'я є
(nysh_cases_list). Відповідь та сама — реєстр один. Схема аргументів будь-якої
з них: nysh op <ім'я> --describe.
🔴 Крок −1 в усіх чотирьох: подивись, що вже зроблено. cases.list,
pages.status. Переробка — найдорожча витрата в довгому дослідженні, і
вона ніколи не виглядає як помилка: робота ж іде.
1. Взяти матеріал у роботу¶
Питання: людина дала теку зі сканами або посилання на архів. Що з цим робити.
| # | крок | ✅ приймач |
|---|---|---|
| 1 | nysh_material_look <шлях> |
скільки кадрів, це одна справа чи багато |
| 2 | якщо кадрів немає — це не матеріал | не вигадуй; скажи людині, що саме побачив |
| 3 | case.register — шифра, назва, роки |
справа отримала ключ |
| 4 | nysh cases build |
справа з'явилась у cases.list |
Без шифри тека лишається купою файлів: у неї немає ні місця в реєстрі, ні
обліку прочитаного, ні можливості послатись на знахідку. Шифру приймають у тих
формах, якими її справді пишуть — ДАХмО 315-1-8433, ф.315 оп.1 спр.8433,
Ф. 211 Оп. 3 Д. 140.
⚠ Опис пишеться в саму теку. Тека переїжджає між дисками й потрапляє до
колег — опис їде з нею. Якщо тека лежить поза простором, ти отримаєш
попередження outside_workspace: справа буде невидима в переліках, доки людина
не візьме теку під облік.
⚠ Для деяких фондів опис входить у ключ справи (ANRM/211-3/140). Запит без
опису відмовить і назве варіанти — це не поламка, це різні книги під одним
номером.
2. Прочитати справу рукописним рушієм¶
Питання: є скани, потрібен машинний текст.
🔴 Читає команда, а не черга. read.start лише ставить завдання в чергу, а
черга є тільки в піднятому застосунку (nysh serve). Робочий шлях — і в цьому
немає нічого другосортного, так задумано:
nysh read <тека зі сканами>
| # | крок | ✅ приймач |
|---|---|---|
| 1 | nysh doctor --json |
рушії стоять, карту видно |
| 2 | nysh read <тека> --dry-run |
план: скільки кадрів, яке письмо, яка модель |
| 3 | nysh read <тека> |
прогін пішов |
| 4 | порахувати .txt на диску проти .jpg |
ось це і є приймач |
🔴 Приймач повноти — диск, а не код повернення. Є клас відмов, за якого сторінка вбиває процес: лог обривається без пояснення, перелік помилок порожній, прогін виглядає завершеним. Виміряний випадок: 14 сторінок із 18 при успішному коді повернення. Тому після прогону завжди звіряй кількість файлів.
⚠ Тека має бути пласкою. Тека з підтеками читається як порожня — «у теці немає сторінок jpg». Це коштувало прогонів, тому перевіряється до запуску, і повідомлення назве підтеки.
⚠ Читання — години. Не запускай його «щоб подивитись». Спершу --dry-run,
потім --limit 20 на розвідку, і аж тоді повний прогін.
🔋 Машина слабка? --shard, --gpu-lock, --no-gpu-sato, --seg-height —
важелі, якими прогін стискають під наявне залізо. Що з них безпечне, а що
коштує якістю прочитаного — htr-tuning.md.
3. Знайти прізвище в прочитаному¶
Питання: машинний текст є, треба знайти в ньому рід.
Це найтонший конвеєр, і саме тут агенти помиляються найчастіше
(antipatterns.md). Порядок економить не токени, а око людини: кроп дорогий,
тому він передостанній, а не перший.
| # | крок | чим | ✅ приймач |
|---|---|---|---|
| 1 | пошук | search.run |
знаменник у попередженні |
| 2 | контекст | уже в хіті (context, alt) |
вікно сусідів + читання другого голосу |
| 3 | відкинути явне | сам, без зображення | тільки за контекстом (нижче) |
| 4 | подивитись | page.view по line_index |
рядок із рамкою |
| 5 | 🛑 до людини | твій звіт | «кандидат», а не «знайдено» |
Крок 1 — знаменник обов'язковий¶
Порожній результат читається разом із попередженням. zero_with_denominator
означає справжній нуль («не знайшлось у N прогонах, M сторінок»);
no_denominator означає, що не шукало ніщо, і звітувати «немає» не можна.
⚠ Пошук уже сам зшиває прізвище, розірване переносом, і сам нормалізує
кирилицю з латинкою — не роби цього руками. Що він уміє, а чого в ньому
немає (склад двору, вік) — search-channels.md. У розібраних записах питання
звужується полями: role (батько, восприємник, померлий), rtype (тип акту) і
axis=place — пошук по поселенню замість прізвища.
Крок 2 — вікно приходить саме¶
search.run віддає кожен хіт разом із сусідніми рядками (context) і, як
справу читано двома рушіями, з читанням другого (alt). Окремо просити
page.text для цього більше не треба — він потрібен, коли хочеш усю
сторінку (заголовок формуляра, ліва колонка, сусідні акти).
Рядок сам по собі не розрізняє трьох родів зі спільним коренем у одній парафії. Доказ живе на двох рядках: прізвище перенеслося, ім'я стоїть вище, роль — нижче. А розбіжність голосів на самому прізвищі означає, що ознака в пікселях — тобто крок 4 обов'язковий.
⚠ Класифікація по вузькому вікні — не розбір, а фільтр. Виміряний випадок: по вікну ±2 рядки ознака бачилась на 15 сторінках, по повному тексту — на 41. Найдорожчими виявились сторінки, де ознака взагалі не була прочитана: вони мовчки поїхали в «чуже».
Крок 3 — відкидати можна тільки за контекстом¶
🔴 Відсів за коренем слова заборонений. Рушій калічить саме середину слова, тож шукане прізвище виходить із нього невпізнанним. Список «поганих коренів» відріже рівно те, по що його кликали.
Три підстави закрити кандидата без зображення — і більше жодної:
- ім'я після формули спорідненості («сина …», «дочки …»);
- топонім: поруч стоїть «повіту», «губернії», «уїзду»;
- токен порожній, самі цифри або 1–3 літери.
Усе інше ранжується, а не відкидається. Ознаки, що піднімають ранг: поруч ім'я з відомого складу роду, по батькові перед токеном, токен відкриває рядок із великої літери. Ознаки, що знижують: стоїть після прийменника з малої, у рядку канцелярський штамп.
Крок 4 — кроп лише тому, що схоже на прізвище¶
Дефолт page.view — рядок: сторінка коштує приблизно вчетверо дорожче.
Бери line_index з хіта, не line_no (перше — з нуля, друге — з одиниці).
🛑 Крок 5 — межа¶
Якщо на кропі прізвище, схоже на шукане, — ти не виносиш вердикт. Клади кандидата людині з зображенням і контекстом. Закривати можеш лише те, що взагалі не є прізвищем.
4. Записати результат¶
Питання: переглянув аркуші — що з цим робити, щоб робота не пропала.
| # | крок | ✅ приймач |
|---|---|---|
| 1 | pages.note на кожен переглянутий аркуш |
сторінка зникла з «ще не дивились» |
| 2 | records.add — розібрані записи |
хто/коли/батьки/восприємники окремими полями |
| 3 | nysh cases build (команда) |
реєстр знову свіжий |
| 4 | export.case — якщо просили таблицю |
кожен рядок несе скан |
🔴 Заносяться всі аркуші, а не тільки вдалі. Порожній, не той, хибне спрацювання пошуку — теж. Негативний результат коштує тих самих токенів, що й позитивний, а без запису наступна сесія передивиться той самий аркуш.
У коментарі пиши чому це не те («пошук подав як потрібне село — на скані інше»). У полі методу — чи ти дивився зображення, чи лише читав машинний текст.
⚠ status=full означає «виписані всі прізвища сторінки». Якщо виписав частину —
partial. Поставиш full без прізвищ — отримаєш попередження
full_without_surnames, і це не причіпка: від цього поля залежить, чи можна
довіряти нулю по всій справі.
⚠ Записи прози й переказу не заміняють структурованих полів. «Виписка без посилання на аркуш — це переказ», і в експорті вона нічого не варта.