diff --git a/docs/README.md b/docs/README.md index 893a6cd..93d3529 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,7 +11,7 @@ ## Структура -- `architecture/` — синтез. **Источник истины по решениям — [`05-decisions-log.md`](architecture/05-decisions-log.md) (D1–D25); при конфликте с любым доком он выше.** +- `architecture/` — синтез. **Источник истины по решениям — [`05-decisions-log.md`](architecture/05-decisions-log.md) (D1–D30); при конфликте с любым доком он выше.** - `01-decisions.md` — принципы Р1–Р10; `02-mvp-plan.md` — фазы и приёмка (v3, 09.07); `03-implementation-notes.md` — контракты Фазы 0; `04-unhappy-paths.md` — ~70 режимов отказа → механизм; `06-memory-risk-registry.md` — реестр рисков банка памяти; **[`07-strategic-review.md`](architecture/07-strategic-review.md) — стратегический аудит (09.07): вердикт end-to-end, топ-риски, курс-коррекции**; `components.puml`/`pipeline.puml` — диаграммы v3 (владелец смотрит PlantUML-расширением VS Code; вручную НЕ рендерить). - `experiments/` — эмпирика «Полигона»: `00-provider-quirks` (читать перед любым вызовом провайдера), `01-token-calibration`, `02-refusal-benchmark`, `03-local-stand`, `04-editor-quality`, `06-local-extraction`, `07-coverage-precision`, `08-cost-model-v2` (актуальная денежная модель), `09-pilot-protocol` (пилот Ф2.5 + поправки D13), `10-explicit-benchmark` (18+ violence-рука канала B), `11-erotica-benchmark` (erotica по трём парам/регистрам — закрытие D14.4, D22). - `research/` — фактура исследований 04–05.07: `01–10` базовые, `11-gap-*` добор критиком, `12-*` режимы отказа/отзывы/таксономии (+ два внешних материала с провенанс-шапками), `13` валидация памяти, `14` адаптивная память, `15` голос и состояние (принят, D21), **`17` внешняя критика GPT-5.6 (принят с ревью-шапкой, D25 — читать шапку прежде тела)**. ⚠ Часть под superseded-баннерами (01/02/03/04/05/09 и gap-1/2/5) — **читай баннер прежде содержимого**. diff --git a/eval/exp12_monitor.py b/eval/exp12_monitor.py new file mode 100644 index 0000000..ffb80ba --- /dev/null +++ b/eval/exp12_monitor.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +"""exp12 — «монитор»: локальная HTML-страница ОРИГИНАЛ + все варианты перевода, СЛЕПО. + +По запросу владельца: удобный просмотр для сравнения и для загрузки (оригинал+вариант) во +флагманские модели (Fable 5/5.6) + место под любительский перевод. ЛОКАЛЬНЫЙ файл (текст книги +копирайтный → держим на машине владельца, ВНЕ git/хостинга). + +СЛЕПОТА: имена моделей в мониторе НЕ показаны; варианты под нейтральными метками, перемешаны +СВОЕЙ перестановкой в каждой главе (D13.5). Ключ соответствий — в ОТДЕЛЬНОМ файле +`diag/reading/_МОНИТОР_КЛЮЧ.json` (не открывать до вынесения оценки). + +Выход: /home/ubuntu/books/gu-zhenren/diag/reading/monitor.html +""" +from __future__ import annotations +import html, json, random +from pathlib import Path + +DIAG = Path("/home/ubuntu/books/gu-zhenren/diag") +ARMS = DIAG / "arms" +chunks = json.loads((DIAG / "chunks.json").read_text(encoding="utf-8")) +CH = [(5, "смешанная (нарратив+диалог)"), (7, "диалого-плотная"), (14, "экспозиция/описание")] +CHUNKS = {5: [0, 1], 7: [0, 1], 14: [0, 1]} +SALT = "exp12-monitor-blind-v1" + +POOL = ["A0", "A1", "A2", "A5", "CAND", "A3", "A4", "A6"] # порядок неважен — тасуется +LEGEND = { + "A0": "черновик deepseek (без редактуры)", + "A1": "glm-5 монолингвальный (= финал этапа A, что читал владелец)", + "A2": "glm-5 билингвальный", + "A5": "gemini-3.1-pro билингвальный (⚠ течёт преамбулой)", + "CAND": "КАНДИДАТ: glm-5 билингв + реверстка + жанр-конвенции", + "A3": "grok-4.3 моно (reasoning-off, ≈ черновик)", + "A4": "grok-4.3 билингв (reasoning-off, ≈ черновик)", + "A6": "grok-4.3 моно без глоссария (reasoning-off, ≈ черновик)", +} + + +def strip_preamble(t): + """gemini (A5) течёт служебной преамбулой «Вот отредактированный перевод…: ***». Снимаем + для ЧЕСТНОГО сравнения ПРОЗЫ (сам дефект утечки задокументирован в отчёте §4.1).""" + first = t.lstrip().split("\n", 1)[0] + if first.startswith("Вот ") and "перевод" in first.lower(): + if "***" in t: + t = t.split("***", 1)[1] + else: # преамбула = первая строка, дальше текст + t = t.split("\n", 1)[1] if "\n" in t else t + return t.strip() + + +def arm_text(arm, ch): + parts = [] + for ci in CHUNKS[ch]: + key = f"{ch}/{ci}" + if arm == "A0": + t = chunks[key]["draft"] + elif arm == "A1": + t = chunks[key]["final"] + else: + p = ARMS / arm / f"{ch}_{ci}.txt" + t = p.read_text(encoding="utf-8").strip() if p.exists() else "(нет)" + if arm == "A5": + t = strip_preamble(t) + parts.append(t.strip()) + return "\n\n".join(parts) + + +def source_text(ch): + return "\n\n".join(chunks[f"{ch}/{ci}"]["source"] for ci in CHUNKS[ch]) + + +CSS = """ +:root{--bg:#faf9f7;--fg:#1c1a17;--card:#fff;--bd:#e3ddd3;--mut:#8a8177;--acc:#7a5c3e} +@media(prefers-color-scheme:dark){:root{--bg:#17150f;--fg:#e8e3d8;--card:#211e17;--bd:#38332a;--mut:#9c9384;--acc:#c9a678}} +*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.6 Georgia,"Noto Serif",serif} +.wrap{max-width:1180px;margin:0 auto;padding:24px} +h1{font-size:24px;margin:0 0 6px}.sub{color:var(--mut);font-size:14px;margin:0 0 20px;line-height:1.5} +.chap{margin:34px 0 8px;font-size:20px;border-bottom:2px solid var(--acc);padding-bottom:6px} +.src{background:var(--card);border:1px solid var(--bd);border-radius:10px;padding:14px 16px;margin:12px 0 20px} +.src .lbl{color:var(--acc);font-weight:700;font-size:13px;letter-spacing:.03em;text-transform:uppercase} +.grid{display:grid;grid-template-columns:1fr;gap:14px} +.card{background:var(--card);border:1px solid var(--bd);border-radius:10px;overflow:hidden} +.hd{display:flex;align-items:center;gap:10px;padding:11px 14px;cursor:pointer;border-bottom:1px solid var(--bd)} +.hd .t{font-weight:700;font-size:15px} +.body{padding:6px 16px 14px;white-space:pre-wrap;font-size:15.5px} +.body.zh{font-family:"Noto Sans CJK SC","Microsoft YaHei",sans-serif;font-size:15px} +button{font:inherit;font-size:12.5px;background:var(--acc);color:#fff;border:0;border-radius:6px;padding:5px 11px;cursor:pointer} +button.ghost{background:transparent;color:var(--acc);border:1px solid var(--acc)} +.slot{border:2px dashed var(--bd);border-radius:10px;padding:16px;color:var(--mut);font-size:14px;margin-top:14px} +.toolbar{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 0} +.note{background:var(--card);border:1px solid var(--bd);border-left:3px solid var(--acc);border-radius:8px;padding:10px 14px;font-size:13.5px;color:var(--mut);margin:16px 0} +""" + +JS = """ +function esc(id){var e=document.getElementById(id);return e?e.textContent:''} +function copyOne(vid){navigator.clipboard.writeText(esc(vid));flash(event.target)} +function copyPair(sid,vid){navigator.clipboard.writeText('=== ОРИГИНАЛ (zh) ===\\n'+esc(sid)+'\\n\\n=== ПЕРЕВОД ===\\n'+esc(vid));flash(event.target)} +function flash(b){var o=b.textContent;b.textContent='✓ скопировано';setTimeout(function(){b.textContent=o},1200)} +""" + + +def main(): + key_map = {} + out = ['
Оригинал + варианты редактуры по 3 главам, СЛЕПО: имена моделей скрыты, '
+ 'варианты перемешаны по-своему в каждой главе («V3» в гл.5 и гл.7 — РАЗНЫЕ конфиги). '
+ 'Кнопка «копировать оригинал+перевод» кладёт пару в буфер для загрузки во флагман (Fable 5/5.6) — '
+ 'имя модели не копируется, флагман судит слепо. Любительский перевод добавляй сам. '
+ 'Ключ соответствий — в файле _МОНИТОР_КЛЮЧ.json рядом, НЕ открывай до вынесения оценки.