100 lines
12 KiB
Markdown
100 lines
12 KiB
Markdown
# Промт: сессия-БЭКЕНД — Трек A, пак-1.5 (экспорт-поверхность + глосс-whitelist + пример), 2026-07-16
|
||
|
||
> Малый хирургический пак ПОСЛЕ приёмки пака-1 (D39.2, `d3f6b34`). Три задачи — все НЕ гейтятся
|
||
> эмпирикой exp15 и закрывают открытые вопросы D39.2 с решениями владельца от 16.07. Крупные слои
|
||
> (чанкер B1, кнобы когезии, дифф-apply) **НЕ строить** — они гейтятся результатами exp15 (research/19 §D).
|
||
> Смысл окна: все снапшот-сдвиги этого пака ложатся В ТОТ ЖЕ единый `--resnapshot`, который и так
|
||
> предстоит (D38.5+пак-1) — сейчас они бесплатны, после resnapshot стоили бы вторую переоплату книги.
|
||
|
||
## Зона/дисциплина (как в паке-1)
|
||
`backend/` только; не коммитить; `.env` не читать; мандат самопроверки ИСПОЛНЕНИЕМ (build/vet/gofmt/
|
||
test -race, каждый фикс запинен firing+non-firing тестом, ДО/ПОСЛЕ на сконструированном входе);
|
||
golden = инвариант №8 — re-capture только с обоснованием «что и почему сдвинулось» (ратифицировано
|
||
D39.2-open + решения владельца 16.07); git status перед работой — в дереве возможны параллельные сессии.
|
||
|
||
## Онбординг
|
||
`CLAUDE.md` → D-лог **D39.2** (что залендено паком-1 + открытые вопросы) → `09-target-architecture.md`
|
||
§2 (слой 6) → свой же код пака-1 (sanitizer.go exportNormalize/detectCJKLeak/stripCosmetic,
|
||
chunkrun.go FinalText, cmd/tmctl).
|
||
|
||
## T1 — Read-only экспорт-поверхность для полигона (закрывает D39.2-open №1; НУЖНО ДО пере-прогона)
|
||
**Проблема:** exportNormalize живёт на бэкенд-поверхностях (translate stdout / report), а полигонная
|
||
экстракция (`records.json`/exp12_extract-класс) читает СЫРЫЕ чекпоинты из store → полигон и
|
||
читатель-сэмплы увидят НЕнормализованный текст. Решение оркестратора: НЕ Python-зеркало нормализации
|
||
(анти-паттерн зеркального дрейфа), а **бэкенд-поверхность**.
|
||
**Сделать:** read-only команда `tmctl export` (проекция класса `status`/`report`: OpenReadOnly, $0,
|
||
без снапшот-влияния): для каждого чанка книги эмитит финальный экспорт-текст РОВНО по прод-семантике
|
||
(`chunk_status.final_hash` → checkpoint.response_text → [для `sanitizer_stripped` — это уже
|
||
стрипнутый derived-чекпоинт] → `exportNormalize`) + метаданные (chapter/chunk/disposition/flag/
|
||
snapshot_id) в стабильном JSON (+опц. plaintext). Флагнутые-непоправимые — пустой текст + причина
|
||
(как FinalText-семантика). Это и есть отложенный `tmctl export` из D15.2-этап-Б в минимальной форме —
|
||
НЕ строй annotations/override-часть, только чтение. Тест: export == translate-FinalText байт-в-байт
|
||
на golden-фикстуре (fresh и resume).
|
||
|
||
## T2 — CJK-глосс-whitelist (решение владельца 16.07: глоссы СОХРАНЯТЬ)
|
||
**Сейчас:** `stripCosmetic` стрипает намеренный глосс «Кулак Ло Ханя (羅漢拳)» и пустит скобку;
|
||
`detectCJKLeak` флагует такой Han-ран. **Сделать:** узкий whitelist — **сбалансированный Han-ран
|
||
целиком внутри скобок, непосредственно после кириллического/латинского слова-головы** (паттерн
|
||
«терм (漢字)») — НЕ утечка: `detectCJKLeak` не флагует, `stripCosmetic`/`exportNormalize` сохраняют
|
||
байты глосса (вкл. НЕ-фолд его полноширинных символов, если они часть глосса). Голый Han вне этого
|
||
паттерна — по-прежнему утечка (прод-класс cjk_leak цел). Краевые: вложенные скобки, глосс с пробелами/
|
||
пиньинем, глосс в начале строки без головы (→ утечка), два глосса подряд. `sanitizerVersion` v5→v6 +
|
||
golden re-capture (обоснование: решение владельца). Тесты: глосс сохранён (strip и normalize),
|
||
standalone-Han флагуется, пустая скобка больше не рождается.
|
||
|
||
## T3 — `example/book.yaml`: вернуть runnable
|
||
После pair-сеама ja-пример fail-loud'ится через zh-ru-keyed pipeline-c1 (сеам работает как задуман).
|
||
**Сделать:** переоформить пример на **zh→ru** (реальный прод-контент пары уже есть) — пример снова
|
||
проходит end-to-end; рядом закомментированный ja-блок с пояснением «fail-loud до появления ja-ru
|
||
пакета» (демонстрация сеама, не заглушка). ja-ru пакет НЕ сочинять (контент пары = данные под
|
||
реальную книгу, инвариант общности §0.1).
|
||
|
||
## T4 — ФИКС-ЛИСТ адверсариала (долг D39.2 ПОГАШЕН 17.07: 8 осей, оба пака; 0 CRITICAL / 1 HIGH / 6 MEDIUM)
|
||
T1–T3 исполнены и верифицированы оркестратором (не лендились — ждут этих фиксов, чтобы санитайзер-бамп
|
||
и golden re-capture легли ОДНИМ лендингом). Обязательные (F1–F6) + дешёвые LOW (F7–F9):
|
||
|
||
**F1 (HIGH, санитайзер — обход гейта, воспроизведён исполнением).** 5 из 6 классов детектят по СЫРОМУ
|
||
тексту (fold делает только detectCJKLeak), а exportNormalize шипит СВЁРНУТЫЕ байты → полноширинная
|
||
вариация сигнатуры обходит детектор, и нормализация ИЗГОТАВЛИВАЕТ ASCII-форму дефекта в экспорте:
|
||
«Вот отредактированный перевод:»(U+FF1A) / «### Глава 5» / trailing «Примечание:…» / fullwidth-латиница
|
||
с U+3000 — все total=0, а в экспорте — ASCII-дефект (ASCII-близнецы при этом флагуются). Регресс vs v4
|
||
(тот фолдил весь U+FF00–FFEF блок и re-check ловил). **Фикс:** fold-first — `t := recoverableFold(text)`
|
||
в начале sanitizeOutput; ВСЕ шесть классов + глосс-маскирование работают по свёрнутому тексту
|
||
(детекция по folded; strip/export-пути сохраняют оригинальные байты; глосс-спаны пере-анкерить
|
||
согласованно). + инвариант-тест гейта: для чистого вердикта `sanitizeOutput(exportNormalize(x)).total()==0`
|
||
по всему тест-корпусу. Версия: v6 НЕ лендился — влить fold-first в ТОТ ЖЕ бамп v5→v6, один golden re-capture.
|
||
**F2 (MED, глосс — unbounded латиница; найден независимо осями 4 и 8).** isValidGloss ограничивает
|
||
только CJK: «Кулак (拳 the quick brown fox…) взлетел.» = total 0, английская фраза уезжает чистой (без
|
||
拳 — substantive drop). **Фикс:** ограничить не-CJK контент — кап полной внутренней длины (~24 руны) +
|
||
пиньинь-правдоподобные латин-токены (lowercase, ≤~7 рун токен, ≤~maxGlossCJKRunes+2 токенов). Запинить
|
||
тестом «(拳 the iron fist that breaks the sky)» → НЕ глосс.
|
||
**F3 (MED, export — gate-drift).** `Export()` читает `PostcheckGate` из ТЕКУЩЕГО конфига: флип гейта
|
||
между прогоном и экспортом тихо шипит удержанный текст (или фабрикует glossary_miss). **Фикс:** сравнить
|
||
SnapshotID строк с текущей проекцией (`currentSnapshotProjected`, как status) → fail-loud ИЛИ top-level
|
||
`config_drift` поле + WARN; docstring-caveat расширить на gate-flip вариант.
|
||
**F4 (MED, export — нет manifest-сверки).** Частичная книга экспортится молча как полная (класс
|
||
D37-скью для полигона); пустая книга даёт `"chunks": null`; ghost-строки удалённой главы экспортятся.
|
||
**Фикс:** `Chunks` = non-nil `[]`; join с $0-манифестом (`bookChunks`) → pending/missing явными
|
||
строками или `total/missing`-счётчиками; строки вне манифеста — drop или громкая метка.
|
||
**F5 (MED, quality — популяция KPI).** QualityReport считает gate-withheld чанки в TextChunks/KPI
|
||
(их экспорт = ""), расходясь с export. **Фикс:** зеркалить gateOn re-derivation (данные уже читаются) —
|
||
исключать из TextChunks/KPI.
|
||
**F6 (MED, quality — метка метрики).** `cjk_leak_rate` считает ВСЕ sanitizer_stripped, вкл.
|
||
markdown-only (ложные 30% «CJK-утечек»). **Фикс:** сплит по классу strip (из detail) на
|
||
`markdown_strip`/`cjk_leak` ИЛИ переименовать в `cosmetic_strip_rate`.
|
||
**F7 (LOW, 1 строка).** resume.go stripped-ветка: `sr.Model = cp.ModelActual` (зеркало ok-ветки) —
|
||
иначе resumed-строка телеметрии атрибутируется конфиг-слагу вместо фактической модели.
|
||
**F8 (LOW, 1 строка).** example/book.yaml: `transcription: pinyin` → `palladius` (ru-target конвенция;
|
||
самопротиворечие примера).
|
||
**F9 (LOW).** Export fail-loud parity: DispOK-строка с ПУСТЫМ final_hash → тоже громко (сейчас уже
|
||
комментарий обещает resume-дисциплину — довести до неё).
|
||
|
||
В ledger/очередь (НЕ этот пак): Retries не в снапшоте (pre-existing, дизайн); pair-fail-loud после
|
||
store.Open + report/export не требуют промптов (дизайн-вопрос); trustGateEvent только первый отказ;
|
||
WarnContext на каждом resume; quality 0.00 при all-dialogue; пунктуационные «огрызки» в НЕ-whitelisted
|
||
скобках; golden-ячейка глосса и escalated+stripped (желательно добавить тестами при F1/F2).
|
||
|
||
## Deliverable
|
||
Отчёт в ответе (не в PROGRESS): per-T — file:line, ДО/ПОСЛЕ, какие снапшот-версии/golden сдвинулись и
|
||
почему, результаты build/vet/gofmt/test -race, само-ревью исполнением. Открытые вопросы — списком.
|
||
Не коммитить — лендит оркестратор.
|