diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 4f37ed8a..5c3e1cd7 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -3,7 +3,7 @@ > **Единственный трекер проекта.** Здесь живут строки, на которые доки, промты и D-ноты ссылаются словами «строка N» / «строка бэклога N»: **ID строки стабилен навсегда**, не перенумеровывается и не переиспользуется (D39.80). Правки — только через оркестратора; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено. > ⚠ **Это НЕ бэклог зоны `docs/`, а бэклог ПРОЕКТА.** У зон свои, с другими неймспейсами ID, и единый их строк не принимает (D39.84): платформа — [../platform/BACKLOG.md](../platform/BACKLOG.md) (`П-N`) и её регистр дефектов `platform/docs/DEFECT_REGISTER.md` (`PD-N`); фронт — [../frontend/docs/BACKLOG.md](../frontend/docs/BACKLOG.md) (`Ф-N`). > ⚠ **Состояние проекта — не здесь.** Очередь, курс, CURRENT-STATE, состояние паков и живая хроника — шапка [PROGRESS.md](PROGRESS.md). Здесь только долг и его диспозиции. -> - **СЧЁТ ОЧЕРЕДИ на 11.09 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **307** строк · зона бэкенд **148** строго / **201** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **153** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строка эксп-22: 153 (плюс 150 — руки владельца; ⚠ 55 из гейтов СНЯТА — D39.198 п.5); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). +> - **СЧЁТ ОЧЕРЕДИ на 11.09 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **308** строк · зона бэкенд **148** строго / **201** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175; **371** — актом D39.233, **360** — актом D39.232, обе 10.09), платные прогоны разблокированы · «скоро» **153** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строка эксп-22: 153 (плюс 150 — руки владельца; ⚠ 55 из гейтов СНЯТА — D39.198 п.5); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). > - ⚠ **Переезд 06.09 (D39.218):** таблица вынесена из `PROGRESS.md` ДОСЛОВНО и ни один ID не сдвинут — **с единственным исключением: две ячейки (строки 220 и 306) тронуты РОВНО в номере якоря `docs/scripts/counts.py:566`→`:569` и `:592`→`:595`**, потому что цель сдвинул этот же коммит; текст ячеек не менялся, длины равны. В `PROGRESS.md` на прежнем месте оставлен заголовок-указатель, поэтому ссылки «секция „Бэклог“» доезжают в один хоп. ## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора) @@ -343,3 +343,4 @@ | 421 | **ЗАМЕР, РАДИ КОТОРОГО ШЕСТОЙ ВОПРОС СНЯТ С ВЛАДЕЛЬЦА: сколько банк-батчей на боевой книге двигает ТОЛЬКО окно.** Дизайн-пак завёл вопрос о проводе банк-ролей и САМ его снял с владельца доводом «цена меняла знак ТРИЖДЫ — 11 % всегда → ноль → интервал от нуля до всего прохода; число, трижды менявшее знак, владельцу отдавать нельзя». Постановка готова: считать на боевой книге долю батчей, у которых меняется только окно `since_ch`/`until_ch`, и тем закрыть интервал. ⚠ **Ряд заведён 11.09 по находке аудита: и дизайн, и акт `D39.245` объявляли замер «ушедшим в бэклог», а в бэклоге его НЕ БЫЛО** — классический случай «заведено» со слов, без грепа по живому трекеру | бэкенд/полигон | когда-нибудь | доля батчей, двигающих только окно, числом на боевой книге | дизайн-пак перекроя 11.09, заведён аудитом смены | | 422 | ⛔ **КОЛОНКА, КОТОРОЙ СПРАШИВАЮТ «СКОЛЬКО СЪЕЛО ДУМАНЬЕ», НЕ НЕСЛА ЧИСЛА НИ РАЗУ ЗА ВСЮ ИСТОРИЮ ПРОЕКТА.** Замер 11.09 оркестратором: `request_log.reasoning_tokens > 0` — **0 строк**; контроль рядом, доказывающий, что вопрос задан существующему предмету: ⚠ **контроль ИСПР. 11.09 — мой первый счёт был занижен: `glob` пропустил ~170 баз, пере-снято через `find`** — файлов `*.db` найдено **448**, несут таблицу `request_log` **405**, прочитано **58 886** строк; ноль устоял на БОЛЬШЕМ знаменателе. Колонка объявлена схемой (`backend/internal/store/migrate.go`, блок `CREATE TABLE request_log`) и присутствует во всех. ⇒ **единственная колонка, которой можно доказать «потолок съело рассуждение», структурно молчит**, и её ноль неотличим от «думанья не было». Прямо это и есть слепота в вопросе владельца «мы ждали 249 секунд и заплатили за ничего»: у DeepSeek рассуждение считается ВНУТРИ `completion_tokens` и отдельным полем не приходит, поэтому на провальных вызовах прогона A видно `completion_tokens` 8496 · 8496 · 8496 · 16000 при нуле знаков текста — то есть потолок выкуплен целиком, а чем — не сказано ничем. ⚠ Родня рядов **414** (признак отказа не в той колонке) и **415** (четверть денег за пустоту): все три — про то, что ОТКАЗ и его ПРИЧИНА не доезжают до прибора, которым смотрят деньги | бэкенд | **скоро** | поле, различающее «рассуждение съело потолок» и «рассуждения не было» — из тела ответа провайдера, а не из отсутствующего поля usage; либо явная пометка «провайдер не сообщает» | пере-замер оркестратора 11.09 по базе прогона A | | 423 | ⛔⛔ **МАЙНЕР ЭМИТИТ ТОЛЬКО ТО ПОЛЕ, РАДИ КОТОРОГО ПОСТРОЕН, И КАЖДЫЙ МЕХАНИЗМ НИЖЕ ПО ТЕЧЕНИЮ, КОТОРОМУ НУЖНЫ ДАННЫЕ БОГАЧЕ, ТИХО ДЕГРАДИРУЕТ. Три открытых ряда оказались ОДНИМ классом.** Замер оркестратора 11.09 (контроль: прибор распарсил **47** yaml-файлов с непустым `terms:`): ненулевые `decl.forms` есть ТОЛЬКО в файлах, написанных человеком — `guzhenren-seed-v2.yaml` 42 терма из 58 · `guzhenren-seed.yaml` 35 из 49 · `rerun2` 41 из 57; **во ВСЕХ машинных выгрузках — ноль**: 0 из 142 · 0 из 102 (шесть раз) · 0 из 83 · 0 из 76 · 0 из 74 · 0 из 69 (банк платного прогона A) · 0 из 67 · 0 из 61 · 0 из 53. ⇒ **на книге без рукописного сида — то есть на нормальной дорожке продукта — пост-проверке нечем опереться, кроме глобального одношагового стеммера**, и это ровно тот механизм, который ряд **419** замерил как дающий 11 ложных тревог из 18. Три инстанса одного класса: `decl.forms` (`internal/seed/seed.go:87`=`type Decl struct`, потребитель `membank/memory.go:343`=`Parse decl forms for the post-check`) · профили голоса (ряд **410**: `voices:` пуст во ВСЕХ 22 машинных выгрузках и отсутствует во ВСЕХ 22 рукописных сидах) · формы глагольных и многословных термов (ряд **408**). ⭐ **Ценность ряда в том, что он снимает три отдельные «доработки данных» и ставит один вопрос: что банк обязан отдавать, кроме пары «исходник → передача», чтобы механизмы ниже работали не вырожденно.** ⚠ Это НЕ заказ «научить майнер всему»: часть полей модель предложить не может в принципе (склонение — да, голос — спорно), и разделение «что майнится · что сеется человеком · что вычисляется из языка» и есть предмет. ⛔ Пока ряд открыт, любой замер точности пост-проверки на РУКОПИСНОМ корпусе меряет исключение, а не правило — этим 11.09 ошибся оркестратор, решая порядок колонок прибора консистентности | бэкенд | **скоро** | разделение «майнится · сеется · выводится из языка» + носитель того, чего майнер не даёт | пере-замер оркестратора 11.09 по числу зоны `textmachine-c9` | +| 424 | **ЧЕТЫРНАДЦАТЬ РЯДОВ ТРЕКЕРА РЕНДЕРЯТСЯ С ЛИШНИМИ КОЛОНКАМИ — неэкранированный `\|` внутри ячейки, обычно в код-спане вида `auto\|draft\|approved`.** Замер 11.09 структурной проверкой по всей таблице (контроль: рядов прочитано **298**, сломанных **14**): 163 · 182 · 248 · 127 · 253 · 279 · 306 · 311 · 320 · 346 · 361 · 378 · 389 · 407. Лечение — `\|` в ячейке; работа механическая. ⭐ **Ряд заведён не ради косметики, а потому что гейт этого НЕ ВИДЕЛ, и слепота стоила инцидента:** проверка формы в `docs/scripts/counts.py` ловила только «колонок МЕНЬШЕ ожидаемого», а «больше» и «текст за последним разделителем» молчали — и ряд **406** прожил от создания до 11.09 с **1044 знаками текста ВНЕ таблицы**, при этом счётчики сходились (они читают ячейки с конца и попадали в нужные) и гейт был зелён. Проверка сделана симметричной тем же днём, эти 14 внесены в `SHAPE_GRANDFATHERED` по конвенции файла «гейт рождается зелёным на известном долге и краснеет на следующем»; три посадки на копии подтвердили, что обе новые половины краснеют ПО ТЕКСТУ, а дедовщина молчит. ⇒ закрытие ряда = экранировать 14 ячеек и вынести их из списка | оркестратор | когда-нибудь | экранирование `\|` в четырнадцати ячейках и пустой `SHAPE_GRANDFATHERED` | структурная проверка оркестратора 11.09 | diff --git a/docs/scripts/counts.py b/docs/scripts/counts.py index 434f22b8..0fc5c2e6 100644 --- a/docs/scripts/counts.py +++ b/docs/scripts/counts.py @@ -169,13 +169,34 @@ def weight_of(line: str) -> str: return col(line, 4).lstrip("*⚠ ") +# Ряды, у которых лишние колонки — ЗНАЕМЫЙ долг: неэкранированный `|` внутри ячейки (обычно в +# код-спане вида `auto|draft|approved`). Та же конвенция, что у WEIGHT_GRANDFATHERED: гейт рождается +# зелёным на известном и краснеет на следующем. Долг числится строкой бэклога 424. +SHAPE_GRANDFATHERED = {"163", "182", "248", "127", "253", "279", "306", "311", + "320", "346", "361", "378", "389", "407"} + + def malformed(rows: list, shape: int, what: str) -> list: - """Строка таблицы неожиданной формы — расхождение, а не тихий IndexError.""" + """Строка таблицы неожиданной формы — расхождение, а не тихий IndexError. + + ⛔ Проверка СИММЕТРИЧНА, и вторая половина куплена инцидентом 11.09. Прежде ловилось только + «колонок меньше», а «больше» молчало — и ряд 406 прожил от создания до 11.09 с ХВОСТОМ ЗА + ПОСЛЕДНИМ РАЗДЕЛИТЕЛЕМ: 1044 знака текста стояли вне таблицы, счётчики при этом сходились + (они читают ячейки с конца и попадали в нужные), гейт был зелён, а ряд рендерился неверно. + Лишний разделитель и висящий хвост — разные болезни с одним симптомом, поэтому обе ниже. + """ bad = [] for l in rows: n = len(CELL_SPLIT.split(l)) + rid = cells(l)[1].strip() if n < shape: bad.append(f"{what}: строка «{cells(l)[1]}» имеет {n - 2} колонок, ожидалось {shape - 2}") + elif n > shape and rid not in SHAPE_GRANDFATHERED: + bad.append(f"{what}: строка «{cells(l)[1]}» имеет {n - 2} колонок, ожидалось {shape - 2} " + f"— неэкранированный `|` внутри ячейки (нужен `\\|`)") + if not l.rstrip().endswith("|"): + bad.append(f"{what}: строка «{cells(l)[1]}» — ТЕКСТ ЗА ПОСЛЕДНИМ РАЗДЕЛИТЕЛЕМ, " + f"он вне таблицы и счётчиками не виден") return bad