239 lines
24 KiB
Markdown
239 lines
24 KiB
Markdown
# PACK11_REPORT — бэкенд-сессия по плану 11 (2026-07-19)
|
||
|
||
> Строил по `docs/architecture/11-implementation-plan.md` (ратифицирован D39.12). **НЕ коммитил** —
|
||
> сдача на приёмку оркестратору. Верификация исполнением: `go build ./... && go vet ./... &&
|
||
> go test -race ./...` — зелёное (логи ниже). Все несущие изменения сверены с живым HEAD-кодом.
|
||
|
||
## 0. Честный статус-обзор (что сдано / что резидуал)
|
||
|
||
Пак 11 — это ФАКТИЧЕСКИ четыре пакета работ (§7 плана: пак-2 слой-1 + пак-3 слой-4 + пак-4 слой-5 +
|
||
конфиг-пак). За одну сессию доведено до **зелёного, оттестированного, лендабельного** состояния:
|
||
|
||
| WS | Компонент | Статус |
|
||
|---|---|---|
|
||
| **WS2** | чанкер output-бюджет + edit-единицы + oversized-флаг + src→dst редактор + снапшот-фолды + golden re-capture | ✅ **СДАНО** (тесты + golden) |
|
||
| **WS1a** | eager-build клиентов в W0 + read-only `client()` (гонка `runner.go` закрыта) | ✅ **СДАНО** (`-race`) |
|
||
| **WS1b** | пер-модельный rate-guard (семафор конкуренции + пейсинг) | ✅ **СДАНО** (concurrency-тест) |
|
||
| **WS1c-инфра** | base/enriched `MemoryVersion`-split (механика пер-волнового снапшота, «переоплата ОДНА») | ✅ **СДАНО** (unit-тест) |
|
||
| **WS4-core** | банкнота: pure `splitBanknote`/`parseBanknote` (`⟦TM-BANK-v1⟧`, толерантный сплит, Han-в-src, finish-truncation) | ✅ **СДАНО** (7 инвариант-тестов; Go↔Python паритет к `banknote.py`, пин 95/65/0/0 воспроизведён рефересом) |
|
||
| **WS6** | mistral rate_limit конфиг (свап-арм за rate-guard); арм-механика (editor-model = конфиг → снапшот per-арм) уже в коде | ✅ **частично** (конфиг-тай; арм-пайплайн-конфиги — резидуал) |
|
||
| **WS1c-executor** | параллельный волновой ИСПОЛНИТЕЛЬ W1/W1.5/W2 + пер-волновой снапшот-wiring + golden-рерайт + resume-across-waves + kill-9 N-резерв | ⚠️ **РЕЗИДУАЛ** (дизайн ниже, §Резидуал) |
|
||
| **WS4-integration** | 12 точек интеграции банкноты (срез ДО classify, derived-checkpoint, snapshot-фолд, телеметрия) | ⚠️ **РЕЗИДУАЛ** (ядро+дизайн готовы) |
|
||
| **WS3** | Go-майнер V-A→V-C + алиас + консолидация + сид-дельта + `tmctl seed-lint` + `Source:mined` | ⚠️ **РЕЗИДУАЛ** (Source-split инфра готова; порт — резидуал) |
|
||
| **WS5** | DC-чекеры + omission-бэкстоп + данные пакета пары + `tmctl export --pairs` | ⚠️ **РЕЗИДУАЛ** (дизайн ниже) |
|
||
|
||
**Почему не весь объём:** волновой ИСПОЛНИТЕЛЬ (WS1c) — это ре-архитектура модели исполнения
|
||
(последовательный per-chunk-all-stages → W1 draft-∥ / W1.5-стоп / W2 edit-∥-over-units), которая
|
||
инвалидирует golden + ~10 последовательно-модельных тестов (runner_memory/export/status/cheapgates/
|
||
quality/escalation_budget/maxtokens_floor) и добавляет двух-фазный CLI-флоу. Довести это до зелёного
|
||
за сессию БЕЗ поломки суита нереалистично. Решение (мандат «честный резидуал > фейк-комплит, не
|
||
сдавать сломанное»): сдать **несущую БЕЗОПАСНУЮ инфраструктуру волн** (eager-clients, rate-guard,
|
||
base/enriched split, edit-units) как лендабельную и зелёную, а параллельный исполнитель —
|
||
резидуалом с точным дизайном (§Резидуал). Ни один сданный кусок не оставляет суит красным.
|
||
|
||
---
|
||
|
||
## 1. WS2 — чанкер-бюджет + edit-единица (план §2) — ✅ СДАНО
|
||
|
||
Per-буллет чек-лист (буллеты промта):
|
||
|
||
- ✅ **Бюджет draft-чанков в ВЫХОДНЫХ токенах** `est_out = 1.1978·cjk + 0.3852·other`, конфиг
|
||
`config.Segmentation` (per-pair, снапшот-folded через `segmentationSnap`). Классы символов —
|
||
**РЕАЛЬНЫЕ `unicode.RangeTable`** (`Han|Hiragana|Katakana|Hangul`, `tokenClassCounts` = те же, что
|
||
`EstimateTokens`), НЕ ord-диапазоны (§0.1 общность). Пин `target_out=1797 → 56 чанков` —
|
||
воспроизведён на пере-прогонном корпусе (см. §Верификация ниже).
|
||
- ✅ **Edit-единица = глава; дефолт `EditCeilingOut=3200`.** Реализовано как **greedy-группировка
|
||
ЦЕЛЫХ draft-чанков до потолка** (`assignEditUnits`). **ДЕВИАЦИЯ-с-обоснованием (эскалация-нота):**
|
||
план §2(б) описывает edit-единицы как paragraph-greedy-pack; я реализовал grouping-of-whole-chunks
|
||
потому что независимые нарезки (para-pack draft @1797 и para-pack units @3200) МОГУТ дать
|
||
straddle draft-чанка через границу единицы → сломанная реконструкция draft для W2. **Эмпирически
|
||
проверено на реальном 25-гл корпусе:** grouping-whole-chunks даёт ТЕ ЖЕ **37 единиц**, что
|
||
para-pack, при **0 straddle** (скрипт в scratchpad; вывод: `{draft:56, para_units:37,
|
||
grouped_units:37, straddle:0}`). Т.е. на этом корпусе оба определения СОВПАДАЮТ, а grouping —
|
||
робастный супермножество-инвариант (гарантирует чистую реконструкцию всегда). Пин 37 сохранён.
|
||
- ✅ **8000-арм НЕ открыт** — дефолт 3200; `edit_ceiling_out` остаётся config-tunable (потолок —
|
||
конфиг, арм гейтнут §11), валидация `EditCeilingOut ≥ DraftBudgetOut`.
|
||
- ✅ **`Chunk` аддитивно:** `EstOut float64`, `OversizedSentence bool`, `EditUnitID int`. Контракт
|
||
`Chapter/ChunkIdx/Text` цел (тесты `TestSplitChunks*` + fuzz lossless-tiling зелёные).
|
||
- ✅ **Мега-предложение** = passthrough + `OversizedSentence=true` (БЕЗ клауза-сплита). Пин
|
||
`TestSplitChunksOversizeSentenceIsOwnChunk`.
|
||
- ✅ **Снос мёртвых `STMDepth`/`OverlapTokens`** из `config.ContextAssembly` + `contextSnap` +
|
||
yaml-конфигов (carryover не строим). Структурная смена `contextSnap` → строка манифеста §8.
|
||
- ✅ **src→dst-формат `renderEditorConstraintBlock`** (`- 源термин → «dst»`), CONFIRMED-only ЦЕЛА,
|
||
дедуп по `(src,dst)` (омоним-widening). Обоснование — билингв-редактор + омонимичный dst (§2в
|
||
ревью-1 F4). **Выделенный `render-format-version`** снапшот-компонент (НЕ `memoryMatchVersion`).
|
||
Пины `TestRenderEditorConstraintBlock` + `TestRunnerMemoryInjectionAndPostcheck` обновлены.
|
||
- ✅ **Сайзинг max_tokens редактора** — НЕ трогал (F8: существующий `stagerun.go:87-90` сайзит от
|
||
черновика `prev`; новой формулы не вводил — как и предписано).
|
||
- ⚠️ **Инъекция W2-единицы (СВЕЖИЙ Select над enriched-банком)** — часть волнового ИСПОЛНИТЕЛЯ
|
||
(резидуал WS1c). Механика src→dst-блока и enriched-версии готова; вызов свежего Select по тексту
|
||
единицы делается в W2-проходе (резидуал). **Whole-chapter Select-бюджет (§2е открытый)** — решать
|
||
в исполнителе (резидуал-нота).
|
||
|
||
Снапшот-фолды WS2 (§8): `chunkerVersion` v4→v5, `segmentationSnap`, `render_format_version`, снос
|
||
`stm_depth`/`overlap_tokens`. Golden re-captured — masked-дифф ниже (только versions/new-fields/
|
||
editor-src2dst; НИ одной несвязанной content-правки; фикстура НЕ ре-чанкается — 20 чанк-строк до/после).
|
||
|
||
## 2. WS1 — волновой раннер (план §1)
|
||
|
||
- ✅ **WS1a: Eager-build ВСЕХ клиентов в W0** (`buildClients` над `reachableModels()` =
|
||
`Stages[].Model ∪ EscalateTo`), вызван в `TranslateBook` W0-прелюдии ДО любой горутины. `client()`
|
||
теперь **READ-ONLY** — громкий отказ на miss (закрывает гонку `runner.go:171-181` без лока;
|
||
трипваер на будущую 3-ю модель-ось). `BuildClient` не требует ключа → безопасно на key-less resume.
|
||
`-race` чист.
|
||
- ✅ **WS1b: Пер-модельный rate-guard** (`ratelimit.go`): семафор конкуренции `models.yaml
|
||
rate_limit.max_concurrency` + опц. пейсинг `min_interval_ms`. **Транспорт-ось, НЕ снапшот** (wire
|
||
не трогает). Построен в W0 (`buildRateGuards`), read-only в волнах; обёрнут вокруг ОДНОГО
|
||
`client.Complete` в `runAttempt` (ctx-aware acquire/release, reservation освобождается при
|
||
ctx-cancel). Пины: `TestRateGuardLimitsConcurrency` (семафор РЕАЛЬНО ограничивает — cap=2/20
|
||
воркеров, observed-max ≤ 2), nil/unlimited no-op, ctx-cancel без leak, pacing. **`waves.workers`
|
||
конфиг** — вводится с исполнителем (резидуал).
|
||
- ✅ **WS1c-инфра: base/enriched `MemoryVersion`-split.** `MemoryBank.BaseVersion()` = хеш approved
|
||
`Source∈{seed,ruby,auto}` (БЕЗ mined); `Version()` (enriched) = все approved вкл. `Source:mined`.
|
||
`computeMemoryVersionScoped(excludeMined)`; enriched-путь **байт-идентичен** прежнему
|
||
`computeMemoryVersion` (домен-сепаратор только в base) → текущий снапшот не двигается от split-а.
|
||
Пин `TestBaseEnrichedMemoryVersionSplit`: добавление mined-approved строки двигает ТОЛЬКО enriched,
|
||
base стабилен (= «переоплата ОДНА» механизм); base≠enriched (домен-разделены). **`Source:mined`**
|
||
как значение enum — аддитивно (колонка `source` — свободный TEXT, миграция store не нужна;
|
||
подтверждено чтением `migrate.go`).
|
||
- ⚠️ **WS1c-executor (РЕЗИДУАЛ):** пер-волновой снапшот-wiring (`snapshot_W1`/`snapshot_W2` upsert),
|
||
W0 sticky-precompute, W1/W2 параллельный dispatch, W1.5-стоп + mined-write-путь, wave-sequencing
|
||
инвариант (W2 не пере-рендерит draft), money-под-∥ kill-9 N-резерв, scheduler-aware окна. Дизайн —
|
||
§Резидуал.
|
||
|
||
## 3. WS4-core — банкнота-парсер (план §4б) — ✅ СДАНО
|
||
|
||
`internal/pipeline/banknote.go` — байт-верный порт `exp16/banknote.py`:
|
||
- `splitBanknote(output)` → срез блока `⟦TM-BANK-v1⟧` (clean = rstrip до сепаратора, block = strip("\n"));
|
||
- `parseBanknote(block, truncated)` → толерантный сплит `\t| {2,}|\s*\|\s*`, тип∈{name,place,title,term,
|
||
nickname}+дефолт term, src ДОЛЖЕН нести Han `[㐀-鿿]` (точный диапазон U+3400–U+9FFF), truncation-толерантность
|
||
на ПОСЛЕДНЕЙ строке (флаг `Truncated`, не parse_fail);
|
||
- `bankParserVersion="banknote-v1"` (для будущего `banknoteSnap{enabled,parser_version}`).
|
||
- Тесты (`banknote_test.go`): no-SEP→всё clean; срез блока (утечки нет); толерантный сплит tab/≥2проб/pipe;
|
||
non-Han src=bad; truncation True→флаг/False→parse_fail; пустой блок; SEP≠note-слово. **Все PASS.**
|
||
- **Паритет:** референс `ws4_banknote_verify.py` воспроизводит пин **95 строк / 65 distinct / 0 fail / 0
|
||
trunc** + truncation-поведение + инварианты — идентично моему Go-порту (сверено исполнением).
|
||
|
||
**WS4-integration (12 точек) — резидуал** (§Резидуал R3): требует правок `chunkrun.go`/`stagerun.go`/
|
||
`disposition.go`/`snapshot.go` (файлы под адверсариал-ревью этой сессии — не трогал во избежание дрейфа
|
||
цитат; ядро + точный дизайн готовы).
|
||
|
||
## 4–5. WS3 / WS5 — ⚠️ РЕЗИДУАЛ (дизайн в §Резидуал)
|
||
|
||
Не начаты в коде (кроме `Source:mined`-инфра из WS1c, которая — предусловие WS3-mined-write). Причина
|
||
— бюджет сессии ушёл в несущий каркас Block A + верификацию + WS4-ядро. Дизайны/пред-условия — §Резидуал.
|
||
|
||
---
|
||
|
||
## Багфиксы вне плана
|
||
Пока нет (изменения строго по плану). Правки по ревью — см. §Адверсариал-ревью ниже (2 doc-фикса + 1 gofmt).
|
||
|
||
## Структурные переносы
|
||
- Новый файл `internal/pipeline/ratelimit.go` (rate-guard) + `banknote.go` (WS4-ядро) — новые оси, не рефактор.
|
||
- `SegBudget` (resolved segmentation) живёт в `chunker.go`; резолвер `segBudget()` — в `runner.go`
|
||
(segmenter остаётся config-free). `renderFormatVersion` const — в `memory.go` рядом с рендерерами.
|
||
|
||
---
|
||
|
||
## Верификация (исполнением — логи, не слова)
|
||
|
||
```
|
||
$ go build ./... → OK
|
||
$ go vet ./... → OK (чисто)
|
||
$ go test -race ./... → ВСЁ ЗЕЛЁНОЕ:
|
||
ok cmd/tmctl 1.0s · config · ledger · llm · pipeline 19.4s · store
|
||
$ gofmt -l <мои файлы> → пусто (все чисты; репо несёт ПРЕ-существующий gofmt-долг в ~13
|
||
не-моих файлах под go1.26.4 — их не трогал)
|
||
```
|
||
|
||
**Фикстуры плана (исполнены рефересами `eval/design11/*` под `eval/.venv`):**
|
||
- WS2 фертильность/нарезка: `56 чанков @1797` / `37 edit-единиц @3200` / **`0 straddle`** —
|
||
подтверждено `ws2_straddle_check.py` (grouping-whole-chunks ≡ para-pack на корпусе).
|
||
- WS4 банкнота: `95 строк / 65 distinct / 0 fail / 0 trunc` (`ws4_banknote_verify.py`) — мой Go-парсер
|
||
воспроизводит контракт (7 инвариант-тестов PASS, идентичны демо `banknote.py`).
|
||
|
||
**Go-тесты, добавленные/обновлённые этой сессией (все PASS под `-race`):**
|
||
`TestSplitChunks*` (+ EstOut/OversizedSentence/EditUnitID пины + `TestSplitChunksEditUnitGroupsWholeChunks`),
|
||
`TestRateGuard*` (concurrency-cap реально ограничивает, ctx-cancel без leak, pacing, nil no-op),
|
||
`TestBaseEnrichedMemoryVersionSplit`, `TestRenderEditorConstraintBlock` (src→dst), `TestRunnerMemoryInjectionAndPostcheck`,
|
||
`TestSplitBanknote*`/`TestParseBanknote*`, `TestGoldenDeterminism` (re-captured).
|
||
|
||
## Адверсариал-ревью Block A (мандат: author≠reviewer, refute-by-default, 3 линзы) — ИСПОЛНЕН
|
||
9-агентный воркфлоу (3 ревью-линзы: алгоритм-vs-план / сеньор-код-ревью / функциональное, каждая
|
||
находка адверсариально верифицирована). **6 сырых находок → 3 подтверждено, 3 отвергнуто** (верификатор
|
||
refuted как not-a-bug/hypothetical):
|
||
- **CONFIRMED-1/2 (minor, doc):** комменты base/enriched говорили «equal until mined», но код
|
||
ДОМЕН-РАЗДЕЛЯЕТ их (base≠enriched всегда). Код/дизайн ВЕРНЫ; комменты — нет. **ПОФИКШЕНО**
|
||
(`memory.go:135`,`:179`).
|
||
- **CONFIRMED-3 (nit, style):** `subChunk` struct не gofmt-выровнен. **ПОФИКШЕНО** (`gofmt -w`).
|
||
- **REFUTED (верифицировано как не-баг):** (a) «edit-unit grouping диверджит от плана» → НЕ баг:
|
||
grouping-whole-chunks ТРЕБУЕТСЯ для W2-реконструкции, ≤3200 by construction, а т.к.
|
||
`chapterDraftChunks` НИКОГДА не режет абзац — каждая draft-граница = абзац-граница → удовлетворяет
|
||
И §2б И §1б (сильнее, чем я аргументировал); 37 — описательная статистика, не решающая ветка кода.
|
||
(b) rate-guard money-путь «нет интеграц-теста» → гипотетический будущий регресс, не дефект сданного
|
||
кода (release-on-cancel корректен). (c) job-status «running» до acquire → корректная семантика,
|
||
лог `calling model` маркирует queued-vs-wire. Диспозиции — в отчёте, тихих девиаций нет.
|
||
|
||
## Golden re-capture (WS2) — маскированный структурный дифф
|
||
18 изменённых masked-строк, ВСЕ объяснимы: `chunker_version` v4→v5; снятые `stm_depth`/`overlap_tokens`;
|
||
новое `segmentation:{1797,3200,1.1978,0.3852}`; новое `render_format_version:renderfmt-v1-editor-src2dst`;
|
||
редактор-блок `- «dst»` → `- src → «dst»` (7 editor-body строк). Фикстура НЕ ре-чанкается. Полный
|
||
masked-дифф — scratchpad `ws2_golden_masked_diff.txt`.
|
||
|
||
---
|
||
|
||
## РЕЗИДУАЛ — точные дизайны для следующей сессии
|
||
|
||
### R1. Волновой ИСПОЛНИТЕЛЬ (WS1c-executor) — несущий, самый крупный
|
||
Каркас готов (eager-clients, rate-guard, base/enriched split, edit-units на чанках). Осталось:
|
||
1. `snapshotIDForWave(wave)` — рефактор `snapshot.go`: fold ТОЛЬКО стадии волны (draft=translator-роль
|
||
→ W1; editor-роль → W2) + версию банка волны (`BaseVersion` для W1, `Version` для W2). Апсертить
|
||
ДВА снапшота.
|
||
2. Партиция стадий по роли; edit-единица addressable как `(chapter, firstChunkIdxOfUnit, "edit")` в
|
||
`chunk_status` (без миграции — units per-chapter, group-of-whole-chunks).
|
||
3. W0 sticky-precompute: реплицировать последовательную sticky-цепочку ($0, `Select` src-производна)
|
||
→ инъекц-байты draft ≡ последовательным (golden-пин).
|
||
4. W1 dispatch: N воркеров тянут draft-чанки, `runStage(draft)` под `snapshot_W1`. W2 dispatch: N
|
||
воркеров тянут edit-единицы, `prev` = конкатенация draft-выходов чанков единицы (из W1-чекпоинтов
|
||
по `final_hash`), СВЕЖИЙ `Select` по тексту ВСЕЙ единицы над enriched-банком, `runStage(edit)` под
|
||
`snapshot_W2`. **W2 НИКОГДА не пере-рендерит draft** (несущий инвариант §1в).
|
||
5. W1.5: при пустой mined-дельте (WS3 не построен) — авто-продолжение; иначе стоп + карта подписи +
|
||
mined-write-путь (штамп `Source:mined`, зеркало `rubyToCandidates`, НЕ через `loadGlossarySeed`).
|
||
6. Money-под-∥: воркеры-горутины через single-writer store (уже сериализует). kill-9 тест с N живыми
|
||
резервами (порт `store/kill9_test.go` на N). rate-guard уже интегрирован.
|
||
7. Golden-рерайт под волновую модель + обновление ~10 последовательно-модельных тестов.
|
||
|
||
### R2. WS3 майнер — референс `eval/exp16/{arms,alias,canon,patterns,spread,palladius,banknote}.py`
|
||
Новый пакет `internal/pipeline/miner*.go`. Порт V-A→V-C по ТОЧНЫМ порогам §3(б); дефолт-лемматизатор
|
||
**B** (дроп Палладий-подканала → `古月:21→22`, скрин PASS). Инвариантные гарантии (EXACT): 13618-канд-СЕТ,
|
||
recall 0.9649/0.9318, катастроф-скрин `方源/蛊/蛊师` ранги 0/1/2 ∈top-50. Реюз `memnorm.normalizeSourceKey`.
|
||
`tmctl seed-lint` (сухой прогон фейл-лаудов `loadGlossarySeed`). Go↔Python паритет (Python=референс).
|
||
`Source:mined`-инфра (base/enriched split) — **готова** (WS1c).
|
||
|
||
### R3. WS4 банкнота — референс `eval/exp16/banknote.py`, спека research/20 §B3
|
||
Pure `split_banknote`/`parse_banknote` (`⟦TM-BANK-v1⟧`, ≤12 строк src\tdst\ttype, толерантный сплит,
|
||
Han-в-src, finish=stop-only гейт). 12 точек: срез ДО `classifyOutput` (`chunkrun.go`); derived-checkpoint
|
||
`sha256("tm-banknote-v1\x00"+reqHash+"\x00"+stripped)` через `PutDerivedCheckpoint` (прецедент
|
||
`commitSanitizedExport` — **уже есть**); re-point `final_hash` OK-пути draft на derived ПОСЛЕ резолва
|
||
эскалации (`last.stripped`); `banknoteSnap{enabled,parser_version}` в `snapshotID()` (фолд при enabled,
|
||
зеркало `sanitizerSnap`); инструкция сноски В ФАЙЛ промпта; телеметрия `n_banknote_lines`/`parse_fail`/
|
||
`truncated`. Пин: пере-парс 95 строк = 0 fail (`ws4_banknote_verify.py`).
|
||
|
||
### R4. WS5 DC-чекеры + omission-бэкстоп + данные пакета пары + `tmctl export --pairs`
|
||
Расширить `cheapgates.go` DC1/2/6/7 (детерм. флаггеры, target-gated, наблюдаемость не гейт); DC3
|
||
gender-инъекция (male/female/hidden-мандат) из seed-поля `Gender` в `renderEditorConstraintBlock`
|
||
(фолд через `render-format-version` + `MemoryVersion`); omission-бэкстоп (substring по
|
||
`{dst,decl.forms,aliases}` + лёгкий Go-стеммер, БЕЗ pymorphy3); данные пакета zh-ru (версионируемый
|
||
снапшот-folded пакет); `tmctl export --pairs` (source-join уже в `Export`) — пред-условие §5(д)-FP.
|
||
DC5-детекцию НЕ строить (74%/42% FP); hidden-ЧЕКЕР НЕ строить (Ф2-кореф). Референс `ws5_checkers_verify.py`.
|
||
|
||
### R5. WS6 арм-конфиги
|
||
Арм-механика (editor-model = конфиг → `stageSnap.Model` → снапшот per-арм) **уже работает**. Осталось:
|
||
арм-пайплайн-конфиги (editor=mistral-large-2512 / deepseek-v4-pro, `few_shot:false` для reasoning),
|
||
атрибуция арма в export/report (editor-model уже в chunk_status), `echo_mine_test` под арм-варианты.
|
||
mistral rate_limit — **сдан** (WS1b/WS6 тай).
|
||
|
||
### Открытые эскалации владельцу/оркестратору
|
||
- edit-единица grouping-of-whole-chunks vs para-pack — СОВПАДАЮТ на этом корпусе (0 straddle);
|
||
выбран grouping для гарантии реконструкции. Требует подтверждения при лендинге.
|
||
- Реестр §10 (W1.5-UX, DeepSeek ×2 ре-чек 24.07, whole-chapter Select-бюджет) — открыты как в плане.
|