From 067206396e509bc00c38a4edd3f2a84f26b16cae Mon Sep 17 00:00:00 2001 From: heaven Date: Sat, 8 Aug 2026 02:42:26 +0300 Subject: [PATCH] Fix the counter that read table columns from the left and mis-parsed a row containing pipes, correcting a live wrong zone count in the header --- docs/PROGRESS.md | 2 +- docs/scripts/counts.py | 65 +++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index f6be9376..99c23993 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -6,7 +6,7 @@ > - **Курс:** ОБЩНОСТЬ ✅ → КАЧЕСТВО БАНКА ✅ → ПАКЕТ-ЧЕКЕРОВ ✅ (D39.59–78) → **ФРОНТ-ЭРА открыта** (D39.81–100: зоны `frontend/`+`platform/` живые, контракт API ратифицирован). Развилка блокера 0731 решена вариантом (б) и ИСПОЛНЕНА (D39.87/91: `reasoning_effort:"low"` черновику + ручка эффорта бэнк-ролям, код `553f1a3`); отладочный прогон C не стартовал ⇒ **строка 16 жива и оси голоса 13б без данных**; пак экрана 46 — дизайн заморожен (D39.92 п.1 + D39.93), промт ждёт выдачи; coldrun-b фаза C заморожена чекпойнтом — легитимный исход (D39.86); эталон денег/поведения — coldrun-a (read-only). Числа и хроника закрытых паков — D-лог D39.79–97, сюда НЕ дублируются. > - **Горизонт (D39.62/67, освежён D39.95):** ре-проба flash ИСПОЛНЕНА и строка 74 закрыта (D39.86/91; порог 6/6 → пере-ратификация выборочным, строка 116; проба Q2 ИСПОЛНЕНА — research/24, D39.102: семейства не окупаются, остаток = рецензент спорных кластеров при ре-пробе 74; эмиссия Q7 — по слову) → **ДОБОР ИДЕАЛА** (первым прогоном: оси голоса 24 · авто-режим · итерация №2 редакторов 65 · цена 16 · веса K1–K12 13а · вне-претрейн чекпоинт 55) → ВТОРАЯ ПАРА живьём (ja→ru; преп 81) → МАСШТАБ → пилот Ф2.5 (гейт резюме-строки 80; строки 62–68, 85) → Ф3 ридер-IDE (69–71). **Стоячие:** ToS-триггер 25.10 · Ш-2 до go1.27 (⚠ + x/text-таблицы Unicode 17 тем же тулчейном — строка 119/реестр 108) · проба провода исполнена и 117 закрыта (D39.97), конфиги 112 залендены — платные прогоны разблокированы. > - **Стек:** draft deepseek-v4-flash thinking-ON (банкнота: ⚠ канал в shipping-c1 НЕ включён — жив ран-локальным конфигом книги, строка 140) **⚠0731** → терминолог (та же модель, батчи, экран `target_script`) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (⚠ exp20/D39.108: второй проход на dspro отрицателен по слепому суду — судьба роли = эксп-21; ⚠ вендор АНОНСИРОВАЛ смену маппинга эффорта pro «early August 2026» — вахта в реестре 108; glm-5 резерв) → судья gemini (Ф2, полигон); канал B Mistral+grok; ~$0.85/ранобэ (D30.4) — 112 залендена (D39.97), пере-калибровка цены при следующем платном прогоне. -> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 07.08 (D39.110, скриптом по таблице; обновлять при каждом лендинге):** всего **120** строк · зона бэкенд **62** строго (ячейка ровно «бэкенд») / **79** широко (ячейка содержит «бэкенд») · **блокеров очереди 0**, платные прогоны разблокированы · «скоро» **32** (2·4·18·46·49·55·99·100·101·103·108·109·113·114·116·118·119·120·121·125·**126**·128·129·130·134·**135·136·138·139·140·143·145**) · гейт-строки эксп-21: 65·106·142; строка 5 — остаток гейчен ре-пробой 74 (D39.102 п.2); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов `repair.go:384` в 104 и честность `quality.go:436` в 105). Лента ✅ выше — про ЗАКРЫТЫЕ паки, читать её как «долга нет» неверно (разбор — вопрос владельца 02.08, D39.89). +> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 07.08 (D39.110, скриптом по таблице; обновлять при каждом лендинге):** всего **120** строк · зона бэкенд **63** строго (ячейка ровно «бэкенд») / **80** широко ⚠ (испр. 08.08: было 62/79 — мой счётчик читал колонки СЛЕВА и на строке 127 с `seed|ruby|auto` внутри ячейки принимал за зону слово «ruby»; теперь колонки читаются с конца, а битая форма строки — расхождение, а не тишина) (ячейка содержит «бэкенд») · **блокеров очереди 0**, платные прогоны разблокированы · «скоро» **32** (2·4·18·46·49·55·99·100·101·103·108·109·113·114·116·118·119·120·121·125·**126**·128·129·130·134·**135·136·138·139·140·143·145**) · гейт-строки эксп-21: 65·106·142; строка 5 — остаток гейчен ре-пробой 74 (D39.102 п.2); остальное «когда-нибудь». ⚠ **Счёт — НИЖНЯЯ граница долга, а не потолок:** трекер содержит только замеченное, и 02.08 дважды за $0 свежие глаза вытащили из кода дефекты, которых в нём не было (релей фронта → строки 99/100/102; приёмочное ревью → третий шов `repair.go:384` в 104 и честность `quality.go:436` в 105). Лента ✅ выше — про ЗАКРЫТЫЕ паки, читать её как «долга нет» неверно (разбор — вопрос владельца 02.08, D39.89). > - Архивы хроники: `archive/PROGRESS-2026-07-04-10.md` (D31) · `-10-13` (D39.6-гигиена) · `-13-25` (стройка паков 11–16, rerun2) · **`-25-31` (паки 17–20 · мини-прогон · полигон-пакеты 5–8 · ToS · холодный прогон; D39.26–58)** · **`-08-01-02` (сессии №9/№10: общность · качество банка · coldrun-b · открытие фронта/платформы; D39.59–90, срез D39.105)**. Записи ниже — живой хвост (№11+, эра D39.91+). ## Бэклог (ЕДИНЫЙ, собран 26.07, актуализация 04.08 D39.99/D39.101; правки — только через оркестратора) diff --git a/docs/scripts/counts.py b/docs/scripts/counts.py index d570946e..307cccbf 100644 --- a/docs/scripts/counts.py +++ b/docs/scripts/counts.py @@ -36,7 +36,7 @@ REGISTER = "platform/docs/DEFECT_REGISTER.md" BACKLOG_ROW = re.compile(r"^\| (\d+[а-яё]?) \|") REGISTER_ROW = re.compile(r"^\| (PD-\d+) \|") -NOTE = re.compile(r"^## (D39\.\d+)") +NOTE = re.compile(r"^## (D(\d+)\.(\d+))") # эра не прибита к 39 FROM_INDEX = "--from-index" in sys.argv @@ -61,16 +61,41 @@ def cells(line: str) -> list[str]: return [c.strip() for c in line.split("|")] +# ⚠ Колонки читаются С КОНЦА, а не с начала. Первая содержательная ячейка («Хвост»/«Суть») законно +# содержит `|` внутри кода — например строка бэклога 127 несёт «seed|ruby|auto», и разбор слева +# отдавал в качестве зоны слово «ruby». Из-за этого счёт зоны в CURRENT-STATE был 62/79 при истине +# 63/80 (нашла панель ревью 08.08). Хвостовые колонки короткие и `|` в них не бывает. +BACKLOG_SHAPE = 8 # '' | ID | хвост | зона | вес | чем закрывается | источник | '' +REGISTER_SHAPE = 9 # '' | ID | класс | серьёзность | где | суть | статус | источник | '' + + +def col(line: str, from_end: int) -> str: + """Ячейка, считая с конца: 2 = последняя содержательная, 3 = предпоследняя и так далее.""" + c = line.split("|") + return c[-from_end].strip() + + +def malformed(rows: list, shape: int, what: str) -> list: + """Строка таблицы неожиданной формы — расхождение, а не тихий IndexError.""" + bad = [] + for l in rows: + n = len(l.split("|")) + if n < shape: + bad.append(f"{what}: строка «{l.split('|')[1].strip()}» имеет {n - 2} колонок, ожидалось {shape - 2}") + return bad + + def backlog(text: str) -> dict: rows = [l for l in text.splitlines() if BACKLOG_ROW.match(l)] ids = [BACKLOG_ROW.match(l).group(1) for l in rows] return { "всего": len(rows), - "бэкенд строго": sum(1 for l in rows if cells(l)[3] == "бэкенд"), - "бэкенд широко": sum(1 for l in rows if "бэкенд" in cells(l)[3]), - "скоро": sum(1 for l in rows if "скоро" in cells(l)[4]), - "блокеров очереди": sum(1 for l in rows if "блокер-очереди" in cells(l)[4]), + "бэкенд строго": sum(1 for l in rows if col(l, 5) == "бэкенд"), + "бэкенд широко": sum(1 for l in rows if "бэкенд" in col(l, 5)), + "скоро": sum(1 for l in rows if "скоро" in col(l, 4)), + "блокеров очереди": sum(1 for l in rows if "блокер-очереди" in col(l, 4)), "дубли ID": [i for i, n in Counter(ids).items() if n > 1], + "битая форма": malformed(rows, BACKLOG_SHAPE, "бэклог"), } @@ -78,11 +103,10 @@ def register(text: str) -> dict: rows = [l for l in text.splitlines() if REGISTER_ROW.match(l)] weight, status, open_ids = Counter(), Counter(), [] for l in rows: - c = cells(l) - st, sev = c[6], c[3].replace("*", "") + st, sev = col(l, 3), col(l, 6).replace("*", "") if st == "open": status["open"] += 1 - open_ids.append(c[1]) + open_ids.append(cells(l)[1]) weight["major" if "major" in sev else "minor" if "minor" in sev else "info" if "info" in sev else sev] += 1 elif st.startswith("fixed"): status["fixed"] += 1 @@ -95,25 +119,33 @@ def register(text: str) -> dict: "по статусу": dict(status), "вес открытых": dict(weight), "открытые": open_ids, + "битая форма": malformed(rows, REGISTER_SHAPE, "регистр"), } def head(dlog: str, prog: str) -> dict: - notes = [NOTE.match(l).group(1) for l in dlog.splitlines() if NOTE.match(l)] - banner = re.search(r"D1–(D39\.\d+)", dlog.splitlines()[0]) if dlog else None + found = [(int(m.group(2)), int(m.group(3)), m.group(1)) + for l in dlog.splitlines() if (m := NOTE.match(l))] + notes = [f[2] for f in found] + # Максимум по НОМЕРУ: в файле уже есть внеочередные аппенды (## D39.17 → D39.19 → D39.18), и + # «последняя по порядку» однажды перестанет быть головой (нашла панель ревью 08.08). + top = max(found)[2] if found else None + banner = re.search(r"D1–(D\d+\.\d+)", dlog.splitlines()[0]) if dlog else None claimed = None for l in prog.splitlines()[:8]: - m = re.search(r"голова (D39\.\d+)", l) + m = re.search(r"голова (D\d+\.\d+)", l) if m: claimed = m.group(1) break last = notes[-1] if notes else None b = banner.group(1) if banner else None return { - "последняя нота D-лога": last, + "максимум по номеру": top, + "последняя по порядку файла": last, + "порядок = номер": last == top, "шапка D-лога": b, "голова в CURRENT-STATE": claimed, - "сходится": bool(last) and last == claimed == b, + "сходится": bool(top) and top == claimed == b, } @@ -170,6 +202,13 @@ def main() -> int: ) if b["дубли ID"]: bad.append(f"дубли ID строк бэклога: {b['дубли ID']}") + bad.extend(b["битая форма"]) + bad.extend(r["битая форма"]) + if not h["порядок = номер"]: + bad.append( + f"внеочередной аппенд в D-логе: последняя по порядку {h['последняя по порядку файла']}, " + f"максимум по номеру {h['максимум по номеру']} — голова считается по максимуму" + ) texts = {PROGRESS: prog, REGISTER: reg} for path, reg_name, pattern, (kind, key) in LITERALS: