Журнал сессии A
Входящие (запросы другой сессии)
2026-10-04, от B — пожелания к FFI для холста Qt (A6, CONTRACTS.md раздел A → B): а) буфер
meridian_doc_render_page— RGBA8888 premultiplied, sRGB,strideв байтах, строки сверху вниз (=QImage::Format_RGBA8888_Premultipliedбез копирования); б)meridian_doc_page_size(doc, page, *w_emu, *h_emu) -> i32— размер страницы до рендера (буфер под масштаб и DPI); в)meridian_last_error() -> *const c_char(thread-local) — текст ошибки для интерфейса; г) одинMeridianDocможно рендерить из рабочего потока (не GUI), без глобальных блокировок; страницы — последовательно; д)meridian_abi_version()оставить — оболочка проверяет её при сборке. Пока A6 не готов, оболочка работает с заглушкой ровно этого контракта (shell/), замена — без правок QML. — принято в A6 (контракт FFI v0.2 вCONTRACTS.mdпри выполнении A6).2026-10-04, от B — зависимости и
THIRD_PARTY.md(сделано в B1): крейты попадают вTHIRD_PARTY.md,NOTICEиsbom.cdx.jsonавтоматически изCargo.lock. После добавления зависимости:python3 scripts/third_party.pyи коммит трёх сгенерированных файлов (протокол §2 разрешает это обеим сессиям);just ciперед слиянием. Копии и порты чужого кода (IronCalc, фрагменты typst, hypher) — строкой во «Входящие» B: путь копии, SPDX, текст NOTICE — внесу вthird_party.toml. В корневойCargo.tomlдобавленtools/*—tools/corpus-toolможно класть по брифу. — принято: зависимости A1 перегенерированыscripts/third_party.py, копия IronCalc — запросом во «Входящие» B.2026-10-04, от B (B2) —
docs/04-file-formats.md§2.16 «Шифрование»: нормативное описание версии 1 теперь вspec/formats/mop-encryption.md(реализацияmeridian-crypto, векторы проверены независимой реализацией на Python). Отличия от черновика §2.16 — таблица в §8 спецификации (ключи через HKDF, MAC заголовка с SHA-256 всегоpackage.bin, STREAM: префикс 7 байт ‖ u32(i) ‖ флаг последнего, AAD сfile_id, атрибутstream="stream-v1"вместоaad, код восстановления). Прошу заменить пример и алгоритм в §2.16 ссылкой на спецификацию (или привести к ней); API для кодека —CONTRACTS.md, раздел «B → A: шифрование пакетов MOP».2026-10-04, от B (B4) — A6 принят, спасибо: оболочка рисует настоящим ядром, заглушка выключена. Пожелание к следующей версии FFI (не срочно, к фазе 1): оглавление документа для панели «Навигация → Заголовки» — например
meridian_doc_outline_count(doc)иmeridian_doc_outline_item(doc, i, *level, *page, buf, cap, *written)(текст UTF-8, уровень 1–9 изoutlineLvl/стилей заголовков, страница с нуля). Пока вкладка перечисляет страницы. — сделано (FFI v0.3): ровно эти сигнатуры,meridian.hиCONTRACTS.mdобновлены.2026-10-04, от B — своя оболочка без Qt (решение владельца № 39): интерфейс теперь
ui/meridian-ui+ui/meridian-writeна Rust; ядро вызывается через тот же C ABImeridian-ffiv0.2 (из Rust, крейт подключён как rlib) — контракт не меняется,cxx-qtне нужен. Два пожелания: (1) новый документ сейчас Letter 612×792 pt — для русской локали (и ГОСТ) ожидаем A4 595×842 по умолчанию, хорошо бы параметр/локаль вmeridian_doc_new; (2) в Rust-частиmeridian-ffiнет константыMERIDIAN_EMU_PER_POINT(есть только вmeridian.h) — можно добавитьpub const, тогда оболочка не держит копию. — сделано (FFI v0.3):meridian_doc_new_locale(locale, out)(meridian_doc_newне менял — ABI совместим) иpub const MERIDIAN_EMU_PER_POINT: i64 = 12_700вmeridian_ffi.2026-10-04, от C («Анализ приложения и план работ», окно
ui/meridian-sheetsнаmeridian_book_*): (1) ошибка: послеsave_xlsx→openформула «=221» показывалась как «=@(221)»; (2)cell_formatотдавал то «General», то «»; (3) пожелания v0.5 по убыванию — стили ячеек (шрифт, заливка, выравнивание, границы) с xlsx, вставка/удаление строк и столбцов со сдвигом ссылок, копирование формулы со сдвигом, ширины столбцов и высоты строк, объединения, поиск по листу. — (1) сделано: формулы xlsx безcmоборачиваются в неявное пересечение, только если могут вернуть массив (meridian_calc::ast::may_return_array, как Excel решает, где показывать@); сверка с Excel не изменилась (99,94 %); (2) сделано (v0.4.1): у «Общего»cell_formatвсегда «»; (3) принято в план, по порядку, без ломающих изменений ABI.
Предложения в библию
- 2026-10-04 (A1) — перенесено B в библию §11 (B2) —
библия §11, строка «Meridian Kernel / формулы»: уточнить «форк IronCalc
сделан (
meridian-calc,meridian-calc-xlsx); formualizer — только образец алгоритмов, не зависимость; порядок доработок: граф зависимостей → инкрементальный пересчёт с порогом полного прохода → кэш агрегатов диапазонов и индекс точного поиска → многопоточность по слоям (ADR-A1,docs/research/spikes/A-calc.md)». - 2026-10-04 (A1) — ответ B: раздел о крейтах ядра в
docs/03-architecture.mdправит A сам (карта владения дополнена: документ общий, разделы о ядре — A) —docs/03-architecture.md§3, строкаmeridian-calc: ключевые типы теперьModel,UserModel,Function,CalcResult(из IronCalc), а неExpr/CellRef/Value/CellProvider; добавить крейтmeridian-calc-xlsx(xlsx-ввод/вывод модели формул до появления полногоcodec-ooxml). Владелец документа в карте не указан — прошу B перенести или подтвердить, что правлю сам. - 2026-10-04 (A1) — перенесено B в план фазы 1
(
docs/08-roadmap.md, B2) — план фазы 1: русская локаль и язык функций дляmeridian-calc(в IronCalc только en/de/es/fr/it), AGGREGATE и GETPIVOTDATA (последние P0 каталога). - 2026-10-04 (A8) — перенесено B в библию §11.1 (с поправкой
на решение № 40) — шейпинг
(
docs/research/spikes/A-shaping.md, ADR-A8): «Текст документов шейпит только harfrust закреплённой версии, одинаково на Windows, macOS и Linux; системные шейперы (CoreText, DirectWrite, Pango) в раскладку документа не допускаются — на OpenType-шрифтах они дают те же глифы и положения, но в 4–7 раз медленнее и зависят от версии ОС; шрифты AAT harfrust обрабатывает сам». Разделы о ядре вdocs/03-architecture.md(§3, таблица ОС) A уже поправил:rustybuzz→harfrust. - 2026-10-04 (A8) — перенесено B в библию §11.1 (с поправкой
на решение № 40) — PDF
(
docs/research/spikes/A-pdf.md): «Растеризатор чужих PDF — hayro (чистый Rust, зеркалоmeridian-oss/hayro); расшифровку защищённых PDF делает ядро; pdfium — только запасной путь за флагом сборки после замера на корпусе» (pdfium не измерен: нет зеркал, запрос во «Входящих» B-log). - 2026-10-04 (A8) — перенесено B в библию §11.1 (с поправкой
на решение № 40) — кисти Paint
(
docs/research/spikes/A-mypaint.md): «Кисти — порт libmypaint (ISC) на Rust вmeridian-rasterс побитной сверкой с C в тестах; C-код libmypaint в продукт не входит; растр кистей детерминирован между ОС: без FMA, безrand()libc, математика —libm» (оценка порта ≈ 1 чел.-мес.; при переносе — запрос B на запись вthird_party.toml).
План работ
Порядок — бриф A-kernel.md (A1→A9). Колонка «GX10» — что
отдаём локальным моделям сервера GX10 (решение владельца 2026-10-04:
экономить подписку на рутинной генерации). Помощник —
scripts/gx10_llm.py (Ollama на GX10 через Tailscale; роли:
code — qwen3-coder:30b, text —
qwen3.6:35b-a3b, ru — T-pro-it-2.1, vision —
qwen3-vl:30b); картинки — ComfyUI на GX10 (:8188).
| № | Задача | Статус | GX10: что отдаём моделям |
|---|---|---|---|
| A1 | Форк IronCalc → meridian-calc, спайк против
formualizer, покрытие каталога |
готово 2026-10-04 | черновики юнит-тестов функций, где меньше 5 случаев
(code); ожидания сверяем с эталонными книгами Excel, не с
моделью |
| A2 | Корпус ≥ 1 000 файлов, corpus-tool stats |
готово 2026-10-04 | черновики разборщиков списков источников и описания категорий файлов
(code, text) |
| A3 | meridian-layout: шейпинг, Кнут–Пласс, переносы |
готово 2026-10-04 | тестовые абзацы ru/en/ar/he/hi и словари исключений переносов
(ru, text); черновики бенчмарков
(code) |
| A4 | codec-ooxml: docx минимум |
готово 2026-10-04 | генератор синтетических docx для тестов и затравки фаззинга
(code) |
| A5 | meridian-render: PNG и PDF/A |
готово 2026-10-04 (конвейер и замер; цель SSIM — к M0.4) | словесный разбор расхождений «эталон / наш рендер» для отчёта
(vision); картинки для inline-изображений синтетических
docx (ComfyUI) |
| A6 | Контракт FFI + пример на C | готово 2026-10-04 | черновик примера на C и обвязки теста (code) |
| A7 | Стенд meridian-lab.24oros.ru |
готово 2026-10-04 | черновик вёрстки отчёта, иллюстрации (code,
ComfyUI) |
| A8 | Спайки pdfium/hayro, harfrust/системный шейпинг, libmypaint | готово 2026-10-04 (pdfium — после зеркал) | черновики обвязок замеров (code) |
| A9 | meridian-spell: ru_RU (SFX), en_US |
готово 2026-10-04 (движок; полные словари — после зеркал) | наборы слов с опечатками и ожидаемыми подсказками (ru,
text) |
Правила разгрузки на GX10:
- Ответ модели — только черновик: сессия читает его целиком и правит;
код проходит fmt, clippy и тесты; ожидаемые значения тестов берутся из
эталонов (Excel, Word, спецификации), а не из ответа модели. Пробный
запрос показал, почему: сгенерированный тест для
excel_col_to_indexожидалNoneдляAAZ. - Код и документы проекта отправлять можно (сервер наш); секреты, ключи и токены — никогда.
- Сначала
gx10_llm.py ps: берём уже загруженные модели; большие (gpt-oss:120b, 65 ГБ) — только при свободной памяти, чтобы не выдавить vLLM роя VibeBot. На GX10 ничего не строим и не скачиваем (диск занят на 96 %). - Сгенерированное и принятое в репозиторий отмечаем в сообщении коммита строкой «черновик: GX10 <модель>».
- Опыт A2 (2026-10-04): черновик
script.rsот qwen3-coder:30b пришёл за 107 с, но 3 из 9 тестов противоречили его же порогу, ничьи были недетерминированы, в «латиницу» попадали×/÷— модуль переписан, выгода мала; запрос таблицы пространств имёнns.rsзавис больше 10 минут (длинный ответ) и прерван — таблица написана вручную. Вывод: отдавать GX10 объёмные, но проверяемые машинно вещи (списки, данные, шаблоны тестов с эталонами из файлов), а не небольшие модули с тонкой логикой; ставить ограничение длины ответа (num_predict) и таймаут 5 минут.
Записи
- 2026-10-04 — журнал создан координатором; сессия ещё не запускалась.
- 2026-10-04 — A1 готово. Форк IronCalc 0.8.3
(
9b1ae3f) →kernel/crates/meridian-calc(база) иkernel/crates/meridian-calc-xlsx(xlsx), NOTICE и заголовки «Основано на IronCalc» в 557 файлах; тесты IronCalc зелёные (2 683 + 229 + 23 сценария на эталонных книгах + doc-тесты); старый мини-парсер заменён, его случаи —tests/legacy_mini.rs; исправлено=10^400→#NUM!(было#DIV/0!). Покрытие каталога: P0 315/317, P1 139/156, P2 4/16, алиасы 38/38. Спайк против formualizer —docs/research/spikes/A-calc.md(ADR-A1: основа — IronCalc, свой граф и инкрементальный пересчёт, кэш диапазонов и индекс поиска по образцу formualizer). Стенд замеров —kernel/spikes/calc-bench(вне workspace, formualizer из зеркала). Помощник разгрузки на GX10 —scripts/gx10_llm.py, план работ с колонкой GX10 — выше. Лицензии: 87 внешних крейтов — все классы 0–1. Дальше: A2 (корпус). Блокеров нет. - 2026-10-04 — A2 готово.
tools/corpus-tool(Rust):plan(квоты по форматам, детерминированный выбор по FNV-хэшу, закреплённые коммиты источников),fetch(GitHub raw параллельно; GovDocs1 — целые архивы ≤ 128 МБ или отдельные файлы по HTTP Range со своим разбором центрального каталога ZIP/ZIP64; SHA-256, дубликаты),scan(формат по содержимому: OOXML по[Content_Types].xml, ODF поmimetype, doc/xls/ppt/msg по потокам CFB, RTF, PDF; приложение и версия, язык, письменность, страницы),stats(частоты элементов OOXML с разрешением пространств имён, ключиw:compatSetting),audit. Корпус: 1 075 файлов (294 МБ, вне git), 20 дубликатов отброшено; docx 367, xlsx 159, doc 158, pptx 102, pdf 60, rtf 60, xls 58, odt/odp/ods 66, повреждённые и зашифрованные тестовые файлы POI/Tika — отдельно (21 «zip-broken» — настоящие fuzz-кейсы, Python их тоже не открывает). Источники: GovDocs1 433 (общественное достояние), POI 380, Tika 167, pdf.js 50, ODF Toolkit 43 (Apache-2.0). В git —tests/corpus/manifest.tsv,stats/ooxml-elements.tsv,stats/ooxml-summary.md,stats/audit.md. Сеть: S3 digitalcorpora с Mac почти не отдаёт данные (из РФ режется), через sagr — нормально; GovDocs1 докачан на sagr (/opt/projects/meridian-lab/corpus-staging, скрипт stdlib Python) и забран rsync. Заодно:docs/04-file-formats.md§2.16 приведён кspec/formats/mop-encryption.md(запрос B), строкаmeridian-calcвdocs/03-architecture.md§3 обновлена. - 2026-10-04 — A3 готово.
kernel/crates/meridian-hyph— форк hypher 0.1.8 (MIT), 46 языков без hu (MPL/GPL/LGPL) и sk (GPL), автоматы побайтно совпадают с исходником, лицензии шаблонов — в NOTICE.kernel/crates/meridian-layout: шрифты (read-fonts 0.43 — та же версия, что у harfrust; целые метрики head/hhea/OS/2, высота строки по winAscent+winDescent, как у Word; подстановка Arial→Liberation Sans, Calibri→Carlito и т. п.), шейпинг harfrust → EMU по глифу, UAX #14 (icu_segmenter), bidi (unicode-bidi), подбор шрифта для отсутствующих символов, переносы, жадный режим «как Word» и Кнут–Пласс (алгоритм из typst, Apache-2.0, на целых числах), выравнивание (влево/центр/вправо/по ширине с целочисленным распределением), отступы, интервалы «множитель/точно/минимум»;#![deny(clippy::float_arithmetic)]. Шрифты комплекта для тестов —kernel/fonts/(Liberation 2.1.5, Carlito, OFL-1.1). Тесты: 10 юнит + 11 интеграционных; бенчмаркcargo bench -p meridian-layout --bench paragraph(абзац ≈ 2 400 символов, M5 Max): жадный 0,21 мс, Кнут–Пласс 0,27 мс, с переносами 0,29 / 0,44 мс. Дальше: A4 (кодек docx). Блокеров нет. - 2026-10-04 — A4 готово.
kernel/crates/meridian-text-model— подмножество модели Write фазы 0 (документ → разделы → абзацы/таблицы → инлайны;CharProps/ParaPropsсOption,StyleSheetс разрешением по OOXML §17.7.2: docDefaults → цепочкаbasedOn→ стиль символов, toggle-свойства XOR между стилем абзаца и символов, прямое — абсолютно; шрифты темы).kernel/crates/codec-ooxml— чтение docx: OPC (части без учёта регистра,.rels, относительные цели, предел части 256 МБ), DOM-дерево XML на quick-xml с принятыми префиксами (глубина ≤ 256, ≤ 4 млн элементов, итеративно), стили, тема, настройки (необязательны — их порча не мешает открыть текст), разделы (w:sectPr), абзацы, прогоны, гиперссылки/поля/элементы управления/вставки (удаления скрыты — «итоговый вид»), табуляция, разрывы, символы, таблицы (gridSpan,vMerge, высота строк, вложенные), картинкиwp:inlineс медиа. Корпус: 367 из 390 docx (94,1 %) открыто, паник 0 (corpus-tool open,tests/corpus/stats/docx-open.md); остальное — честные отказы: 15 не-ZIP (fuzz-кейсы и обрезанные), 6 зашифрованных, стресс-тест вложенности POI, пакет темы вместо документа. Фаззинг:kernel/fuzz(cargo-fuzz, отдельное пространство), цельdocx, семена CC0 —tests/corpus/fuzz-seeds/docx/; в тестах кодека — 400 детерминированных мутаций без паник. Прогон фаззера 5 минут × 8 потоков (семена — свои и 60 docx POI): ≈ 1 млн входов, покрытие 3 334 ребра, падений 0. Дальше: A5 (рендер PNG и PDF/A). - 2026-10-04 — A5 готово (конвейер и замер; цель «≥ 60 %
страниц SSIM ≥ 0,95» — к вехе M0.4, сейчас 20,3 %).
kernel/crates/meridian-render: список отображения страницы → растр tiny-skia 0.12 (контуры глифов skrifa 0.46, кэш путей, картинки PNG (tiny-skia) и JPEG (zune-jpeg) с пределом 64 Мпикс, линии тоньше пикселя — ровно 1 пиксель по сетке, как у Word/LibreOffice) → PNG; экспорт PDF/A-2b через krilla 0.8 (подмножества шрифтов, слой текста по кластерам — поиск и копирование работают, лигатура несёт все свои буквы; проверка валидатором krilla; дата создания — параметр, ядро не читает часы); SSIM (окна 8×8, шаг 4, размытие 1 px) и строгий SSIM «по чернилам». Найдена и исправлена ошибка экспорта: krilla ждёт продвижение глифа в долях кегля, а не в пунктах (глифы разлетались в 12 раз) — есть тест.meridian-layout::layout_document— вёрстка документа по страницам: висячие строки, разделы (со следующей страницы / на текущей / с колонки / с чётной и нечётной), колонки равной ширины с разделителем и разрывами колонки, колонтитулы (первая/чётная/по умолчанию, наследование между разделами, поля PAGE/NUMPAGES), списки изnumbering.xml(десятичные, буквы, римские, русские буквы без ё/й/ъ/ы/ь, маркеры Symbol/Wingdings, шаблоны%N,isLgl, переопределения старта), табуляции (влево/центр/вправо/по разделителю, заполнители, своя позиция за правым отступом — какTabOverMargin),contextualSpacing, рамки и заливка абзацев (рамка занимаетspace + width), таблицы (сетка, объединения, рамки из цепочки стилей и ячеек, заливка, поля ячеекtblCellMar/tcMar, отступtblIndс учётом режима совместимости Word, выравнивание, перенос строк таблицы между страницами, в том числе вложенных), плавающие картинкиwp:anchorи VMLv:imagedata. Метрики как у Word: внешний интерлиньяж по формуле vcl (Times New Roman 12 pt = 13,8 pt), разрыв строки только после пробела/дефиса (UAX #14 — для CJK/тайского), кернинг и стандартные лигатуры выключены, как в Word безw:kern/w14:ligatures. Инструменты:tools/meridian-convert(docx → PNG постранично и PDF/A),corpus-tool refs(эталоны LibreOffice 26.8 без интерфейса: PDF → pdftoppm 72 dpi; путь через Word готов, но требует разового разрешения владельца на управление Word из песочницы) иcorpus-tool compare. Замер на 100 docx корпуса (у 98 есть эталон, 295 страниц): страниц с SSIM ≥ 0,95 — 60 (20,3 %), средний SSIM 0,696, число страниц совпало у 86 из 98 документов; в начале A5 было 16,8 % и 0,640 —tests/corpus/stats/render-compare.mdи.json. Главные причины расхождений (по сдвигу полос строк и картинкам «эталон | наш»): накопленный сдвиг пагинации после первого расхождения; нет надписей и фигур (wps:txbx, VML-фигуры), обтекания плавающих объектов, сносок, диаграмм, балансировки колонок перед разделом «на текущей странице»,keepNext/keepLines, неравных колонок; LibreOffice кладёт добавку интервала «множитель» под строку, Word — над строкой (мы следуем Word, поэтому к эталону LibreOffice остаётся сдвиг 1–3 px). Для честной цели M0.4 нужны эталоны из Word. GX10 для A5 не понадобился: разбор расхождений быстрее сделали скрипты (сдвиг полос строк, координаты слов из PDF через pdftotext). Новые крейты (krilla, tiny-skia, skrifa 0.46, zune-jpeg и зависимости) — классы 0–1,THIRD_PARTY.mdперегенерирован. Дальше: A6 (FFI рендера для оболочки — B4 ждёт). - 2026-10-04 — A6 готово.
meridian-ffi— рендер документов для оболочки по контракту B (CONTRACTS.md«A → B: C ABI» v0.2, имена — ровно как вshell/src/kernel/meridian_render.h):meridian_doc_open/new/free/page_count/ page_size/render_page/export_pdf,meridian_last_error(своя строка у каждого потока), кодыMERIDIAN_E_*(−1…−5, паника перехватывается), страницы с нуля, размеры в EMU, буфер RGBA8888 premultiplied соstrideв байтах — при плотных строках tiny-skia рисует прямо в буфер оболочки, иначе через холст и копию строк; рендер из рабочего потока (кэш глифов под мьютексом). Шрифты комплекта вшиты в библиотеку (FontStore::embedded, те жеFontId, что у каталога).meridian_render::draw_pageрисует в чужой буфер любого размера. Пример на Cexamples/c/render_page.cсобирается системнымccпротивlibmeridian_ffi.aи проверяется тестомc_example; заголовок оболочки без заглушки компилируется сmeridian.h. Запись о готовности — во «Входящих» B-log. Дальше: A7 (стенд meridian-lab). - 2026-10-04 — A7 готово. Стенд https://meridian-lab.24oros.ru
— генератор
tools/lab-site(Rust; статический сайт изrender-compare.jsonи картинокtests/corpus/private/lab/…): сводка SSIM и гистограмма, таблица 98 документов с фильтрами и поиском, страница каждого документа «эталон | наш рендер | разница» по страницам, покрытие функций docx, замеры конвейера (release, Mac M5 Max, один поток: 98 документов, 782 страницы за 3,5 с; медиана на страницу — чтение 0,32 мс, вёрстка 0,14 мс, растр 96 dpi 1,6 мс, PDF/A 0,47 мс). Выкладка —tools/lab-site/deploy/deploy.sh: sagr/opt/projects/meridian-lab, контейнерmeridian-labна 192.168.1.90:18301, маршрут Traefiksagr-meridian-lab-direct.yaml, строка домена в HAProxy на VPS (с резервной копией иhaproxy -c). Проверено снаружи: страницы, стили, сценарий и картинки — 200; браузер 1440 и 375 px — без прокрутки вбок, картинки грузятся; запись в/opt/CHANGELOG.md. Стенд сразу нашёл ошибку: у 18 документов с картинками PDF/A отклонялся валидатором (/Interpolate true) — исправлено, есть тест. Дальше: A8 (спайки). - 2026-10-04 — A9 готово (движок, фаза A).
kernel/crates/meridian-spell— свой движок формата Hunspell (код с нуля: движки Hunspell — MPL/LGPL): кодировкиSET(UTF-8, KOI8-R, CP1251, ISO 8859-1/5/15), флаги всех видов (FLAGchar/long/num/UTF-8), суффиксы и приставки с условиями, перекрёстное произведение, двухуровневые суффиксы,FORBIDDENWORD,NEEDAFFIX,KEEPCASE,NOSUGGEST,IGNORE,WORDCHARS; регистр как в Hunspell; для русского «ё» = «е»; слова через дефис — целиком, затем по частям; разбор текста на слова (misspelled), слова пользователя. Подсказки: регистр,REP(с^/$), соседние клавишиKEY, одна правка с ранжированием по биграммам, два слова, вторая правка. Тесты — на своих словарях CC0tests/data/{ru,en}_miniс настоящими правилами (склонение -а и мужского рода, беглая «о», прилагательные -ый, глаголы -ать/-аться; en: un-/re-, -s/-ed/-ing): 14 опечаток ru и 11 en — первая подсказка верна, 3 неоднозначных — в первой пятёрке (частот слов в фазе A нет). Замер (--example bench, синтетический словарь 94 тыс. корней на правилах ru_mini, M5 Max, release): загрузка 48 мс, проверка ≈ 800 тыс. слов/с, подсказка 1,9 мс на слово, нужная форма — в 197 из 200 перестановок. Полных словарей ru_RU (Лебедев, BSD) и en_US (SCOWL) в зеркалах нет — запрос во «Входящих» B-log; сложные слова, морфология, n-граммы и частоты — фаза B (E1.7). GX10 для A9 не понадобился: тестовые наборы малы и должны совпадать со словарём, их быстрее и надёжнее написать вручную. - 2026-10-04 — A8 готово (pdfium — после зеркал). Три
отчёта со стендами вне workspace: PDF
(
A-pdf.md,kernel/spikes/pdf-bench): hayro на 60 PDF корпуса и 98 PDF LibreOffice — 156 из 158 открыто (2 отказа — зашифрованные), 0 паник, SSIM ≥ 0,95 к poppler — 72 % страниц корпуса и 90 % офисных, медиана 0,3–1,2 мс на страницу; pdfium не измерен — нет зеркал. Шейпинг (A-shaping.md,kernel/spikes/shaping-bench, черновая работа — фоновым агентом): harfrust = HarfBuzz 14.3.1 на 100 % глифов; с CoreText на OpenType-шрифтах в режиме ядра — 225 из 225 абзацев одинаково, CoreText в 4–7 раз медленнее. Найдено и сразу исправлено в ядре: у шрифтов AAT (morxбезGSUB) выключенныйcligломал обязательные конъюнкты деванагари — теперь для них выключаются толькоkern/liga; планы шейпинга кэшируются вFontFace(по спайку — в 1,2–3 раза быстрее). Кисти (A-mypaint.md,kernel/spikes/mypaint-port, фоновым агентом): портrender_dab_maskи режима Normal совпадает с C побитно на 350 000 дабах (C без FMA), по скорости равен C; сам C даёт три разных результата на разных компиляторах (FMA) — решающий довод за порт. Предложения — в разделе «Предложения в библию». - 2026-10-04 — A5, продолжение: надписи и фигуры.
Inline::Shapeв модели (прямоугольник, скруглённый, эллипс; заливка, контур, поля, текст надписи); чтение VML (v:rect/v:roundrect/v:oval/v:shape+v:textbox,fillcolor/strokecolor/strokeweight,mso-position-*,z-index) и DrawingML (wps:wsp:a:prstGeom,a:solidFill/a:ln, ссылки стиляwps:style, цвета темыa:schemeClr,wps:bodyPr); вёрстка плавающих и встроенных фигур, эллипс в растре и PDF. Замер: средний SSIM 0,696 → 0,702, совпало число страниц 86 → 88 из 98; доля страниц ≥ 0,95 — прежние 20,3 %. - 2026-10-04 — FFI v0.3 и вёрстка. По пожеланиям B:
оглавление (
meridian_doc_outline_count/_item, заголовки поw:outlineLvlс номерами страниц),meridian_doc_new_locale(A4 и поля Word для ru, Letter для США и соседей),pub const MERIDIAN_EMU_PER_POINT. Вёрстка: «не отрывать от следующего» (keepNext, цепочки до 16 абзацев плюс первые строки следующего; счётчики списков при заглядывании вперёд восстанавливаются), «не разрывать абзац» (keepLines), отключаемый запрет висячих строк (widowControl), надстрочные и подстрочные знаки (w:vertAlign: 58 % кегля, ±33 %/8 %) и подъёмw:position. Замер: 20,3 % страниц ≥ 0,95, средний SSIM 0,701 (без изменений: поправки правильности, а не массовые). Эталоны Word: песочница этой сессии не может писать в контейнер Word и вызывать его без разрешения системы — оставлено владельцу. - 2026-10-04 — Решение владельца: «весь код свой».
Продукт коммерческий — чужие решения не подключаем, а пишем заново своим
кодом (чужой проект — только образец алгоритма). План по ядру —
docs/research/own-code-plan.md(10 шагов, ≈ 6–8 чел.-мес.; данные — шрифты, словари, шаблоны, UCD — вынесены на решение владельца с рекомендациями). Сделано сразу: (1) оптимальный разрыв строк переписан по статье Кнута–Пласса (1981), фрагмент typst удалён; (2)meridian-hyph— свой движок Лианга вместо форка hypher: шаблоны.tex— данные, разбираются при первом обращении; сверка с прежним на 654 тыс. слов словарей ru/en/pl/nl/tr — 0 расхождений; исключения\hyphenationтеперь учитываются. Попросил B убрать записи typst/hypher изthird_party.toml.meridian-spellна настоящем ru_RU (зеркалоmeridian-oss/dictionaries, BSD): загрузка 47 мс, 139 тыс. корней, ≈ 230 тыс. слов/с; добавлены свои фонетические замены для русского и проверка кандидатов с заглавной — 13 из 13 проверочных опечаток дают верную первую подсказку («сабака» → «собака», «Масква» → «Москва», «щастье» → «счастье»). - 2026-10-04 — «Весь код свой», шаг 3: свои ZIP и
XML.
meridian-archive(CRC-32, INFLATE и DEFLATE по RFC 1951, чтение ZIP/ZIP64 с проверкой CRC, сдвигом для данных перед архивом и пределами против ZIP-бомб, запись ZIP детерминированно) иmeridian-xml(XML 1.0 + пространства имён в дерево, нормализация переводов строк и значений атрибутов, DOCTYPE без раскрытия сущностей, пределы глубины и размера).codec-ooxmlбольше не зависит отzipиquick-xml. Сверка на корпусе (corpus-tool zipcheck/xmlcheck, прежние крейты остались только в инструменте как эталон): ZIP — 23 110 записей из 720 архивов совпали побайтно; XML — 16 739 из 16 742 частей (2 VML с оборванным CDATA мы разбираем, прежний отказывал); открытие docx — прежние 367 из 390, 0 паник; рендер 100 docx побайтно тот же. По замечаниям B: пункты оглавления длиннее 120 символов обрезаются по слову; неизвестные шрифты подбираются по классу (рубленый/моноширинный/с засечками — «Arial Narrow» больше не уходит в шрифт с засечками). Фаззинг docx с новыми ZIP/XML: 3 мин × 8 потоков, ≈ 321 тыс. входов, покрытие 3 943 ребра, падений 0. - 2026-10-04 — «Весь код свой», шаг 4: свои UAX #14 и UAX
#9 (
meridian-unicode). Таблицы — своим генератором из UCD 17.0.0 (загружено через sagr: unicode.org из РФ недоступен; SHA-256 файлов в журнале генерации), правила LB1–LB31 и полный алгоритм UAX #9 (P2–P3, X1–X10, W1–W7, N0–N2, I1–I2, L1, L2) — по текстам стандартов. Официальные тесты (хранятся сжатыми нашим DEFLATE): LineBreakTest — 19 338 из 19 338, BidiCharacterTest — 91 707 из 91 707.meridian-layoutбольше не зависит отicu_segmenterиunicode-bidi; рендер корпуса побайтно тот же. Ограничение: тайский, лаосский, кхмерский и бирманский переносятся только по пробелам (у ICU были словари) — отдельный пункт 4а плана. По договорённости с B: свой растеризатор (шаг 6) делает B (meridian-raster), шрифты и шейпинг (шаги 7–8) — A. - 2026-10-04 — «Весь код свой», шаг 5 и переход на растр
B.
meridian-image— свои декодеры PNG (все типы цвета и глубины,tRNS, Adam7, фильтры; сжатие — наш INFLATE) и JPEG (базовый, расширенный, прогрессивный с уточнением, перезапуски, любое прореживание с билинейным растяжением цветности, серое/YCbCr/CMYK/YCCK, целочисленное обратное DCT). Сверка на картинках docx корпуса (corpus-tool imgcheck): PNG — 190 из 190 как у прежнего (±1 в предумноженном виде), JPEG — 296 картинок, PSNR медиана 64,7 дБ, минимум 45,4 дБ.meridian-render,meridian-ffi, corpus-tool и lab-site рисуют своимmeridian-raster(сделан сессией B); tiny-skia и zune-jpeg остались только эталонами в corpus-tool. Замер корпуса: изменения страниц в пределах ±0,004 SSIM, средний 0,699, строгий «по чернилам» 0,171 → 0,174. В ядре от чужих крейтов остались: harfrust/read-fonts/skrifa (шаги 7–8) и krilla (шаг 9). - 2026-10-04 — «Весь код свой», шаг 7 (TrueType).
meridian-font— свой разбор OpenType: каталог таблиц и TTC,head/hhea/OS/2/maxp/name,cmap(форматы 4/6/12/13, выбор подтаблицы как у FreeType, символьные шрифты),hmtx, контурыglyf/loca(неявные точки, составные глифы с матрицами и округлением, фантомная точка начала координат сUSE_MY_METRICS),kernформата 0. Сверка (tests/oracle.rs, эталоны read-fonts/skrifa только в тестах): 11 шрифтов комплекта и 172 системных TrueType macOS — метрики,cmapпо всем 1,1 млн кодов, продвижения и растр контуров каждого глифа совпали.meridian-layout(метрики, имя, начертание, покрытие) иmeridian-render(контуры) переведены; skrifa из продукта ушла; рендер корпуса побайтно тот же. Осталось: контуры CFF/CFF2 и шаг 8 (свой шейпер вместо harfrust, ему пока нужен read-fonts). - 2026-10-04 — «Весь код свой», шаг 7 (CFF).
meridian-fontрисует контуры PostScript (CFF): INDEX/DICT, CharStrings, локальные и глобальные подпрограммы со смещением, CID-шрифты (FDArray, FDSelect форматов 0 и 3), интерпретатор Type 2 со всеми операторами пути (включая flex/hflex/hflex1/flex1), подсказки и маски пропускаются; предел вложенности 10 и бюджет 200 тыс. операторов на глиф. Сверка (tests/oracle.rs,MERIDIAN_FONT_DIR, теперь и.otf/.ttcпо каждому шрифту коллекции): 118 системных шрифтов CFF (STIX, Noto, Kohinoor, Apple SD Gothic Neo, Hiragino) — ≈1,1 млн глифов растр в растр как у skrifa; тот же тест портит каждый 97-й байт шрифтов и проходит все глифы без паник. Не поддержаны:CFF2, нестандартнаяFontMatrix,seac. Шаг 7 закрыт; дальше — пары GPOS (просьба B: кернинг Inter только в GPOS) и шаг 8. - 2026-10-04 — Пары GPOS и таблица
kernApple (meridian-font, начало шага 8; просьба B — кернинг Inter есть только в GPOS). Общие структуры раскладки (layout.rs: Coverage 1/2, ClassDef 1/2, ScriptList/FeatureList/ LookupList),gpos.rs— PairPos форматов 1 и 2 с расширением (тип 9),kern.rs— заголовки Microsoft и Apple, форматы 0/2/3.kern()как у HarfBuzz: GPOS-признакkernважнее таблицыkern. Сверкаtests/kern.rsс harfrust: 224 шрифта, 7,1 млн пар, 161 тыс. с кернингом — 0 расхождений (у старой таблицы harfrust делит поправку между глифами, поэтому сравнивается сумма продвижений пары). Попутно по B: FFI рисует прямо в буфер оболочки (PixmapMut), свой эллипс заменён наPathBuilder::from_oval. - 2026-10-04 — «Весь код свой», шаг 8 (этап 1): свой шейпер
meridian-shape. Устройство повторяет HarfBuzz, код новый: буфер с выходным буфером подстановок и слиянием кластеров, карта признаков со стадиями и паузами (какhb_ot_map), выбор письменности/языковой системы (теги письменностей, языки BCP 47 → теги OpenType по реестру — свой генераторlang_tables.rs), GDEF (классы, классы прикрепления, наборы меток, список испорченных GDEF), все типы GSUB (1–8, расширения, обратная цепочка) и GPOS (1–9: пары, курсив, метки к основе/лигатуре/метке, контекстные), итератор с пропуском (флаги правил, ZWJ/ZWNJ, скрытые), лигатуры с номерами компонентов, нормализация (разложение и составление по наличию глифов, порядок меток), запасное размещение меток и пробелов, таблицаkernпри шейпинге, шейпер иврита. Данные Юникода для шейпера — вmeridian-unicode(props: категория, класс комбинирования, письменность, зеркальные пары, разложения/составления, тип и группа соединения; генераторgenerate_props.rs), вmeridian-font—cmapформата 14, габариты глифов, открытыеData/layout/kern. Сверкаtests/oracle.rsс harfrust: 220 шрифтов (комплект, Inter, системные без AAT), тексты спайка A8 и проверочные строки (диакритика, дроби, невидимые, селекторы, зеркалирование), режимы «по умолчанию» и «как Word», 4 языка — 115 760 случаев, 8,6 млн глифов, совпали номер, кластер, продвижение и смещения каждого.meridian-layoutшейпит своим шейпером; harfrust остался для письменностей со сложными шейперами (арабская, индийские, тайская, хангыль, кхмерская, бирманская, USE) и шрифтов AAT — следующие этапы. Рендер корпуса побайтно тот же (286 страниц). - 2026-10-04 — Шаг 8, этап 2: арабский, тайский/лаосский,
хангыль. Арабский шейпер: автомат соединения букв по типам и
группам соединения Юникода с контекстом соседних отрезков, стадии форм
isol/fina/fin2/fin3/medi/med2/init,
rlig/calt/mset, растягиваниеstch, перенос модифицирующих меток, запасные формы для шрифтов без арабского GSUB (свой генераторarabic_tables.rsиз UnicodeData; таблица форм совпала с эталонной; из лигатур — лам-алеф и шадда с огласовками). Тайский/лаосский: сара ам → никхахит + сара аа с переносом, формы PUA для старых шрифтов без GSUB. Хангыль: составление/разложение слогов, ljmo/vjmo/tjmo, тоновые знаки. Сверка: тексты + 238 случаев с контекстом + новый тест случайных строк по 32 письменностям (406 тыс. строк на системных шрифтах и Noto) — расхождений нет, кроме известной ошибки harfrust (сара ам после двух надстрочных знаков: harfrust дублирует знак, наш результат совпадает сhb-shape14.3.1). Шрифты сkerxтеперь всегда идут прежним путём (harfrust применяетkerx, если в GPOS нетkern). Рендер корпуса побайтно тот же. Осталось: индийские, кхмерский, бирманский, USE. - 2026-10-04 — Шаг 8, этап 3: индийские, кхмерский,
бирманский, USE — все сложные шейперы свои. Общий модуль
слоговых шейперов: свой движок регулярных грамматик над категориями
(самое длинное совпадение, при равенстве — первое правило), вставка
пунктирного круга, ограничения гласных, проверка «применилось бы правило
GSUB». Свои генераторы таблиц из UCD 17: индийские категории/позиции
(
indic_tables.rs), категории USE (use_tables.rs, с поправками Microsoft из HarfBuzz 12.3.0, лицензия MIT —LICENSE-MS-USE.txt), ограничения гласных (vowel_tables.rs); правила — по генераторам HarfBuzz как описанию, код свой. Шейперы: индийский (база, реф, матры, pref, старая и новая модели), кхмерский (коэнг+Ра, cfar), бирманский (кинзи, медиали, сортировка позиций), USE (разбор без CGJ/ZWNJ перед меткой, rphf, топографические формы, соединение для арабоподобных). Сверка случайными строками по 32 письменностям: 765 тыс. строк — расхождений нет; где harfrust сам отступает от HarfBuzz на C, наш результат совпадает сhb-shape14.3.1 (тест перепроверяет им автоматически). Раскладка шейпит своим шейпером всё, кроме шрифтов AAT (morx/kerx/trak) — они пока через harfrust. Рендер корпуса побайтно тот же. - 2026-10-04 — Шаг 8 закрыт: harfrust и read-fonts ушли из
раскладки.
meridian-layoutшейпит только своимmeridian-shape; прежний путь через harfrust удалён вместе с зависимостями harfrust и read-fonts (они остались эталонами в тестахmeridian-fontиmeridian-shape). Ограничение: таблицы AAT (morx,kerx,trak) не применяются — раскладка загружает только шрифты комплекта (OpenType), системные шрифты не подключаются; если появятся шрифты AAT, их поддержка — отдельный пункт. В продукте из чужого кода для шрифтов осталось только то, что тянет krilla (PDF, шаг 9: read-fonts/skrifa внутри krilla). Рендер корпуса побайтно тот же. - 2026-10-04 — Шаг 9: свой писатель PDF/A-2b
meridian-pdf, krilla убран. Новый крейт без чужого кода (ISO 32000-1, ISO 19005-2): объекты, xref, потоки Flate на своём DEFLATE, детерминированный /ID; шрифты — Type0 с Identity-H, потомок CIDFontType2 с подмножеством TrueType (glyf/loca пересобраны, номера глифов сохранены, составные тянут компоненты, контрольные суммы иcheckSumAdjustmentпересчитаны) или CIDFontType0 для CFF (OpenType целиком), ширины W из hmtx; ToUnicode закрепляет значение глифа при первой встрече, кластеры, которые им не выражаются (лигатура из нескольких глифов, перестановка), идут под/Span /ActualText. Картинки: JPEG с 1/3 компонентами как есть (DCTDecode), остальное — RGB Flate + SMask (группа прозрачности на странице). PDF/A: XMP (pdfaid 2/B, dc:title, dc:language, даты), назначение вывода GTS_PDFA1 со своим профилем ICC sRGB v2 (первичные цвета по Брэдфорду к D50, кривая sRGB 1024 точки), без словаря Info.meridian-render::export_pdf— тот же API, позиции глифов ровно из раскладки (числа TJ; сдвиги меньше 0,01/1000 кегля не пишутся, перо считается точно). Проверка: veraPDF 1.30.2 (внешний инструмент) — 160/160 документов корпуса PASS, отдельно шрифт CFF (Noto Javanese) PASS; растрpdftoppm1 428 страниц против прежнего PDF krilla — средняя разница 0,007 из 255, наибольшая 0,57 (картинка);pdftotext— текст совпал у всех 160. Объём файлов +7 % к krilla (без оптимизации потоков). krilla, pdf-writer, subsetter, skrifa, read-fonts и др. ушли из Cargo.lock (−274 строки), THIRD_PARTY/NOTICE/SBOM перегенерированы. Тестmeridian-pdf/tests/pdf.rs: xref, детерминизм, контуры подмножества, ToUnicode, ActualText. - 2026-10-04 — Шаг 10, этап 1: свой движок формул
meridian-calc. Форк IronCalc переехал вkernel/oracles/ironcalcиkernel/oracles/ironcalc-xlsx(пакетыoracle-ironcalc*, scope «dev» в third_party.toml — по согласию B; в продукт не входит, нужен только как эталон тестов). Имяmeridian-calcзанял свой движок поdocs/apps/sheets.md§4–5: лексер канонической записи (ссылки A1, столбцы и строки целиком, 3D и внешние ссылки, структурированные ссылки,_xlfn./_xlpm.), парсер Пратта с приоритетами Excel (-2^2 = 4,2^3^2 = 64, пересечение пробелом, объединение в скобках,#,@, вызов LAMBDA), печать формулы; вычислитель со ссылками-диапазонами, поэлементным применением к массивам (правила расширения Excel), неявным пересечением, разливом и#SPILL!(блокировка и снятие), именами, LET/LAMBDA/MAP/REDUCE/SCAN/BYROW/BYCOL/MAKEARRAY; граф зависимостей (ячейки, диапазоны по столбцам, волатильные) и пересчёт в порядке Кана с вычислением по требованию в потоке с большим стеком, циклы →circular; приведение типов и даты по §5.8–5.9 (15 цифр «Общего», ошибка 1900 года). Функций ≈ 250: математика, статистика и*IF/*IFSс критериями и подстановочными знаками, логические, текст (UTF-16 как в Excel), информационные, поиск (VLOOKUP…XLOOKUP, INDEX, OFFSET, INDIRECT), динамические массивы (FILTER, SORT, UNIQUE, TAKE/DROP, VSTACK…), дата и время. Проверка: 15 948 формул xlsx корпуса разбираются и печатаются обратно; сверка с эталоном — 265 формул вручную и 50 тыс. случайных выражений совпадают; расхождения только там, где эталон отступает от Excel (перечислены в тесте с причиной: 17 цифр вместо 15 в тексте,"<>текст"в COUNTIF, переполнение EXP, DATE(1900;2;29), RANK.AVG и др.). Обратная цепочка 100 тыс. формул: построение 72 мс, пересчёт 43 мс (форк: 462 и 48 мс). Дальше — остальные функции каталога, TEXT и числовые форматы, свой xlsx, локаль ru. - 2026-10-04 — Шаг 10, этапы 2–3: все функции и сверка с
Excel.
meridian-calcдорос до 497 функций — все 496 функций каталога форка IronCalc плюс PERCENTOF: финансовые (аннуитеты, облигации и купоны, ODDF*/ODDL* по квазикупонным периодам — примеры документации Excel совпадают до последнего знака), инженерные (Бессель K — по полиномам Абрамовица — Стиган, как в Excel), распределения и регрессия (special.rs: ln Γ Ланцоша, erf, неполные гамма и бета), базы данных, SUBTOTAL/AGGREGATE, матрицы, TEXT/FIXED/DOLLAR на своих числовых форматах (numfmt.rs), REGEX* на своём движке регулярных выражений (regex.rs, подмножество PCRE2), FORECAST.ETS* (Хольт — Винтерс; у форка не реализованы). Таблицы Excel и структурированные ссылки (tables.rs), формулы массива старого типа (фиксированная область), неявное пересечение для формул до Excel 365. Новый крейтmeridian-calc-xlsx: чтение xlsx на своём ZIP/XML (листы, общие строки, общие и массивные формулы со сдвигом ссылок, имена, таблицы, форматы). Главная проверка — значения Excel: 151 книга корпуса, 27 508 формул пересчитаны своим движком, 99,94 % совпадают со значениями, сохранёнными Excel; остаток — 16 ячеек файла стороннего производителя с десятичной запятой в формуле (=L6-(-4,3), в Excel это #VALUE!). Сверка с форком: 606 формул вручную + 50 тыс. случайных, расхождения — только ошибки форка (перечислены в тесте с причиной). - 2026-10-04 — Шаг 10: запись xlsx.
meridian_calc_xlsx::write_xlsx— своя запись SpreadsheetML: листы с константами и формулами, общие строки, имена, минимальные стили; формулы в файловой форме (функции Excel 2010+ с_xlfn., FILTER/SORT —_xlfn._xlws., параметры LAMBDA/LET —_xlpm., неявное пересечение старых формул снимается), разлив — формулой массива на области,fullCalcOnLoad. Круговой путь (tests/roundtrip.rs): 160 книг корпуса читаются, пересчитываются, записываются и читаются снова — значения и формулы совпадают; каждый записанный файл открывает и независимый читатель (импорт форка IronCalc). - 2026-10-04 — Шаг 10: русская локаль формул.
meridian_calc::locale— ввод и показ формул в локали при каноническом хранении: имена функций (≈ 220 русских имён Excel; остальные принимаются по-английски, как в Excel), ИСТИНА/ЛОЖЬ, ошибки (#ДЕЛ/0!,#Н/Д,#ССЫЛКА!…),;между аргументами, десятичная запятая, разделители массивов{1;2\3;4}; строки и имена листов в кавычках не трогаются. Ввод значений:1 000,5,12,5%,04.10.2026 12:00; точка в русском вводе — не десятичная. API:Workbook::set_input_in,formula_in. - 2026-10-04 — Шаг 4а: словарное деление тайского, лаосского,
кхмерского и бирманского. Новый крейт
meridian-segment— свой алгоритм: участки одной письменности, разрешённые границы только между графемными кластерами (не перед знаками, не после вирамы/коенга/пхинтху, не после «передних» гласных, не перед гласными, цепляющимися к слогу), разбиение динамическим программированием (меньше символов вне словаря, затем меньше слов; длинные слова раньше), куски вне словаря сливаются. Словари — списки слов ICU 77.1 как данные (тайский и кхмерский — лицензия Unicode V3, лаосский — BSD-2, бирманский — BSD-3; уведомления вdata/и NOTICE), сжаты своим DEFLATE (≈ 1 МБ). Сверка с ICU 76 (BreakIterator в одноразовом контейнере на sagr, статьи Википедии, эталон вне git): F1 границ — тайский 0,987, лаосский 0,978, бирманский 0,974, кхмерский 0,939 (у ICU для кхмерского свои эвристики слияния слогов).meridian-layoutдобавляет эти границы к разрывам UAX #14; рендер корпуса docx побайтно тот же (286 страниц). Запрос B — внести словари ICU в third_party.toml. - 2026-10-04 — Нормализация Юникода
meridian_unicode::{nfc, nfd}(по просьбе B — NFC паролей в meridian-crypto вместо крейта unicode-normalization): полное каноническое разложение, канонический порядок знаков, каноническое составление с блокировкой по UAX #15 на таблицах UCD 17. NormalizationTest.txt 17.0: 20 034 строки, расхождений нет. Совместимые формы (NFKC/NFKD) не нужны и не поддерживаются. - 2026-10-04 — П. 5 плана своего кода: свои криптопримитивы
meridian-cipher(решение владельца — своё, по согласованию с B). Без внешних зависимостей,deny(unsafe_code)(кроме вызова getentropy/ProcessPrng): SHA-256 (FIPS 180-4), HMAC и HKDF (RFC 2104/5869), BLAKE2b (RFC 7693), Argon2id (RFC 9106), AES-256 (FIPS 197) с S-блоком без таблиц — 64 байта разом в восьми битовых плоскостях u64, обращение x^254 в GF(2^8) и аффинное преобразование, — GCM (SP 800-38D) с умножением в GF(2^128) через маски, без ветвлений и таблиц;ct::eq/wipe, Base64 (RFC 4648),rng::fill(getentropy / ProcessPrng / /dev/urandom). Ключи раундов затираются при Drop, открытый текст — при неверном теге. Тесты: векторы стандартов; разностный против RustCrypto (dev-зависимости, 300 раундов случайных длин до 5 КБ, Argon2id на 5 наборах) — побайтно те же выходы;tests/timing.rs— замер в духе dudect (два класса входов вперемешку, t Уэлча по партиям, верхние 5 % отброшены): |t| < 3,5 для AES по данным и по ключу и для GHASH, стенд ловит сравнение с ранним выходом (t ≈ 900). B может переключатьmeridian-crypto. - 2026-10-04 — Шаг 10: C ABI книг Sheets (контракт
v0.4).
meridian-ffi::sheet—MeridianBookна своём движке формул: новая книга по локали, открытие xlsx с пересчётом, сохранение в xlsx, листы, занятая область, текст ячейки для сетки и для строки формул, вид и число значения, ввод как с клавиатуры (пересчёт зависимых; ошибка в формуле не меняет ячейку), числовые форматы.meridian_calc::display— показ по числовому формату с разделителями локали (numfmt::format_number_with: русские — запятая и неразрывный пробел; встроенная дата 14 →ДД.ММ.ГГГГ, как в русском Excel) и текст строки формул, который при вводе даёт то же значение (15 значащих цифр, даты, проценты, апостроф перед текстом, похожим на число;set_input_inпонимает апостроф).meridian-calc-xlsx:cell_formatsиwrite_xlsx_with_formats— числовые форматы читаются и пишутся (встроенные номера 1–49, свои с 164), пустые ячейки со стилем сохраняются; круговой путь корпуса: 160 книг, 70 448 форматов без изменений. Пример на Cexamples/c/book.cсобирается и запускается тестомc_example. Следующий шаг — экран Sheets в оболочке (B). - 2026-10-04 —
meridian-cipher: аппаратный путь AES-256-GCM (запрос B: свой путь был в ~200 раз медленнее RustCrypto). Модульhw.rs— единственный сunsafe: aarch64 — AESE/AESMC и PMULL, x86_64 — AES-NI и PCLMULQDQ; команды проверяются при запуске, на Apple Silicon на время вызова включается DIT (время гарантированно не зависит от данных). AES — по 8 блоков за проход; GHASH — свёртка в «отражённом» представлении блока GCM (вывод в комментарии модуля) и агрегация по 4 блока со степенями H⁴…H¹ и одной свёрткой. Свой побитовый путь остался запасным (Aes256::new_software,Aes256Gcm::new_software) и ускорен вдвое (транспонирование плоскостей матрицами 8×8, квадрат в GF(2⁸) — линейный);encrypt_blocksпринимает любое число блоков. Скорость (M5 Max, 64 МБ): 2,3–2,7 ГБ/с (было 16 МБ/с; RustCrypto 3,1 ГБ/с), x86_64 под Rosetta — 2,3 ГБ/с; свой путь — 30 МБ/с. Проверка: разностный тест против RustCrypto для обоих путей, 20 тыс. случайных умножений GF(2¹²⁸) аппарат = свой, все тесты и на x86_64; замер dudect — оба пути, партия не короче 2 мкс (короче — шум разрешения таймера), замеры по одному, до трёх повторов с наименьшим |t|: все |t| < 4,5, самопроверка на утечке — t в сотни. - 2026-10-04 — Переименование «Meridian Office» → «MOffice»,
этап 1 в зоне A (решение владельца № 41, передано сессией
«Анализ приложения и план работ»): видимые имена в docs/algorithms,
docs/04-file-formats.md, docs/apps (write, sheets, slides, draw, paint,
pdf, math), doc-комментариях и описаниях крейтов ядра и инструментов,
NOTICE, заголовке
meridian.h, шапке стенда (MOffice Lab), манифесте корпуса, XMP PDF (CreatorTool/Producer— MOffice): «Meridian Office» → «MOffice», «Meridian Write/Sheets/…/Print/Cloud/ID/…» → «MOffice …», MeridianScript → MOffice Script, «Meridian-режим» → «MOffice-режим». Не тронуто (этап 2 — только по слову владельца): имена крейтовmeridian-*, C ABImeridian_*/MERIDIAN_*,meridian.h, идентификаторы кода (TypographyMode::Meridian,Meridian.Fragment, UTIru.meridian-office.*), заголовокX-Meridian-Report, примеры данных в XML, крейты зоны B (meridian-raster,meridian-license,meridian-crypto) и эталонный пароль в векторах meridian-crypto. - 2026-10-04 — Шрифты-данные комплекта (решение № 43) и шрифты
темы для письменностей. В
kernel/fontsдобавлены из первоисточников (OFL-1.1, файлы без изменений): Caladea ×4 (замена Cambria; есть в 79 из 98 документов стенда как шрифт темы), Gelasio ×4 (Georgia), курсивы Carlito (Calibri — 437 из 486 docx корпуса), Liberation Mono Bold/Italic/ BoldItalic; комплект — 24 файла, ≈ 7,9 МБ вшито. Замены совпадают с оригиналами по ширинам, но не по высоте строки (Caladea 1,30 em против 1,172 у Cambria, Gelasio 1,66 против 1,136 у Georgia — числа сняты с оригиналов на Mac владельца): раскладка берёт для них вертикальные метрики оригинала (ORIGINAL_LINE_METRICS), как считает Word. Запасные символы — по явному порядкуFALLBACK_ORDER(Carlito, Liberation…), а не по алфавиту файлов. Стенд нашёл ошибку в разборе docx:w:asciiTheme="majorBidi"сводился к латинице темы (Cambria), а по ECMA-376 этоa:csтемы, при пустом — шрифт письменности языкаw:lang w:bidi(a:font script="Arab"→ Times New Roman у документов Word 2007 сar-SA); то же для*EastAsia.ThemeFontsтеперь хранитea/cs/шрифты письменностей,CharProps— языкиeastAsia/bidi. Сверка с эталоном LibreOffice: страниц с SSIM ≥ 0,95 — 60 (как было), средний SSIM 0,694 (было 0,699), число страниц совпало у 87 из 98 (было 88). Остаток расхождения — эталон: LibreOffice на macOS считает строку Caladea по hhea (1,15 em), Word с настоящим Cambria — 1,172 em; прежнее «совпадение» держалось на неверной замене Cambria → Liberation Serif с той же высотой строки 1,15 em. Честная оценка — только с эталонами Word. - 2026-10-04 — MOffice, этап 2 в зоне A (решение №
44). В docs/04-file-formats.md, docs/algorithms и docs/apps
(write, sheets, slides, draw, paint, pdf, math): пространства имён
urn:meridian:office:<app>:1→urn:moffice:<app>:1(и прочиеurn:meridian:→urn:moffice:), MIMEapplication/vnd.meridian.*→application/vnd.moffice.*(spec/formats и meridian-crypto/license — зона B, согласовано то же правило). Видимые строки ядра:INFO("osversion")→ «MOffice», описание своего профиля sRGB в PDF — «sRGB IEC61966-2.1 (MOffice)» (XMP CreatorTool/Producer — MOffice с этапа 1; словаря Info в наших PDF/A нет). Стенд — основной адрес https://moffice-lab.24oros.ru, прежний meridian-lab.24oros.ru оставлен рабочим: маршрут Traefik на оба имени, строка в/etc/haproxy/sagr-domains.lstна VPS (бэкап.before-moffice-lab-…,haproxy -c— valid, reload). Не менялись (внутреннее кодовое имя): крейтыmeridian-*, C ABI,meridian.h, имя контейнера и файлов маршрута, UTIru.meridian-office.*в описании буфера обмена. - 2026-10-04 — Обтекание плавающих объектов «сверху и
снизу». По стенду: надписи есть в 12 из 98 документов, у 11
средний SSIM < 0,9; чаще всего у них обтекание «сверху и снизу».
Модель:
Anchor.wrap(Wrap::None/TopAndBottom/ Square/Tight),dist_top/dist_bottom; кодек читаетwp:wrap*иdistT/distB(DrawingML),w10:wrapиmso-wrap-distance-*(VML). Вёрстка: объект с таким обтеканием ставит на странице полосу, строки колонок, задетых объектом по горизонтали, её перепрыгивают (без правил висячих строк — это не конец страницы); если полоса появилась от объектов самого абзаца, его строки пересчитываются. «Вокруг рамки» и «по контуру» пока полоса, только когда рядом с объектом в колонке меньше дюйма; обтекание сбоку с переразбивкой строк — следующий шаг. Сверка: средний SSIM 0,694 → 0,698 (426080 +0,126), страниц ≥ 0,95 — 60. Тестtop_and_bottom_wrap_keeps_lines_out_of_the_band. - 2026-10-04 — Диаграммы,
mc:AlternateContent, вложенный HTML (w:altChunk). По худшим документам стенда: уchartex(1 страница против 3) пропадали все диаграммы —c:chartтеперь занимает место пустой рамкой своего размера (до своего движка диаграмм), аmc:AlternateContentвыбираетmc:Choiceтолько если понятны все префиксыRequires(wps, wpg, w14…), иначеmc:Fallback— как требует ECMA-376 ч. 3 (диаграммыcxWord 2016 — картинкой из Fallback): 0,286 → 0,663. Новый модульcodec_ooxml::html— свой импорт HTML (терпимый разбор, сущности, абзацы, заголовки, списки, таблицы,br, жирный/курсив/подчёркнутый; MHT — MIME, quoted-printable, base64) с умолчаниями Word для HTML (Times New Roman 12 pt, интервалы 14 pt);w:altChunkподставляет разобранные блоки:stress0120,182 → 0,526 (CSS пока не разбирается). Стенд: средний SSIM 0,698 → 0,705. - 2026-10-04 — Высокие колонтитулы опускают и поднимают текст,
как в Word. Стенд показал наезд таблицы верхнего колонтитула на
текст (
404064). Теперь перед вёрсткой раздела измеряются колонтитулы первой и остальных страниц (section_chrome), текст начинается не вышеполе колонтитула + высота верхнегои кончается не ниже начала нижнего. Тестtall_header_and_footer_push_the_body. Сверка с LibreOffice: средний SSIM 0,705 → 0,701, число страниц совпало у 84 (было 87): в трёх документах с таблицами в колонтитулах эталон ниже по высоте строк — LibreOffice не даёт высоты пустому абзацу после вложенной таблицы в конце ячейки (60329: строка 14 pt против наших 26 pt). Под это не подгоняю: нужен эталон Word. Проверено: интервал после последнего абзаца колонтитула на итог не влияет. - 2026-10-04 — Сноски. Модель:
Inline::Note { id, props, custom }(ссылкаw:footnoteReferenceили знакw:footnoteRefв тексте сноски;custom— свой знакw:customMarkFollows),Document.footnotes,footnote_separator; кодек читаетfootnotes.xmlсо своими связями. Вёрстка: номера по порядку первых ссылок (сноски со своим знаком номера не занимают), знак без стиля — надстрочный; строка знает свои сноски, при подборе строк на страницу их высота (и разделитель для первой сноски страницы) прибавляется к высоте строки; низ текста поднимается, сноски ставятся внизу над нижним колонтитулом под линией-разделителем (2″, высота — абзац-разделитель документа). Тестfootnotes_go_to_the_bottom_of_their_page. Стенд: 0,701 → 0,703 (372437+0,042). Пока нет: сносок из ячеек таблиц, переноса длинной сноски на следующую страницу, концевых сносок, разделителя справа в RTL. Найдено попутно: абзацы в рамкахw:framePr(абсолютное положение) ставятся в поток — следующий кандидат. - 2026-10-04 — Свойства абзаца и символов стиля
таблицы. Стиль таблицы (
TableGridи др.) задаёт тексту ячеек шрифт, кегль и интервалы (w:style w:type="table"→w:pPr/w:rPr); раньше они не применялись, и ячейки получали умолчания документа (Calibri 11, интервал 10 pt вместо Times New Roman 10 и 0). Модель:resolve_para_in/resolve_char_inсо слоем стиля таблицы между умолчаниями документа и стилем абзаца (ECMA-376 §17.7.2); вёрстка держит стек стилей таблиц (вложенные — внутренний последний), все разрешения стилей идут через него. Тестtable_style_layers_under_paragraph_styles. Стенд: страниц с SSIM ≥ 0,95 — 61 (было 60), средний 0,703 → 0,704 (table-alignment+0,088,Bug54849+0,083). - 2026-10-05 — Рамки абзацев
(
w:framePr). Модель:ParaProps.frame(Frame: размер с правилом высоты, привязка и смещение по осям, выравниваниеxAlign/yAlign, обтекание, отступыhSpace/vSpace, буквица); кодек читаетw:framePr(без привязки — от колонки и от места абзаца, как на стенде у Word-документов). Вёрстка: абзацы подряд с одинаковой рамкой — одна рамка вне потока (ширинаwили колонки, высота точная/«не меньше»/по содержимому), ставится по привязке;notBeside— полоса,around/auto— полоса, если рядом меньше дюйма (обтекание сбоку — следующий шаг),none— поверх. Буквицы пока в потоке. Тестframed_paragraphs_leave_the_flow_and_push_text_aside. Стенд:2249400,406 → 0,662 (страниц 5 → 4, как у эталона); страниц ≥ 0,95 — 62, средний SSIM 0,704 → 0,708. - 2026-10-05 — Разбор документов с оглавлением (6 на стенде,
все < 0,9). Две причины, обе зависят от эталона: (1) строки
оглавления несут стиль знака
Hyperlink(синий, подчёркнутый) — LibreOffice перестраивает оглавление сам и показывает их чёрными; (2)313486: перед текстом обложки стоит абзац только сw:br w:type="page"— мы честно переносим текст, LibreOffice ставит весь раздел на первую страницу, отсюда сдвиг на страницу во всём документе. Ни то, ни другое не подгоняю под LibreOffice: нужен эталон Word.