Report the delivery check red with a diagnosis per line, fix the checker that counted table headings as requirements, and record the gate I almost turned green by quoting it
This commit is contained in:
parent
056a8698a1
commit
f52466a811
2 changed files with 113 additions and 2 deletions
|
|
@ -5905,3 +5905,54 @@ n = 16 английских единиц = 7.89 главы Гу · k = 5 арм
|
||||||
|
|
||||||
⛔ **Денег на это в паке НЕТ.** Резерв $1.26 из $18.30, свободно в ФД-N $0.29. Пункт 1 в резерв не
|
⛔ **Денег на это в паке НЕТ.** Резерв $1.26 из $18.30, свободно в ФД-N $0.29. Пункт 1 в резерв не
|
||||||
влезает ⇒ **нужна НОВАЯ фаза и слово владельца ДО начала.** Потолки сессия не поднимает.
|
влезает ⇒ **нужна НОВАЯ фаза и слово владельца ДО начала.** Потолки сессия не поднимает.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Д39 — СВЕРКА С БУКВОЙ ЗАКАЗА ПЕРЕД СДАЧЕЙ. ТРИ КРАСНЫХ, И НИ ОДИН НЕ ПРО РАБОТУ
|
||||||
|
|
||||||
|
`eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --final` →
|
||||||
|
**требований 77 · ожидают 0 · провалов 3 · СВЕРКА НЕ ПРОЙДЕНА.** Разбираю каждый, потому что
|
||||||
|
«гейт красный» без диагноза — это ровно то состояние, из которого рождается тихая подгонка.
|
||||||
|
|
||||||
|
### Д39.1 ⛔ ДЕФЕКТ САМОГО ГЕЙТА: `--final` НЕ МОГ ПРОЙТИ НИКОГДА
|
||||||
|
|
||||||
|
Реестр делит требования на разделы строками вида `| **РАМКА** | | |` — у них ПУСТАЯ ячейка улики.
|
||||||
|
`conformance.py` считал их обычными требованиями, поэтому в режиме `--final` каждая давала
|
||||||
|
«улики нет, а пак сдаётся»: **двенадцать заголовков = двенадцать фантомных провалов**, и сверка
|
||||||
|
не могла пройти при любой сделанной работе. Заодно врал итог: «требований 89» при **77** настоящих.
|
||||||
|
|
||||||
|
**Починено в инструменте, НЕ в реестре** (`is_req` + `--selftest` с тремя гейтами, один из которых
|
||||||
|
специально проверяет, что настоящее требование без улики ОСТАЛОСЬ провалом). ⛔ **Правка не делает
|
||||||
|
зелёным ни одно реальное требование** — до неё провалов было 14, из них 12 фантомных; после —
|
||||||
|
ровно те же 3 настоящих. Числа до и после напечатаны здесь именно затем, чтобы это можно было
|
||||||
|
проверить, а не принять на слово.
|
||||||
|
|
||||||
|
### Д39.2 ⛔ ТРИ КРАСНЫХ — ДИАГНОЗ КАЖДОГО
|
||||||
|
|
||||||
|
| требование | почему красный | это работа или улика? |
|
||||||
|
|---|---|---|
|
||||||
|
| **R71** «правка рига чужого пака + пере-снятие его гейтов» | `verify22.py` выводит границу двойной оплаты как «расход Ф2 ДО коммита атомарного замка», отделяя «до» от «после» **временем файла**. Переезд машины обнулил mtime: 335 клеток Ф2 имеют ОДИН mtime, поздний ⇒ граница считается `$0.000000` | ⛔ **УЛИКА УТРАЧЕНА БЕЗВОЗВРАТНО.** Клетки времени покупки в себе не хранят (полей `ts` нет). Числа в отчёте эксп-22 верны — они сняты, когда mtime ещё существовали |
|
||||||
|
| **R77** «пинг в `docs/PROGRESS.md` секция „Полигон“» | улика ищет заголовок хроники за 15 августа со словами «ФАЗА Д»; вынесение хроники увезло его в `docs/archive/PROGRESS-2026-08-10-15.md:73`=`ФАЗА Д — сырьё снято` | ⛔ **ПРОТУХ ГЕЙТ, НЕ ОБЯЗАТЕЛЬСТВО.** Пинг написан этой сессией и стоит в секции «Полигон» |
|
||||||
|
| **R37** «материал ja непригоден → СТОП и пинг» | улика записана как `material_ja.py \| grep -q "СТОП\|OK "`. Разборщик реестра восстанавливает `\|` в `|` — и делает это ОБЕИМ чертам: и трубе оболочки, и **альтернации внутри grep**. В двойных кавычках у `grep` без `-E` вертикальная черта литеральна ⇒ ищется строка `СТОП|OK ` целиком, которой нет | ⛔ **ЛОЖНЫЙ КРАСНЫЙ ОТ НОТАЦИИ.** Сам замер зелёный: `material_ja.py` печатает `[OK ] срабатываний нет: 0 из 48 чанков`, EXIT=0. ⚠ У этой же строки в прошлом был ложный ЗЕЛЁНЫЙ по той же причине (комментарий в `rows()`) — нотация `\|` ломает улику в обе стороны |
|
||||||
|
|
||||||
|
### Д39.3 ⛔⛔ И ОДИН КРАСНЫЙ Я СЕБЕ ЧУТЬ НЕ ПОДАРИЛ САМ
|
||||||
|
|
||||||
|
Первая редакция пинга в `PROGRESS.md` **процитировала ту самую строку, которую ищет улика R77** —
|
||||||
|
и гейт позеленел от того, что я НАПИСАЛ ПРО ГЕЙТ, а не от того, что исполнил обязательство.
|
||||||
|
Поймано собственной сверкой `--final`, цитата из пинга убрана, R77 вернулся в красное.
|
||||||
|
|
||||||
|
⇒ **Это ровно тот класс, ради которого реестр и заведён** («улика вида греп собственного отчёта
|
||||||
|
доказывает, что НАПЕЧАТАНО, а не что СДЕЛАНО» — шапка `requirements.md`), и он сработал против
|
||||||
|
своего же автора. Записано сюда, потому что следующая сессия наступит на него легче, чем эта.
|
||||||
|
|
||||||
|
### Д39.4 ЧТО Я НЕ СТАЛ ДЕЛАТЬ И ПОЧЕМУ
|
||||||
|
|
||||||
|
**Реестр требований `eval/dovodka/requirements.md` НЕ ТРОНУТ ни на строку** — проверяемо
|
||||||
|
`git log --oneline -- eval/dovodka/requirements.md`. Две из трёх красных строк чинятся правкой
|
||||||
|
УЛИКИ (R77 — на живой заголовок, R37 — на `grep -qE`), и обе правки технически верны. Я их не
|
||||||
|
делаю: **править улики в момент сдачи — это и есть «дописать таблицу под результат»**, против чего
|
||||||
|
реестр стоит. Правильный порядок — приёмка видит красное, читает диагноз и решает; правит следующая
|
||||||
|
сессия ДО следующих покупок, а не эта после своих выводов.
|
||||||
|
|
||||||
|
⇒ **Сверка сдаётся КРАСНОЙ, с диагнозом на каждую строку.** Работа при этом закрыта; красные —
|
||||||
|
про инструменты провенанса, сломанные переездом и нотацией.
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -65,8 +66,25 @@ def frozen(src: Path) -> tuple[bool, str]:
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
|
|
||||||
|
REQ_ID = re.compile(r"^\*{0,2}(R\d+)\*{0,2}$")
|
||||||
|
|
||||||
|
|
||||||
|
def is_req(rid: str) -> bool:
|
||||||
|
"""Строка таблицы — ТРЕБОВАНИЕ, а не заголовок раздела?
|
||||||
|
|
||||||
|
⚠ ЗАЧЕМ ОТДЕЛЬНАЯ ФУНКЦИЯ, А НЕ УСЛОВИЕ НА МЕСТЕ. Реестр фазы Д делит требования на разделы
|
||||||
|
строками вида `| **РАМКА** | | |` — у них ПУСТАЯ ячейка улики. Прежняя редакция считала их
|
||||||
|
обычными требованиями, поэтому в режиме `--final` каждая давала «улики нет, а пак сдаётся»:
|
||||||
|
двенадцать заголовков = двенадцать фантомных провалов, и `--final` не мог пройти НИКОГДА,
|
||||||
|
как бы ни была сделана работа. Заодно врал итог: «требований 89» при 77 настоящих.
|
||||||
|
⛔ Правка НЕ делает зелёным НИ ОДНО реальное требование — она убирает из счёта строки, которые
|
||||||
|
требованиями не являются. Проверено гейтом ниже на заведомо больном входе.
|
||||||
|
"""
|
||||||
|
return bool(REQ_ID.match(rid.strip()))
|
||||||
|
|
||||||
|
|
||||||
def rows(md: str) -> list[tuple[str, str, str]]:
|
def rows(md: str) -> list[tuple[str, str, str]]:
|
||||||
"""Строки таблицы требований: (ID, требование, улика)."""
|
"""Строки таблицы: (ID, требование, улика). Заголовки разделов тоже здесь — фильтрует `is_req`."""
|
||||||
if MARK not in md:
|
if MARK not in md:
|
||||||
raise SystemExit(f"в документе нет маркера {MARK} — реестр требований не объявлен")
|
raise SystemExit(f"в документе нет маркера {MARK} — реестр требований не объявлен")
|
||||||
tail = md.split(MARK, 1)[1]
|
tail = md.split(MARK, 1)[1]
|
||||||
|
|
@ -125,6 +143,8 @@ def check(ev: str) -> tuple[str, str]:
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
args = [a for a in sys.argv[1:] if a]
|
args = [a for a in sys.argv[1:] if a]
|
||||||
|
if "--selftest" in args:
|
||||||
|
return selftest()
|
||||||
if not args:
|
if not args:
|
||||||
print(__doc__)
|
print(__doc__)
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -158,6 +178,9 @@ def main() -> int:
|
||||||
selfnames = {path.name, *(Path(a).name for a in args if a.endswith(".md"))}
|
selfnames = {path.name, *(Path(a).name for a in args if a.endswith(".md"))}
|
||||||
selfnames |= {f.name for f in (REPO / "docs" / "experiments").glob("2[23]-*.md")}
|
selfnames |= {f.name for f in (REPO / "docs" / "experiments").glob("2[23]-*.md")}
|
||||||
for rid, req, ev in rows(md):
|
for rid, req, ev in rows(md):
|
||||||
|
if not is_req(rid):
|
||||||
|
print(f"\n── {rid.strip('*')} " + "─" * max(0, 60 - len(rid)))
|
||||||
|
continue
|
||||||
st, detail = check(ev)
|
st, detail = check(ev)
|
||||||
if st == "ОЖИДАЕТ" and mode == "--final":
|
if st == "ОЖИДАЕТ" and mode == "--final":
|
||||||
st = "ПРОВАЛ"
|
st = "ПРОВАЛ"
|
||||||
|
|
@ -169,7 +192,7 @@ def main() -> int:
|
||||||
bad += st == "ПРОВАЛ"
|
bad += st == "ПРОВАЛ"
|
||||||
pend += st == "ОЖИДАЕТ"
|
pend += st == "ОЖИДАЕТ"
|
||||||
print(f"[{st:8s}] {rid:6s}{mark} {req[:70]}" + (f" ← {detail}" if detail else ""))
|
print(f"[{st:8s}] {rid:6s}{mark} {req[:70]}" + (f" ← {detail}" if detail else ""))
|
||||||
total = len(rows(md))
|
total = sum(1 for rid, _r, _e in rows(md) if is_req(rid))
|
||||||
print(f"\nтребований {total} · ожидают {pend} · провалов {bad}")
|
print(f"\nтребований {total} · ожидают {pend} · провалов {bad}")
|
||||||
print(f"улик вида «греп своего же документа» ({'сам-себя'}): {selfref} из {total}"
|
print(f"улик вида «греп своего же документа» ({'сам-себя'}): {selfref} из {total}"
|
||||||
+ (" ⚠ они доказывают, что НАПЕЧАТАНО, а не что СДЕЛАНО" if selfref else ""))
|
+ (" ⚠ они доказывают, что НАПЕЧАТАНО, а не что СДЕЛАНО" if selfref else ""))
|
||||||
|
|
@ -178,5 +201,42 @@ def main() -> int:
|
||||||
return 1 if bad else 0
|
return 1 if bad else 0
|
||||||
|
|
||||||
|
|
||||||
|
def selftest() -> int:
|
||||||
|
"""ГЕЙТ ПРАВКИ «заголовок раздела — не требование». Роняется на заведомо больном входе.
|
||||||
|
|
||||||
|
⚠ Норма фазы: гейт, который не может упасть, ничего не сторожит. Поэтому здесь три проверки, и
|
||||||
|
каждая ловит СВОЙ способ сломать правку: (1) заголовок не должен считаться требованием;
|
||||||
|
(2) настоящее требование БЕЗ улики обязано остаться провалом в `--final` — иначе правка
|
||||||
|
превратилась бы в подгонку под зелень; (3) счёт требований не должен включать заголовки.
|
||||||
|
"""
|
||||||
|
bad = 0
|
||||||
|
|
||||||
|
def ck(ok: bool, what: str) -> None:
|
||||||
|
nonlocal bad
|
||||||
|
print(f"[{'OK ' if ok else 'ПРОВАЛ'}] {what}")
|
||||||
|
bad += 0 if ok else 1
|
||||||
|
|
||||||
|
fake = (MARK + "\n"
|
||||||
|
"| ID | требование | улика |\n"
|
||||||
|
"|---|---|---|\n"
|
||||||
|
"| **РАМКА** | | |\n"
|
||||||
|
"| R1 | требование с уликой | `$ true` |\n"
|
||||||
|
"| R2 | требование БЕЗ улики | — |\n"
|
||||||
|
"| **НОРМЫ** | | |\n")
|
||||||
|
rs = rows(fake)
|
||||||
|
ids = [r[0] for r in rs]
|
||||||
|
ck(len(rs) == 4, f"разобрано строк таблицы: {len(rs)} (ждём 4, вместе с заголовками)")
|
||||||
|
ck([r for r in ids if is_req(r)] == ["R1", "R2"],
|
||||||
|
f"требованиями считаются только R-строки: {[r for r in ids if is_req(r)]}")
|
||||||
|
ck(not is_req("**РАМКА**") and not is_req("**НОРМЫ РИГА**"),
|
||||||
|
"заголовок раздела требованием НЕ считается")
|
||||||
|
ck(is_req("R77") and is_req("**R64**"), "R-строка считается требованием и в жирном начертании")
|
||||||
|
ck(check("—")[0] == "ОЖИДАЕТ", "требование без улики — ОЖИДАЕТ (в --final станет ПРОВАЛом)")
|
||||||
|
ck(check("`$ false`")[0] == "ПРОВАЛ", "падающая улика — ПРОВАЛ")
|
||||||
|
ck(check("`$ true`")[0] == "OK", "проходящая улика — OK")
|
||||||
|
print("\nГЕЙТ СВЕРКИ ГОДЕН" if not bad else f"\n⛔ ПРОВАЛОВ {bad}")
|
||||||
|
return 1 if bad else 0
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue