Читати першоджерела, а не переказ про них
«Прочитати Прудона» і «прочитати статтю про Прудона» — це не одна задача з двома рівнями якості. Це дві різні задачі. Переказ уже несе чужий відбір: що важливо, що викинути, під яким кутом дивитись — і економить час рівно тим, що ухвалив рішення замість мене. Для довідки ок. Для власної позиції — ні: не можна не погодитись з аргументом, який до тебе не дійшов у своєму вигляді.
Різниця тут не в тексті, а в інструменті. Переказ споживають лінійно й забувають. Першоджерело треба перечитувати, розмічати й повертатись — інакше воно теж стає лінійним споживанням, просто довшим. Тобто рідер, який справді допомагає думати, — не «зручна читалка», а окремий клас інструмента: приватний, з нотатками на рівні секцій, зі станом, що переживає зміну пристрою, і з експортом того, що читач написав сам.
Нижче — п'ять шарів такого рідера. Кожен корисний окремо; будувати приблизно в цьому порядку. Розмежування, яке тримає всю конструкцію: асистент будує риштування, читач формує позицію. Асистент дзеркалить чужий текст, перекладає його, робить поля під нотатки — і ніколи не пише самі думки. Щойно з нього вилазить «а ось головна ідея цього розділу» — це вже переказ, і задача підмінена.
Шар 1 — дзеркалення джерел з copyright-дисципліною
Перше, що ламає наївну реалізацію, — не техніка, а право. Тут дві незалежні осі, які постійно злипаються в одну:
- Public domain (автор помер достатньо давно за строком юрисдикції) — дзеркалити безпечно, і байдуже, наскільки приватний рідер.
- Приватне, некомерційне, запаролене використання ще чинного під копірайтом тексту — розумний fair-use аргумент, але інша, ненульова ризик-категорія. Її треба назвати вголос людині, що будує рідер, і дати вирішити per text, а не тихо загорнути все під одне ковдрове припущення.
- Джерело, яке саме про себе пише «not copyrighted» / freely reproducible, — найбезпечніша категорія з трьох.
Технічно перед дзеркаленням варто мацнути саму сторінку: curl -sS -D - і подивитись, чи немає X-Frame-Options / CSP frame-ancestors, які ріжуть вбудовування, і чи це повний текст, а не тизер або paywall-заглушка. Неочевидний URL — спробувати передбачуваний slug-патерн сайту, потім його власний пошук. А якщо тексту там немає (він існує деінде, просто не на очікуваному сайті) — зупинитись і сказати це прямо. Підставити інший текст і назвати його тим самим — гірше за відсутність тексту.
Структуру сторінки закладаю одразу під двомовність: блок мовою оригіналу, порожня заглушка під переклад, перемикач між ними і один спільний маленький скрипт-тоглер на всі тексти рідера — не копіпаст на кожну сторінку.
Шар 2 — переклад як писання, а не копіювання
Робоча мова читача відрізняється від мови більшості джерел — треба перекладати, а не резюмувати. Стиснутий дайджест убиває весь сенс читання першоджерел: він знову ухвалює рішення замість читача. Допустимий він рівно тоді, коли людина явно сказала, що повний переклад конкретного тексту не вартий зусиль.
Правила, які роблять переклад придатним для звірки, а не просто читабельним:
- Перекладати абзац-в-абзац, 1:1 з оригіналом — та сама кількість абзаців, той самий порядок. Так переклад звіряється з оригіналом за номером абзаца, а розбиття на секції (шар 3) лишається синхронним між обома мовами.
- Термін із двома і більше усталеними перекладами: обрати один, тримати його константним на весь текст і сказати, який обрано і чому. Не давати йому дрейфувати посеред документа.
- Зберігати регістр і тон оригіналу: саркастичний памфлет лишається саркастичним, академічна лекція — академічною, полеміка — полемікою. Не сплющувати все до нейтральної прози.
І головне: це справжня писальна задача, а не механічний крок копіювання. Ресурс під неї закладати відповідно — сильніший, повільніший прохід моделі, не найдешевший, — надто для довгих чи аргументативно щільних текстів. Дешевий прохід віддає граматично правильний текст, з якого зникла половина авторської інтонації, — і читач формує позицію вже проти каліченого опонента.
Шар 3 — секції, нотатки й позиція читання
Текст ріже на секції клієнтський скрипт, а не ручне редагування HTML. Це принципово: розбиття живе в коді рідера, тому оригінал і переклад лишаються синхронними, і жоден переклад не чіпається заради поділу.
- Розмір секції узгоджувати з людиною до побудови, не дефолтити мовчки. Розумна стартова точка — кілька десятків абзаців на секцію, але це сильно залежить від щільності тексту; спитати.
- Не різати секцію посеред підрозділу — зсувати межу до найближчого заголовка, навіть якщо секція стане трохи довшою чи коротшою за ціль.
- Під кожною секцією — поле нотатки: що зачепило, що приймається, що відкидається, яке питання лишилось відкритим. Поле того ж типу текст отримує в самому кінці — під загальний вердикт.
Позицію читання (яку секцію читач востаннє відкривав) треба зберігати серверно — щоб продовжити з іншого пристрою. Показувати маленький банер «продовжити з секції N», ніколи не автоскролити без кліку.
Де це зберігати — визначальний вибір. Браузерний localStorage вмирає разом з очищенням кешу, не переживає зміну пристрою і не читається жодним іншим інструментом. Тому — маленька БД. У референсній реалізації це три таблиці Postgres, розділені за роллю: секційні нотатки, фінальні нотатки на текст і позиція читання. Розділення не косметичне — саме секційні нотатки потім стають сирим матеріалом для синтезу (шар 5), і їх треба діставати окремо від позиції та фінального вердикту.
| Рішення про сховище нотаток | Вибір |
|---|---|
| Нотатки мають пережити очищення кешу браузера | серверна БД, не localStorage |
| Читач ходить з телефону і з ноута | серверна БД + серверна позиція читання |
| Нотатки потім підуть у синтез окремо від позиції | окремі таблиці за роллю, не один blob |
| Прототип на один вечір, один пристрій, викидний | localStorage припустимий, але сказати про обмеження |
Шар 4 — візуальний шар як носій прогресу
Генеративний візуальний шар тут — не декор. Це носій прогресу, який заміняє звичайний прогрес-бар. Якщо в людини вже є ембіент-шар, що їй подобається деінде на власному сайті, — переюзати його; інакше взяти будь-який легкий генеративний візуал (частинки, градієнтне поле, шум) з reseed-подібним API.
Три правила перетворюють візуал з фону на індикатор:
- Кожен текст отримує детермінований seed, похідний від його slug/назви. Один і той самий текст завжди стартує з того самого поля — воно стає впізнаваним, як обкладинка.
- Якщо в списку читання є тематична структура (скажімо «заперечення» проти «захистів» проти «контраргументів») — мапнути її на акцентний колір чи параметр. Саме поле натякає, де в аргументі перебуває читач.
- На перетині межі секції — reseed: повна видима регенерація поля. Оце і є нагорода за прогрес замість смужки, що повзе.
У референсній реалізації reseed зроблено найдешевшим можливим способом: сторінка тримає data-seed атрибут (детермінований на текст), а при вході в секцію N викликається reseed((seed + idx)) уже наявного ембіент-модуля. Не форкати й не переписувати сторонню візуальну бібліотеку заради цього — конфігурувати її через ті публічні параметри/атрибути, які вона вже віддає. Форк заради прогрес-індикатора — це технічний борг, який переживе саму мотивацію читати.
Шар 5 — експорт нотаток як сирий матеріал для синтезу
Одна кнопка на індексній/оглядовій сторінці рідера (не на кожному тексті), яка збирає всі нотатки, що написав читач, — і фінальну нотатку на текст, і кожну секційну — у канонічному порядку читання і віддає markdown-файлом.
- Для кожного тексту, де є хоч одна непорожня нотатка: заголовок з назвою, лінк на повний текст, маркер «прочитано» (якщо є), далі по буллету на секційну нотатку з глибоким лінком на секцію (
#section-N), потім фінальний вердикт окремим абзацом. - Текст без жодної нотатки пропускається цілком — не набивати експорт порожніми заголовками.
- Експорт лишається вірним тому, що читач реально написав. Не редагувати, не «покращувати», не вставляти власних коментарів усередину. Це сирий матеріал для позиційного паперу / есе / рішення, яке людина будує далі, — і будь-яка домішка асистента отруює саме те, заради чого все будувалось.
Це замикає петлю. Рідер узяв чужі тексти, дав їх мовою читача, дав розмітити по секціях — і повернув читачеві його власні розрізнені реакції, зібрані докупи, готові стати цілісною позицією. Асистент жодного разу не сказав, що думати. Він лише зробив так, щоб думання не розсипалось.
Антипатерни
- Резюмувати замість перекладати. Найпоширеніша підміна: дайджест виглядає як послуга, а насправді вирішує за читача, що важливо. Першоджерело перетворюється на переказ, просто зроблений тобою.
- Ковдрове copyright-припущення. Дзеркалити все під одне «ну це ж приватно» замість рішення per text. Public domain і приватний fair-use — різні осі; змішування їх ховає реальний ризик.
- Ручне різання HTML на секції. Розводить оригінал і переклад — і далі будь-яка правда про секцію живе у двох місцях і розсинхронюється.
- Нотатки в localStorage. Гинуть при очищенні кешу, не переживають зміну пристрою, не читаються експортом. Приватні нотатки — це те, що взагалі не можна тихо втратити.
- Асистент пише думки. «Головна ідея розділу — …» у полі нотатки чи в експорті. Це кінець задачі: тепер читач формує позицію не проти джерела, а проти чужого переказу джерела.
- Візуал як декор. Гарне поле, що не реагує на прогрес, — просто фон. Носієм прогресу його робить детермінований seed на текст і reseed на межі секції, а не сам факт наявності анімації.
- Форк візуальної бібліотеки. Глибока модифікація стороннього рушія заради прогрес-індикатора — борг, що переживе мотивацію. Конфігурувати через публічні параметри або не чіпати.
- Тихо розширювати список читання. Джерела додала інша сесія чи людина — не вважати це помилкою і не видаляти мовчки; перевірити.
- Editorializing в експорті. Будь-який коментар асистента всередині зібраних нотаток знецінює їх як сире джерело для синтезу.
Таблиця рішень
| Ситуація | Дія |
|---|---|
| Джерело ще під копірайтом, рідер приватний і запаролений | назвати ненульовий ризик вголос, рішення per text |
| Джерела немає на очікуваному сайті | сказати прямо, не підставляти інший текст під тією ж назвою |
| Робоча мова читача ≠ мова джерел | повний переклад 1:1 по абзацах, не дайджест |
| Термін має кілька усталених перекладів | обрати один, тримати константним, зафіксувати вибір |
| Довгий чи аргументативно щільний текст | сильніший прохід моделі на переклад, не найдешевший |
| Треба розбити текст на секції | клієнтський скрипт, межі по заголовках, розмір узгодити наперед |
| Нотатки мають пережити зміну пристрою | серверна БД (окремі таблиці за роллю), не localStorage |
| Потрібен індикатор прогресу | детермінований seed на текст + reseed на межі секції |
| Читач хоче зібрати все написане | одна кнопка експорту на індексі, вірна тексту, без домішок |
| Access control мовчки зник з приватної локації | відновити за замовчуванням, потім питати |
Чекліст
- По кожному тексту прийнято окреме copyright-рішення (public domain / приватний fair-use / freely reproducible)
- Сторінку джерела перевірено на
X-Frame-Options/CSP і на повний текст (не тизер/paywall) - Переклад 1:1 по абзацах, порядок і кількість абзаців збігаються з оригіналом
- Спірні терміни зафіксовано з поясненням вибору, дрейфу немає
- Регістр і тон оригіналу збережені
- Секції ріже клієнтський скрипт, межі — по заголовках, розмір узгоджено з читачем
- Нотатки й позиція читання в серверній БД, не в localStorage
- Seed детермінований на текст, reseed спрацьовує на межі секції
- Кнопка експорту одна, на індексі, збирає всі непорожні нотатки в порядку читання
- Ніде — ні в нотатках, ні в експорті — асистент не написав самі думки за читача
Є стійка ілюзія, що прочитати книжку — це дійти до останньої сторінки. За цим критерієм переказ на чотири абзаци «прочитав» усі першоджерела за тебе, ще й швидше і без нудних місць.
Справжній критерій готовності інший, і він незручний: чи змінилась позиція від зіткнення з текстом у його власному вигляді, а не з чиїмось відбором з нього. Рідер на п'ять шарів існує рівно для того, щоб зробити цей незручний критерій дешевшим за зручний. Секційні нотатки — це слід того, що аргумент таки дійшов. Порожній експорт наприкінці означає рівно одне: сторінки гортались, а думати ще не почали.