diff --git a/.flangrc b/.flangrc index c09a34f97..1bfeb59e8 100644 --- a/.flangrc +++ b/.flangrc @@ -91,6 +91,13 @@ script.proofs:summary = bootstrap/flang run-script seed:freshness --what proofs: script.word:check = bootstrap/flang run-script seed:freshness --what word:check >&2 && bootstrap/flang io flang/scripts/word-guard.fscript --plan 'Сторож слов' --max-steps 2000000000 --на-веру script.word:forgery = bootstrap/flang run-script seed:freshness --what word:forgery >&2 && bootstrap/flang io flang/scripts/word-guard.fscript --plan 'Подлог слов' --max-steps 2000000000 --на-веру script.guard-calls:check = bootstrap/flang io scripts/guards/who-calls-the-guards.fscript --plan Check +script.proved-share-tree:check = bootstrap/flang io scripts/guards/proved-share-vs-tree.fscript --plan Check +script.proved-share-tree:numbers = bootstrap/flang io scripts/guards/proved-share-vs-tree.fscript --plan Numbers +script.proved-share-tree:forgery = bootstrap/flang io scripts/guards/proved-share-vs-tree.fscript --plan Forgery +script.forgery-probe:check = bootstrap/flang io scripts/guards/guards-without-forgery-probe.fscript --plan Check +script.forgery-probe:census = bootstrap/flang io scripts/guards/guards-without-forgery-probe.fscript --plan Census +script.forgery-probe:list = bootstrap/flang io scripts/guards/guards-without-forgery-probe.fscript --plan List +script.forgery-probe:forgery = bootstrap/flang io scripts/guards/guards-without-forgery-probe.fscript --plan Forgery script.uncalled-checks:check = bootstrap/flang io scripts/guards/checks-nobody-calls.fscript --plan Проверка --max-steps 4000000000 script.closed-length:check = bootstrap/flang io flang/scripts/closed-length-guard.fscript --max-steps 4000000000 script.emptiness:check = bootstrap/flang run-script seed:freshness --what emptiness:check >&2 && bootstrap/flang io flang/scripts/emptiness-guard.fscript --plan 'Пустоты в доказанном нет' --timeout 900000 --max-steps 2000000000 diff --git a/.githooks/pre-push.fscript b/.githooks/pre-push.fscript index d3fb066e7..94ddba505 100644 --- a/.githooks/pre-push.fscript +++ b/.githooks/pre-push.fscript @@ -22,8 +22,8 @@ запись «Check» с «name» равным "seed-refresh" и «command» равным "bootstrap/flang io scripts/seed/seed-refresh.fscript --plan Check", запись «Check» с «name» равным "version-derivations-guard" и «command» равным "bootstrap/flang io scripts/guards/version-derivations-guard.fscript --plan Проверка", запись «Check» с «name» равным "who-calls-the-guards" и «command» равным "bootstrap/flang io scripts/guards/who-calls-the-guards.fscript --plan Check", - запись «Check» с «name» равным "guards-without-forgery-probe" и «command» равным "sh scripts/guards/guards-without-forgery-probe.sh --check", - запись «Check» с «name» равным "proved-share-vs-tree" и «command» равным "sh scripts/guards/proved-share-vs-tree.sh", + запись «Check» с «name» равным "forgery-probe" и «command» равным "bootstrap/flang run-script forgery-probe:check", + запись «Check» с «name» равным "share-tree" и «command» равным "bootstrap/flang run-script proved-share-tree:check", запись «Check» с «name» равным "stdlib-proof-guard" и «command» равным "bootstrap/flang io scripts/guards/stdlib-proof-guard.fscript --plan Brackets", запись «Check» с «name» равным "cyrillic-file-names-guard" и «command» равным "bootstrap/flang io scripts/guards/cyrillic-file-names-guard.fscript --plan Проверка", запись «Check» с «name» равным "translit-file-names-guard" и «command» равным "bootstrap/flang io scripts/guards/translit-file-names-guard.fscript --plan Проверка", diff --git a/.github/workflows/binary.yml b/.github/workflows/binary.yml index 2fcb7efe9..6b7561b41 100644 --- a/.github/workflows/binary.yml +++ b/.github/workflows/binary.yml @@ -394,9 +394,9 @@ jobs: # # Счётчиков долга в дереве было три — раздел «Вне языка» в docs/ROADMAP.md, # docs/javascript-inventory.md и числа сайта, — и все три считали ОДИН - # язык: JavaScript. Оболочка (49 файлов, 9344 строк), HTML, CSS, пробы на - # СНЯТО 2026-10-04 файлов *.sh = 49 (перенос flang/translation/run.sh на план flang/translation/run.fscript снял один файл оболочки; до него 50, снято 2026-10-04) (задачи 0049 и 5821: сняты flang/scripts/word-occupancy.mjs, scripts/seed/seed-freshness.sh и scripts/guards/version-derivations-guard.sh — у каждого двойник на flang доказан прогоном; до них 52, снято 2026-10-04) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 101, снято 2026-09-17) - # СНЯТО 2026-10-04 строк-в *.sh = 9344 (перенос flang/translation/run.sh на план flang/translation/run.fscript снял 214 строк оболочки; до него 9558, снято 2026-10-04) (задачи 0049 и 5821: сняты flang/scripts/word-occupancy.mjs, scripts/seed/seed-freshness.sh и scripts/guards/version-derivations-guard.sh — у каждого двойник на flang доказан прогоном; до них 9756, снято 2026-10-04) (задачи 1426 и 8567: поиск коммита отпечатка по содержимому прибавил 135 строк в scripts/bootstrap-reprint.sh, а отменённая хронология предела шагов убрала 141; до них 9762, снято 2026-09-17) (задача 1400: девять проб на подлог и две честные под правила Н6 и О9 прибавили 42 строки в flang/proof/checker/tests/run.sh) (задача 1416: четырнадцать объявлений ярлыков заведены в скриптах и зов «Сбора» — в хуке; до них 23372, снято 2026-09-17) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 23980, снято 2026-09-22) (ADR-0046: довод в шапках двух сторожей имён — сперва почему flang/proof не судится, потом почему вошёл в область — прибавил 9 строк; до него 23971, снято 2026-09-17) + # язык: JavaScript. Оболочка (47 файлов, 8930 строк), HTML, CSS, пробы на + # СНЯТО 2026-10-04 файлов *.sh = 47 (перенос scripts/guards/proved-share-vs-tree.sh и guards-without-forgery-probe.sh на планы снял два файла оболочки; до них 49, снято 2026-10-04) (перенос flang/translation/run.sh на план flang/translation/run.fscript снял один файл оболочки; до него 50, снято 2026-10-04) (задачи 0049 и 5821: сняты flang/scripts/word-occupancy.mjs, scripts/seed/seed-freshness.sh и scripts/guards/version-derivations-guard.sh — у каждого двойник на flang доказан прогоном; до них 52, снято 2026-10-04) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 101, снято 2026-09-17) + # СНЯТО 2026-10-04 строк-в *.sh = 8930 (перенос scripts/guards/proved-share-vs-tree.sh и guards-without-forgery-probe.sh на планы снял 414 строк оболочки; до них 9344, снято 2026-10-04) (перенос flang/translation/run.sh на план flang/translation/run.fscript снял 214 строк оболочки; до него 9558, снято 2026-10-04) (задачи 0049 и 5821: сняты flang/scripts/word-occupancy.mjs, scripts/seed/seed-freshness.sh и scripts/guards/version-derivations-guard.sh — у каждого двойник на flang доказан прогоном; до них 9756, снято 2026-10-04) (задачи 1426 и 8567: поиск коммита отпечатка по содержимому прибавил 135 строк в scripts/bootstrap-reprint.sh, а отменённая хронология предела шагов убрала 141; до них 9762, снято 2026-09-17) (задача 1400: девять проб на подлог и две честные под правила Н6 и О9 прибавили 42 строки в flang/proof/checker/tests/run.sh) (задача 1416: четырнадцать объявлений ярлыков заведены в скриптах и зов «Сбора» — в хуке; до них 23372, снято 2026-09-17) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 23980, снято 2026-09-22) (ADR-0046: довод в шапках двух сторожей имён — сперва почему flang/proof не судится, потом почему вошёл в область — прибавил 9 строк; до него 23971, снято 2026-09-17) # C, Python, awk и Erlang не считались нигде и ни в одной проверке. Долг, # которого никто не считает, не убывает: его не видно ни в отчёте, ни в # ленте, и растёт он молча. @@ -407,9 +407,9 @@ jobs: # оболочке или на Python останавливает работу в тот же день. # # Замер на этом дереве: 17,7 с и 471 МБ, двоичному хватает `git` и `wc`. - # Предел шагов поднят с умолчания (10 млн): опись обходит 192 файлов и + # Предел шагов поднят с умолчания (10 млн): опись обходит 190 файлов и # семнадцать языков, и в умолчание не укладывается. - # СНЯТО 2026-10-04 файлов *.sh,*.c,*.h,*.py,*.html,*.css,*.awk,*.erl,*.js,*.mjs,*.java,*.cs,*.ex,*.exs,*.go,*.rs,*.lua,*.vim,*.rb,*.cpp,*.cc,*.hpp,*.hh,ярлык,packaging/asdf/bin/download,packaging/asdf/bin/install,packaging/asdf/bin/list-all,.githooks/pre-push = 192 (перенос flang/translation/run.sh на план flang/translation/run.fscript снял один файл вне flang; до него 193, снято 2026-10-04) (задачи 0049 и 5821: сняты flang/scripts/word-occupancy.mjs, scripts/seed/seed-freshness.sh и scripts/guards/version-derivations-guard.sh — у каждого двойник на flang доказан прогоном; до них 196, снято 2026-10-04) (две честные пары сличителя перевода: отбор по признаку и объявленная мера; до них 194, снято 2026-09-17) (задача 5821: семь проверок scripts/** стали планами; до них 251, снято 2026-09-27) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 256, снято 2026-09-17) + # СНЯТО 2026-10-04 файлов *.sh,*.c,*.h,*.py,*.html,*.css,*.awk,*.erl,*.js,*.mjs,*.java,*.cs,*.ex,*.exs,*.go,*.rs,*.lua,*.vim,*.rb,*.cpp,*.cc,*.hpp,*.hh,ярлык,packaging/asdf/bin/download,packaging/asdf/bin/install,packaging/asdf/bin/list-all,.githooks/pre-push = 190 (перенос scripts/guards/proved-share-vs-tree.sh и guards-without-forgery-probe.sh на планы снял два файла вне flang; до них 192, снято 2026-10-04) (перенос flang/translation/run.sh на план flang/translation/run.fscript снял один файл вне flang; до него 193, снято 2026-10-04) (задачи 0049 и 5821: сняты flang/scripts/word-occupancy.mjs, scripts/seed/seed-freshness.sh и scripts/guards/version-derivations-guard.sh — у каждого двойник на flang доказан прогоном; до них 196, снято 2026-10-04) (две честные пары сличителя перевода: отбор по признаку и объявленная мера; до них 194, снято 2026-09-17) (задача 5821: семь проверок scripts/** стали планами; до них 251, снято 2026-09-27) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 256, снято 2026-09-17) # # СКОЛЬКО ИЗ ЭТИХ ПЯТИДЕСЯТИ МИЛЛИОНОВ УХОДИТ, замер 29 августа 2026. # Меряно перебором самого предела: при 10 500 000 опись умирает @@ -504,52 +504,38 @@ jobs: # ── ОПИСЬ ДОКАЗАННОГО СВЕРЯЕТСЯ С ДЕРЕВОМ НА КАЖДОМ ПУШЕ ──────────────── # - # `scripts/guards/proved-share-vs-tree.sh` сверяет знаменатель + # `scripts/guards/proved-share-vs-tree.fscript` сверяет знаменатель # `scripts/ledgers/proved-share-ledger.txt` со счётом по исходнику: у # каждого .flang с обязательствами есть строка, у каждой строки — файл, и # «написано» сходится со счётом. До 15 сентября 2026 его звал только хук # перед пушем, CI — никто: запрос слияния с новым файлом доказательств # проходил зелёным, а хук краснел у следующего, кто пушил поверх main. - # Двоичный сверке не нужен — ей хватает git, grep, md5sum и awk; 12 с на - # машине разработки. FLANG_TMP задан потому, что умолчание /srv/tmp на - # раннере не создать. + # 4 октября 2026 сверка перенесена с оболочки на план: двоичный к этому + # шагу уже собран (шаги выше зовут ./bootstrap/flang), а прежний довод + # «её зовёт хук до сборки двоичного» устарел с задачи 1219 — хук сам стал + # планом. Считает по-прежнему git, grep и md5sum, 11 с на машине + # разработки; FLANG_TMP больше не нужен — времянок план не заводит. - name: Check proved share - env: - FLANG_TMP: ${{ runner.temp }} - run: sh scripts/guards/proved-share-vs-tree.sh - # Три порчи — по одной на каждую беду, которую сверка обязана назвать: - # «написано» первой строки +1, первая строка вынута, строка о файле, - # которого нет. Каждая сличается cmp (подлог собрался), требует кода не 0 - # и своих слов в выводе; опись возвращается и сличается в конце. + run: ./bootstrap/flang run-script proved-share-tree:check + # Четыре стороны порчи — нулевая (опись как есть, бед быть не должно) и по + # одной на каждую беду, которую сверка обязана назвать: «написано» первой + # мерной строки +1, строка о первом файле дерева вынута, вписана строка о + # файле, которого нет. Порча идёт В ПАМЯТИ: файл описи не трогается, и + # откатывать нечего даже если прогон убьют на середине. + # КОДЫ ПЕРЕВЁРНУТЫ, как у пары про опись дерева выше: код 1 — подлог + # пойман на всех четырёх сторонах; код 0 — сверка промолчала хотя бы на + # одной, ЛИБО порча не собралась. Оба случая обязаны красить шаг. + # Прогнано на выпотрошенной копии сверки («Troubles of», возвращающая + # пустой список на любом входе): она даёт этому шагу код 0. + # Зовётся ФАЙЛОМ, а не командой `proved-share-tree:forgery`: прибор проб + # порчи (scripts/guards/guards-without-forgery-probe.fscript) относит + # пробу к сторожу по файлу, а не по имени парной команды. - name: Probe proved share - env: - FLANG_TMP: ${{ runner.temp }} run: | - opis=scripts/ledgers/proved-share-ledger.txt - cp "$opis" "$RUNNER_TEMP/opis" - porcha() { - slova=$1; shift - awk "$@" "$RUNNER_TEMP/opis" > "$opis" - if cmp -s "$opis" "$RUNNER_TEMP/opis"; then - echo "ПОДЛОГ НЕ СОБРАЛСЯ: опись не изменилась (порча «$slova»)" >&2 - exit 1 - fi - if sh scripts/guards/proved-share-vs-tree.sh > "$RUNNER_TEMP/sverka.out" 2>&1; then - cp "$RUNNER_TEMP/opis" "$opis" - echo "СВЕРКА ПРОМОЛЧАЛА на порче «$slova»" >&2 - exit 1 - fi - cp "$RUNNER_TEMP/opis" "$opis" - if ! grep -F "$slova" "$RUNNER_TEMP/sverka.out"; then - echo "ПОКРАСНЕЛО НЕ ПО ПОРЧЕ «$slova»:" >&2 - tail -5 "$RUNNER_TEMP/sverka.out" >&2 - exit 1 - fi - } - porcha '«НАПИСАНО» НЕ СХОДИТСЯ' -F'|' -v OFS='|' '!s && !/^\/\// && NF == 7 && $2 ~ /^[0-9]+$/ { $2 = $2 + 1; s = 1 } { print }' - porcha 'НЕТ СТРОКИ' -F'|' '!s && !/^\/\// && NF == 7 { s = 1; next } { print }' - porcha 'ЛИШНЯЯ СТРОКА' '{ print } END { print "00000000000000000000000000000000|1|×|×|×|0|docs/there-is-no-such-file.flang" }' - cmp "$opis" "$RUNNER_TEMP/opis" + if ./bootstrap/flang io scripts/guards/proved-share-vs-tree.fscript --plan Forgery; then + echo "сверка промолчала на порченой описи — проверять ею нечего" >&2 + exit 1 + fi - name: Check records follow their sources run: ./bootstrap/flang io scripts/guards/record-follows-its-source.fscript --plan Проверка @@ -1021,7 +1007,7 @@ jobs: make -C bootstrap -j"$(nproc)" CFLAGS="$FLANG_CFLAGS" fi # ПРОБА ИДЁТ ПЕРВОЙ И СТОИТ ОДНУ ПЕЧАТЬ ИЗ ТРЁХ. Сторож, которого нельзя - # покрасить, неотличим от выключенного (scripts/guards/guards-without-forgery-probe.sh: + # покрасить, неотличим от выключенного (scripts/guards/guards-without-forgery-probe.fscript: # за одни сутки 5 сентября 2026 эта порода поймана четырежды, и ни разу # прибором). Проба подкладывает сверщику изменённый байт и пропавший # файл и требует красноты, а от дословной копии — молчания. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a717984d..6dcc406e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -212,8 +212,8 @@ jobs: # 31 августа 2026 в дереве нашлось 31 место в 14 файлах, где записанное рукой # число разошлось с тем, что лежит рядом: `docs/tree-inventory.md` считала # `seed-parses-sources-guard.sh` в 83 строки при 195, оболочку — в 66 файлов - # при 71 тогдашних — сегодня их 49; - # СНЯТО 2026-10-04 файлов *.sh = 49 (перенос flang/translation/run.sh на план flang/translation/run.fscript снял один файл оболочки; до него 50, снято 2026-10-04) (задача 5821: scripts/guards/version-derivations-guard.sh снят — сверка производных версии стала планом scripts/guards/version-derivations-guard.fscript, приговор доказан ядром (13 из 13), хук зовёт план; до него 51, снято 2026-10-04) (задача 0049: scripts/seed/seed-freshness.sh снят — проверка давно живёт планом scripts/seed/seed-freshness.fscript, а переходник ещё и терял довод (exec без "$@"); до него 52, снято 2026-10-04) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 101, снято 2026-09-21) `flang/cat/SPEC.md` обещала восемнадцать поручений при 22; + # при 71 тогдашних — сегодня их 47; + # СНЯТО 2026-10-04 файлов *.sh = 47 (перенос scripts/guards/proved-share-vs-tree.sh и guards-without-forgery-probe.sh на планы снял два файла оболочки; до них 49, снято 2026-10-04) (перенос flang/translation/run.sh на план flang/translation/run.fscript снял один файл оболочки; до него 50, снято 2026-10-04) (задача 5821: scripts/guards/version-derivations-guard.sh снят — сверка производных версии стала планом scripts/guards/version-derivations-guard.fscript, приговор доказан ядром (13 из 13), хук зовёт план; до него 51, снято 2026-10-04) (задача 0049: scripts/seed/seed-freshness.sh снят — проверка давно живёт планом scripts/seed/seed-freshness.fscript, а переходник ещё и терял довод (exec без "$@"); до него 52, снято 2026-10-04) (задача 5821: семь скриптов scripts/** переехали с оболочки на flang; до них 101, снято 2026-09-21) `flang/cat/SPEC.md` обещала восемнадцать поручений при 22; # `flang/PLAN.md` — пять вариантов «Поручение» при 22. Каждое из этих чисел # было ВЕРНО В ДЕНЬ ЗАПИСИ и солгало назавтра, и сторожа не было ни на одном. # @@ -305,7 +305,7 @@ jobs: # ПРОБ ДВЕ, И ВТОРАЯ ВАЖНЕЕ ПЕРВОЙ. Первая подкладывает путь в памяти плана # (`--plan Подлог`). Вторая кладёт НАСТОЯЩУЮ ВРЕМЯНКУ НА ДИСК и требует кода 1: # в чистой выписке CI сторож зелен всегда, а сторож, зелёный всегда, неотличим - # от выключенного (scripts/guards/guards-without-forgery-probe.sh, та же порода). + # от выключенного (scripts/guards/guards-without-forgery-probe.fscript, та же порода). vremyanki: name: stray-temporaries runs-on: ubuntu-latest @@ -1450,6 +1450,29 @@ jobs: - name: Check uncalled guards run: bootstrap/flang run-script guard-calls:check + # ПРИБОР, КОТОРЫЙ СТЕРЕЖЁТ НАЛИЧИЕ ПРОБ ПОРЧИ, ОБЯЗАН НЕСТИ ПРОБУ ТЕМ + # БОЛЕЕ. Сосед выше отвечает на вопрос «кого CI зовёт»; этот — на второй, + # без которого первый мало стоит: «а показано ли, что позванный вообще + # способен покраснеть». 4 октября 2026 он перенесён с оболочки + # (scripts/guards/guards-without-forgery-probe.sh, 275 строк с python и + # pyyaml) на план: разбор ключей run: ввезён у соседа + # scripts/guards/who-calls-the-guards.fscript, и разборщик YAML больше не + # нужен. До переноса его звал только хук перед пушем, CI — никто. + # + # КОДЫ ПЕРЕВЁРНУТЫ, а не как у соседа выше: план «Forgery» здесь портит + # перепись и ведомость В ПАМЯТИ и отвечает кодом 1, когда подлог пойман на + # всех пяти сторонах; код 0 значит «сверка промолчала хотя бы на одной» + # либо «порча не собралась». Прогнано на выпотрошенной копии («Troubles + # of», возвращающая пустой список на любом входе): она даёт шагу код 0. + - name: Probe guards without forgery probe + run: | + if bootstrap/flang io scripts/guards/guards-without-forgery-probe.fscript --plan Forgery; then + echo "сверка промолчала на порченой переписи — проверять ею нечего" >&2 + exit 1 + fi + - name: Check guards without forgery probe + run: bootstrap/flang run-script forgery-probe:check + # ── Ещё двое, прогнанные и снабжённые подлогом задачей 6612 ──────────── # # Оба числились ЗВАНЫМИ у переписи зова, и оба званы не были: прибор @@ -1547,7 +1570,7 @@ jobs: ln -sf "$put" "$podstavnoy/$programma" done # Вызов стоит В УСЛОВИИ `if`, и это не вкусовщина: перепись проб - # (scripts/guards/guards-without-forgery-probe.sh) засчитывает пробу только такой + # (scripts/guards/guards-without-forgery-probe.fscript) засчитывает пробу только такой # форме. Записанный как `otvet=$(…) && { … }`, тот же шаг работает, # но прибор его не видит, и сторож числится беспробным. if otvet=$(PATH="$podstavnoy" bootstrap/flang run-script install-path:check 2>&1); then diff --git a/.github/workflows/install-path.yml b/.github/workflows/install-path.yml index a9875ffcb..7a68a384a 100644 --- a/.github/workflows/install-path.yml +++ b/.github/workflows/install-path.yml @@ -223,7 +223,7 @@ jobs: # копии и ОБЯЗАН ответить провалом «подлог пойман». Ответил кодом 0 — # значит сравнение выпотрошено, и зелёный шаг выше ничего не значит. # Зовётся файлом, а не командой `asdf-plugin:forgery`: прибор проб порчи - # (scripts/guards/guards-without-forgery-probe.sh) относит пробу к сторожу по файлу. + # (scripts/guards/guards-without-forgery-probe.fscript) относит пробу к сторожу по файлу. - name: Probe asdf plugin run: | set -u @@ -247,7 +247,7 @@ jobs: # покраснел на подложенном. Подлог внутренний — план «Подлог» того же # файла вычёркивает проводник из прочитанного состава архива и ОБЯЗАН # ответить провалом «подлог пойман». Зовётся файлом, а не командой: - # прибор проб порчи (scripts/guards/guards-without-forgery-probe.sh) относит пробу к + # прибор проб порчи (scripts/guards/guards-without-forgery-probe.fscript) относит пробу к # сторожу по файлу. - name: Probe delivery contents run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae3fc8597..a69009517 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -246,7 +246,7 @@ jobs: # ПОКАЗАНО ПРОГОНОМ, ЧТО СТОРОЖ ВЫШЕ УМЕЕТ КРАСНЕТЬ. # # Сторож, у которого не показано, что он краснеет, — это сторож, которому - # верят зря: ровно этот род долга считает `scripts/guards/guards-without-forgery-probe.sh`. + # верят зря: ровно этот род долга считает `scripts/guards/guards-without-forgery-probe.fscript`. # Проба подставляет версию, заметки о которой в json заведомо нет, и # требует от плана ОТКАЗА. Прошёл план — красный здесь, а не молчание. # diff --git a/docs/javascript-inventory.md b/docs/javascript-inventory.md index c605cb21c..20c8c5fd8 100644 --- a/docs/javascript-inventory.md +++ b/docs/javascript-inventory.md @@ -68,8 +68,8 @@ JavaScript стало 55, строк 29 733; в трёх каталогах о Эта опись считает ОДИН язык. Остальные шестнадцать — оболочка, C, C++, Python, HTML, CSS, awk, Erlang, Java, C#, Elixir, Go, Rust, Lua, vimscript, Ruby — -считает [`tree-inventory.md`](tree-inventory.md) (4 октября 2026: 192 файлов вне flang, - +считает [`tree-inventory.md`](tree-inventory.md) (4 октября 2026: 190 файлов вне flang, + долг вне JavaScript — **97 файлов, 18 427 строк при потолке 63**: храповик красен, разбор — задачи 4838 и 7405). Там же названы 569 строк JavaScript, лежащих ВНУТРИ файлов `.html`: счёт по именам файлов их не видит, и diff --git a/docs/shell-to-flang-census.md b/docs/shell-to-flang-census.md index 0e8b9fe2a..bb0816215 100644 --- a/docs/shell-to-flang-census.md +++ b/docs/shell-to-flang-census.md @@ -67,8 +67,18 @@ done Файлов, у которых НИ ОДНОГО из этих семи признаков, — **три**: `scripts/guards/proved-share-vs-tree.sh`, `scripts/guards/seed-knows-type-words-guard.sh` -и `scripts/release/bump-version.sh`. Первые два держит не язык, а место вызова -(хук до сборки двоичного; сторож судит семя). Третий перенесён. +и `scripts/release/bump-version.sh`. Третий был перенесён тогда же. + +**Довод про «место вызова» у первого УСТАРЕЛ, и это проверено прогоном +4 октября 2026.** Он звучал так: «сторожа держит хук перед пушем, а хук идёт до +сборки двоичного». С задачи 1219 хук САМ СТАЛ ПЛАНОМ: `.githooks/pre-push` — это +две строки `exec bootstrap/flang io .githooks/pre-push.fscript`, то есть к +моменту, когда хук зовёт сторожа, двоичный обязан уже существовать, иначе не +стартует и сам хук. Второе место вызова, `binary.yml`, зовёт `./bootstrap/flang` +на двенадцати шагах выше. Оба довода мертвы, и сторож перенесён +(`scripts/guards/proved-share-vs-tree.fscript`, 13 обязательств, все доказаны +ядром; прогон обоих на одном дереве дал одни и те же 14 чисел и одни и те же +слова на трёх порчах описи). ### Пять новых границ, найденных пересчётом @@ -141,7 +151,7 @@ done Столбец «упирается во что» — теперь ДВЕ причины там, где их две. Порядок — по причине. -### Перенесено на flang — 7 (3 в первой работе, 4 в этой) +### Перенесено на flang — 9 (3 в первой работе, 4 во второй, 2 в третьей) | файл | строк | стало | чем доказано равенство | |---|---:|---|---| @@ -152,13 +162,14 @@ done | `scripts/seed/print-progress.sh` | 88 | `print-progress.fscript` | 13 пар прогонов, из них 4 НАСТОЯЩИХ журнала печати (1,5–147 КБ) | | `scripts/cell-work-preserved.sh` | 97 | `cell-work-preserved.fscript` | 5 пар прогонов на построенных ячейках, сверка заведённых ссылок | | `scripts/release/bump-version.sh` | 145 | `bump-version.fscript` | показ + подъём на двух деревьях-близнецах, пять файлов сверены побайтово | +| `scripts/guards/proved-share-vs-tree.sh` | 139 | `…-vs-tree.fscript`, планы «Check», «Numbers», «Forgery» | отчёт сошёлся ЗНАК В ЗНАК (14 чисел), три порчи описи дали одни и те же слова и код 1 у обоих | +| `scripts/guards/guards-without-forgery-probe.sh` | 275 | `…-probe.fscript`, планы «Check», «Census», «List», «Forgery» | перепись и список сошлись ЗНАК В ЗНАК, две порчи ведомости дали одни и те же слова и код 1 у обоих | -### Упирается в чужой прибор, которого у языка нет — 8 +### Упирается в чужой прибор, которого у языка нет — 7 | файл | строк | во что именно | |---|---:|---| -| `scripts/guards/guards-without-forgery-probe.sh` | 323 | разборщик YAML (`pyyaml`); подстрочный счёт уже давал ложные записи | -| `scripts/guards/who-calls-the-guards.sh` | 269 | то же: ключ `run:` берётся разбором YAML, подстрочный счёт давал 115 ярлыков вместо 111 | +| `scripts/guards/who-calls-the-guards.sh` | 269 | то же: ключ `run:` берётся разбором YAML, подстрочный счёт давал 115 ярлыков вместо 111 — довод снят переносом самого соседа 4 октября 2026 | | `scripts/seed/seed-runtime-is-source.fscript` | 80 | `diff` считает по наибольшей общей подпоследовательности; построчное сличение даст ДРУГОЕ число | | `scripts/guards/seed-knows-type-words-guard.sh` | 311 | ПОРОЖДАЕТ программу на awk и гоняет её лексером по сотням файлов; mawk против gawk дал 30 ложных находок — это мера, а не счёт | | `scripts/targets/target-collisions.sh` | 248 | `jq` и awk-программа построения дерева | @@ -166,7 +177,7 @@ done | `scripts/guards/bad-octet-guard.sh` | 340 | сырые негодные октеты: литерал flang их не несёт | | `scripts/guards/one-string-measure-guard.sh` | 119 | то же | -### Упирается в порядок сборки: зовётся до того, как собран двоичный — 5 +### Упирается в порядок сборки: зовётся до того, как собран двоичный — 4 Хук `.githooks/pre-push` нарочно не собирает `bootstrap/flang` (2 минуты на раннере, 5–6 на слабой машине). **Это граница порядка сборки, а не языка.** Её @@ -179,7 +190,6 @@ done | `scripts/guards/task-numbers-guard.sh` | 284 | ярлыки.flang (и это ЗАМЫСЕЛ: запасной путь на свежем клоне) | | `scripts/guards/flangrc-guard.sh` | 238 | ярлыки.flang, ci.yml | | `scripts/guards/version-derivations-guard.sh` | 195 | хук, .flangrc | -| `scripts/guards/proved-share-vs-tree.sh` | 139 | хук, binary.yml | ### Судит двоичный, семя или печать — 7 @@ -268,8 +278,9 @@ done | причина | файлов | строк | |---|---:|---:| | перенесено на flang (в этой работе) | 4 | 415 | -| чужой прибор, которого у языка нет | 8 | 1772 | -| зовётся до сборки двоичного | 5 | 1272 | +| перенесено на flang (4 октября 2026) | 2 | 414 | +| чужой прибор, которого у языка нет | 7 | 1449 | +| зовётся до сборки двоичного | 4 | 1133 | | судит двоичный, семя или печать | 7 | 1402 | | собирает сам двоичный | 5 | 4269 | | экран, терминал, ssh | 3 | 693 | @@ -281,6 +292,17 @@ done | прочее | 3 | 1462 | | **осталось в `scripts/`** | **41** | **12 705** | +**Вся таблица — замер 23 сентября 2026, и трогать её числа задним числом +нельзя.** Два переноса 4 октября 2026 сняли из неё 2 файла и 414 строк +(`proved-share-vs-tree.sh` 139 и `guards-without-forgery-probe.sh` 275), но +сложить 41 − 2 и 12 705 − 414 значило бы выдать арифметику над протухшей базой +за замер: за эти одиннадцать суток `scripts/**` похудел и чужими работами. +Замер того же прибором 4 октября 2026 — **9 файлов и 6 169 строк** +(`git ls-files 'scripts/*.sh' 'scripts/**/*.sh' | wc -l` и `| xargs wc -l`), +то есть долг оболочки в `scripts/` убыл вчетверо, а не на два файла. Четвёртый +столбец «Числа» этим замером не заводится: он требует перепись целиком, а не +одну строку. + ## Что сдвинуло бы перепись дальше, числом Порядок — по числу освобождаемых файлов на одно изменение. diff --git a/docs/tree-inventory.md b/docs/tree-inventory.md index 720b0986f..722a6e9aa 100644 --- a/docs/tree-inventory.md +++ b/docs/tree-inventory.md @@ -1,5 +1,5 @@ -# Опись дерева по языкам: 192 файлов вне flang, долг вне JavaScript — 93 при потолке 63 - +# Опись дерева по языкам: 190 файлов вне flang, долг вне JavaScript — 93 при потолке 63 + ⚠ **ХРАПОВИК ДОЛГА КРАСЕН, и заголовок это теперь говорит.** Прогон `bootstrap/flang run-script inventory:languages` **5 сентября 2026** отвечает кодом 1: «ДОЛГ ВНЕ @@ -76,7 +76,7 @@ $ bootstrap/flang io scripts/guards/tree-inventory.fscript --max-steps 50000000 | язык | файлов | строк | долг файлов | долг строк | |---|---:|---:|---:|---:| -| оболочка | 55 | 9661 | 50 | 5 431 | +| оболочка | 53 | 9 247 | 48 | 5 017 | | C | 39 | 882 835 | 0 | 0 | | C++ | 1 | 404 | 0 | 0 | | Python | 5 | 2 906 | 0 | 0 | diff --git a/scripts/guards/guards-without-forgery-probe.fscript b/scripts/guards/guards-without-forgery-probe.fscript new file mode 100644 index 000000000..a06ac84ce --- /dev/null +++ b/scripts/guards/guards-without-forgery-probe.fscript @@ -0,0 +1,1237 @@ +модуль «Guards without forgery probe» + использует «Who calls the guards» из "who-calls-the-guards.fscript" + +примечание "У КАКИХ СТОРОЖЕЙ НЕТ ПРОБЫ ПОРЧИ — поимённо, прибором, а не рукой." +примечание " bootstrap/flang run-script forgery-probe:check сверка с ведомостью, код 1" +примечание " bootstrap/flang run-script forgery-probe:census перепись целиком, код 0" +примечание " bootstrap/flang run-script forgery-probe:list только имена беспробных" +примечание " bootstrap/flang run-script forgery-probe:forgery пять сторон порчи, код 1" + +примечание "ЗАЧЕМ. СТОРОЖ, КОТОРОГО НЕЛЬЗЯ ПОКРАСИТЬ, НЕОТЛИЧИМ ОТ ВЫКЛЮЧЕННОГО. За одни" +примечание "сутки 5 сентября 2026 эта порода поймана четыре раза, и ни разу прибором —" +примечание "всякий раз случайно: target-words:check проверял пустоту (задача 3223); шесть" +примечание "проверок чекера не отрабатывали ни разу (8690); проба под правило 9999 лежала в" +примечание "дереве, а run.sh её не звал (9999); две пробы порчи не собрались, и заметно это" +примечание "было только по тому, что числа не сдвинулись (7855, 9751). Общее у всех" +примечание "четырёх — беспроверочная вера в то, что проверка работает." + +примечание "Прибор scripts/guards/who-calls-the-guards.fscript отвечает на вопрос «кого CI" +примечание "зовёт»; этот отвечает на второй, без которого первый мало стоит: «а показано" +примечание "ли, что позванный вообще способен покраснеть»." + +примечание "ЧТО СЧИТАЕТСЯ ПРОБОЙ ПОРЧИ. Проба — это то, что ЛОМАЕТ проверяемое и требует," +примечание "чтобы сторож на этом покраснел. В дереве проба бывает ПОСТРОЕНА и отдельно —" +примечание "ПОЗВАНА, и путать эти два состояния нельзя: построенная, но никем не званная" +примечание "проба не срабатывает никогда, ровно как сторож без зовущего." +примечание " ПРОБА ПОСТРОЕНА — рядом с ярлыком X:check в .flangrc есть парный X:forgery" +примечание " или X:corrupt. Такая команда портит вход изнутри сторожа: она не зависит от" +примечание " номеров строк и портит ровно то, что сторож смотрит. Лучший вид пробы." +примечание " ПРОБА ПОЗВАНА — в теле run: какого-нибудь workflow стоит вызов сторожа В" +примечание " УСЛОВИИ if, и в том же теле есть exit 1. Признак один и тот же и от вида" +примечание " порчи не зависит: шаг падает ровно тогда, когда сторож промолчал." +примечание "Прибор считает оба и печатает раздельно. В долг («без пробы») попадает тот, у" +примечание "кого НЕТ НИ ОДНОГО из двух." + +примечание "ЧЕГО ЭТОТ ПРИБОР НЕ ГОВОРИТ. Он НЕ говорит, что проба хороша. Проба бывает" +примечание "холостой: правка не собралась либо испорчено не то, что сторож смотрит. Такую" +примечание "пробу прибор считает существующей, потому что отличить её от рабочей он не" +примечание "может — для этого надо прогнать сторожа с порчей и без. Это делает сама проба" +примечание "в CI; здесь считается только ЕЁ НАЛИЧИЕ." + +примечание "ВЕДОМОСТЬ, А НЕ ЗАПРЕТ. Беспробных сторожей больше половины; правило" +примечание "«беспробных быть не должно» красило бы CI всегда, а вечно красный сторож — это" +примечание "выключенный сторож. Поэтому план «Check» сверяет с ведомостью" +примечание "scripts/ledgers/guards-without-forgery-probe.json В ОБЕ СТОРОНЫ:" +примечание " · беспробный, которого в ведомости НЕТ, — красно: появился новый долг;" +примечание " · запись, у которой проба УЖЕ есть, — тоже красно: долг закрыт, запись стала" +примечание " неправдой, и убрать её обязан тот, кто долг закрыл." + +примечание "ЧЕМ ЭТОТ ФАЙЛ ОТЛИЧАЕТСЯ ОТ ПРЕЖНЕГО НА ОБОЛОЧКЕ. До 4 октября 2026 то же" +примечание "считал scripts/guards/guards-without-forgery-probe.sh, 275 строк оболочки с" +примечание "встроенной программой на python. Перепись дерева" +примечание "(docs/shell-to-flang-census.md) держала его доводом «разборщик YAML (pyyaml)»." +примечание "Довод снят не словами, а соседом: who-calls-the-guards.fscript берёт ключи" +примечание "run: разбором отступов, и его разбор здесь ВВЕЗЁН, а не переписан заново." +примечание "Нового в этом файле — только группировка строк в ТЕЛА: прежний сосед отдавал" +примечание "плоский список строк, а здесь нужно, чтобы exit 1 стоял в ТОМ ЖЕ теле, что и" +примечание "условие. Числа прогона обоих приборов на этом дереве 4 октября 2026 сошлись:" +примечание "77 сторожей, 34 пробы позваны, 13 построены и не позваны, 43 в долгу." + +примечание "ЧЕГО ЗДЕСЬ НЕТ. Расхождение кода возврата названо: у плана нет кода 3 за" +примечание "«нет модуля yaml» — разборщик свой; «ведомости нет» отвечает кодом 3, как и у" +примечание "оболочки, а «кривой ключ» у плана невозможен — режим задаётся именем плана." + +объект «Sweep» + «floor»: число + «running»: признак + «lines»: список строки + «bodies»: список строки + +объект «Spot» + «file»: строка + «names»: строка + «scripts»: строка + +объект «Post» + «name»: строка + «file»: строка + «built»: строка + +объект «Side» + «name»: строка + «says»: строка + «stands»: список «Post» + «entries»: список «Entry» + +тип «Stage» + вариант «Listing flows» содержит mode: строка + вариант «Reading a flow» содержит mode: строка, pending: список строки, spots: список «Spot» + вариант «Reading the debt» содержит mode: строка, spots: список «Spot» + вариант «Reading settings» содержит mode: строка, spots: список «Spot», entries: список «Entry» + +примечание "── ТЕЛА КЛЮЧЕЙ run: ГРУППАМИ, А НЕ ПЛОСКИМ СПИСКОМ ────────────────────────" + +примечание "Проба — конструкция из нескольких строк: порча, условие, откат. Резать её на" +примечание "строки значит потерять связь между вызовом и exit 1. Ввезённый сосед" +примечание "«Commands of» отдаёт плоский список со всех ключей run: разом; здесь тот же" +примечание "обход копит строки ТЕЛА и закрывает тело, когда блок кончился." + +тотальная функция «Sweep made» + принимает floor: число, running: признак, lines: список строки, bodies: список строки + возвращает «Sweep» + запись «Sweep» с «floor» равным floor и «running» равным running и «lines» равным lines и «bodies» равным bodies + +тотальная функция «Flushed» + принимает lines: список строки, bodies: список строки + возвращает список строки + пример «The lines of a body become one body» + дано lines равно ["a", "b"] + дано bodies равно пустой список + ожидается ["a\nb"] + пример «An empty body closes nothing» + дано lines равно пустой список + дано bodies равно ["c"] + ожидается ["c"] + если (длина lines) равен 0 + то bodies + иначе добавить (соединить lines по "\n") к bodies + +тотальная функция «Is noted» + принимает line: строка + возвращает признак + пример «A comment of YAML names no key» + дано line равно " # run: sh one.sh" + ожидается да + пример «A key is not a comment» + дано line равно " run: |" + ожидается нет + («Entry body» от line) начинается с "#" + +тотальная функция «Opens body» + принимает line: строка + возвращает признак + пример «A run key with a bar opens a body of commands» + дано line равно " - run: |" + ожидается да + пример «A run key with a plain value opens no body» + дано line равно " - run: make" + ожидается нет + пример «A run key inside a comment opens nothing» + дано line равно " # run: |" + ожидается нет + пусть value равно («Run value» от («Entry body» от line)) + пусть block равно ((value начинается с "|") или (value начинается с ">")) + (не («Is noted» от line)) и притом block + +тотальная функция «Opens any» + принимает line: строка + возвращает признак + пример «A block of another key is opened to be skipped» + дано line равно " script: |" + ожидается да + пример «A plain value opens nothing» + дано line равно " - run: make" + ожидается нет + пусть other равно ((не («Is noted» от line)) и притом («Opens a block» от («Entry body» от line))) + («Opens body» от line) или other + +тотальная функция «Key floor» + принимает line: строка + возвращает число + пример «The floor of a block stands one sign right of its key» + дано line равно " - run: |" + ожидается 9 + пример «A plain value leaves no floor» + дано line равно " - run: make" + ожидается 0 + если («Opens any» от line) + то («Entry indent» от line) плюс 1 + иначе 0 + +тотальная функция «Plain value» + принимает line: строка + возвращает строка + пример «A run key with a plain value is one body» + дано line равно " - run: make" + ожидается "make" + пример «A run key with a bar is not a plain value» + дано line равно " - run: |" + ожидается "" + пример «A comment is not a value» + дано line равно " # run: make" + ожидается "" + пусть value равно («Run value» от («Entry body» от line)) + пусть plain равно ((не («Is noted» от line)) и притом (не («Opens any» от line))) + если plain то value иначе "" + +тотальная функция «Inside sweep» + принимает sweep: «Sweep», line: строка + возвращает «Sweep» + пусть kept равно (добавить line к (sweep.«lines»)) + если sweep.«running» + то «Sweep made» от (sweep.«floor») и да и kept и (sweep.«bodies») + иначе sweep + +тотальная функция «Key sweep» + принимает sweep: «Sweep», line: строка + возвращает «Sweep» + пусть closed равно («Flushed» от (sweep.«lines») и (sweep.«bodies»)) + пусть value равно («Plain value» от line) + пусть bodies равно (если value равен "" то closed иначе (добавить value к closed)) + «Sweep made» от («Key floor» от line) и («Opens body» от line) и (пустой список) и bodies + +тотальная функция «Names a key» + принимает line: строка + возвращает признак + пример «A line with a key is looked at closely» + дано line равно " - run: make" + ожидается да + пример «A filter of paths names no key» + дано line равно " - 'scripts/one.sh'" + ожидается нет + ((line содержит "run:") или (line содержит "|")) или (line содержит ">") + +тотальная функция «Outside sweep» + принимает sweep: «Sweep», line: строка + возвращает «Sweep» + пусть closed равно («Flushed» от (sweep.«lines») и (sweep.«bodies»)) + если («Names a key» от line) + то «Key sweep» от sweep и line + иначе «Sweep made» от 0 и нет и (пустой список) и closed + +тотальная функция «Sweep step» + принимает sweep: «Sweep», line: строка + возвращает «Sweep» + если «Belongs to block» от (sweep.«floor») и line + то «Inside sweep» от sweep и line + иначе «Outside sweep» от sweep и line + +тотальная функция «Bodies of» + принимает text: строка + возвращает список строки + пример «Every run key gives a body of its own, and comments stay inside it» + дано text равно "steps:\n - run: |\n # п\n if sh a.sh; then exit 1; fi\n - run: make\n" + ожидается [" # п\n if sh a.sh; then exit 1; fi", "make"] + пусть start равно («Sweep made» от 0 и нет и (пустой список) и (пустой список)) + пусть swept равно (свёртка (разделить text по "\n") начиная с start как sweep и line → «Sweep step» от sweep и line) + «Flushed» от (swept.«lines») и (swept.«bodies») + +примечание "── ПРИЗНАК ПРОБЫ: ВЫЗОВ В УСЛОВИИ if, И В ТОМ ЖЕ ТЕЛЕ exit 1 ──────────────" + +тотальная функция «Is if line» + принимает line: строка + возвращает признак + пример «A call in a condition is a probe» + дано line равно " if sh one.sh --подлог; then exit 1; fi" + ожидается да + пример «A bare call is a working run, not a probe» + дано line равно " sh one.sh --check" + ожидается нет + пример «A comment of the shell is not a condition» + дано line равно " # if sh one.sh; then exit 1; fi" + ожидается нет + пусть bare равно («Without leading blanks» от line) + (bare начинается с "if ") или (bare начинается с "elif ") + +тотальная функция «Demands red» + принимает body: строка + возвращает признак + пример «A body that falls demands red» + дано body равно "if sh one.sh; then exit 1; fi" + ожидается да + пример «A body that never falls demands nothing» + дано body равно "sh one.sh --check" + ожидается нет + body содержит "exit 1" + +тотальная функция «Spot made» + принимает file: строка, names: список строки, scripts: список строки + возвращает «Spot» + пример «A spot keeps the file and both ways of calling» + дано file равно "ci" + дано names равно ["a:check"] + дано scripts равно ["b.sh"] + ожидается (запись «Spot» с «file» равным "ci" и «names» равным "\na:check\n" и «scripts» равным "\nb.sh\n") + запись «Spot» с «file» равным file и «names» равным («Marked» от names) и «scripts» равным («Marked» от scripts) + +тотальная функция «Parting marks» + возвращает список строки + обеспечивает «знаков оболочки восемь» (длина результат) равен 8 + ["\"", "'", "`", "(", ")", ";", "&", "|"] + +тотальная функция «Cleaned» + принимает line: строка + возвращает строка + пример «The signs that bind a call to the shell are taken off» + дано line равно "if sh one.sh; then exit 1; fi" + ожидается "if sh one.sh then exit 1 fi" + пример «A call in brackets stands on its own» + дано line равно "if (sh one.sh); then" + ожидается "if sh one.sh then" + свёртка («Parting marks») начиная с line как text и sign → соединить (разделить text по sign) по " " + +тотальная функция «Spot of body» + принимает file: строка, body: строка + возвращает «Spot» + пример «The calls of the conditions of a body are gathered» + дано file равно "ci" + дано body равно "if bootstrap/flang run-script a:check; then exit 1; fi\nsh b.sh" + ожидается (запись «Spot» с «file» равным "ci" и «names» равным "\na:check\n" и «scripts» равным "\n\n") + пусть kept равно (отфильтровать (разделить body по "\n") где line → («Is if line» от line)) + пусть lines равно (отобразить kept как line → («Cleaned» от line)) + пусть names равно (свёртка lines начиная с (пустой список) как found и line → «Names in» от found и line) + пусть scripts равно (свёртка lines начиная с (пустой список) как found и line → «Scripts in» от found и line) + «Spot made» от file и names и scripts + +тотальная функция «Spots of» + принимает file: строка, text: строка + возвращает список «Spot» + пусть bodies равно (отфильтровать («Bodies of» от text) где body → («Demands red» от body)) + отобразить bodies как body → («Spot of body» от file и body) + +примечание "── ПАРНАЯ КОМАНДА: X:forgery ЛИБО X:corrupt РЯДОМ С X:check ───────────────" + +тотальная функция «Front pieces» + принимает pieces: список строки + возвращает список строки + обеспечивает «список не длиннее прежнего» (длина результат) не больше (длина pieces) + пример «The last piece is dropped» + дано pieces равно ["word", "occupancy", "check"] + ожидается ["word", "occupancy"] + пример «Of one piece nothing is left» + дано pieces равно ["check"] + ожидается пустой список + разбор pieces + случай пусто + то пустой список + случай голова и хвост + то если (длина хвост) равен 0 + то пустой список + иначе приписать голова к («Front pieces» от хвост) + +тотальная функция «Prefix of» + принимает name: строка + возвращает строка + пример «The prefix is the name without its last share» + дано name равно "codes:check" + ожидается "codes" + пример «A joined name keeps its middle shares» + дано name равно "word:occupancy:check" + ожидается "word:occupancy" + соединить («Front pieces» от (разделить name по ":")) по ":" + +тотальная функция «Pair name» + принимает name: строка, tail: строка + возвращает строка + пример «The pair of a guard stands at its prefix» + дано name равно "codes:check" + дано tail равно "forgery" + ожидается "codes:forgery" + соединить [(«Prefix of» от name), ":", tail] по "" + +тотальная функция «Or corrupt» + принимает name: строка, marks: строка + возвращает строка + пример «A corrupt command counts as a built probe» + дано name равно "codes:check" + дано marks равно "\ncodes:corrupt\n" + ожидается "codes:corrupt" + пример «Without a pair nothing is built» + дано name равно "codes:check" + дано marks равно "\nother:forgery\n" + ожидается "" + пусть corrupt равно («Pair name» от name и "corrupt") + если («Is marked» от marks и corrupt) то corrupt иначе "" + +тотальная функция «Built pair» + принимает name: строка, marks: строка + возвращает строка + пример «A forgery command is the first pair looked for» + дано name равно "codes:check" + дано marks равно "\ncodes:forgery\n\ncodes:corrupt\n" + ожидается "codes:forgery" + пример «Without a forgery the corrupt command is taken» + дано name равно "codes:check" + дано marks равно "\ncodes:corrupt\n" + ожидается "codes:corrupt" + пусть forgery равно («Pair name» от name и "forgery") + если («Is marked» от marks и forgery) + то forgery + иначе «Or corrupt» от name и marks + +примечание "── ПОЛОЖЕНИЕ СТОРОЖА: ГДЕ СТОИТ ЕГО ПРОБА И ПОСТРОЕНА ЛИ ПАРНАЯ КОМАНДА ───" + +тотальная функция «Post made» + принимает name: строка, file: строка, built: строка + возвращает «Post» + запись «Post» с «name» равным name и «file» равным file и «built» равным built + +тотальная функция «No spot» + возвращает «Spot» + пример «A guard nobody probes stands at no spot» + ожидается (запись «Spot» с «file» равным "" и «names» равным "" и «scripts» равным "") + запись «Spot» с «file» равным "" и «names» равным "" и «scripts» равным "" + +тотальная функция «Calls it» + принимает command: «Command», spot: «Spot» + возвращает признак + пример «A probe calls the guard by its name» + дано command равно (запись «Command» с «name» равным "a:check" и «line» равным "sh one.sh") + дано spot равно (запись «Spot» с «file» равным "ci" и «names» равным "\na:check\n" и «scripts» равным "") + ожидается да + пример «A probe calls the guard by its file» + дано command равно (запись «Command» с «name» равным "a:check" и «line» равным "sh one.sh") + дано spot равно (запись «Spot» с «file» равным "ci" и «names» равным "" и «scripts» равным "\none.sh\n") + ожидается да + пример «A spot that calls neither does not call the guard» + дано command равно (запись «Command» с «name» равным "a:check" и «line» равным "sh one.sh") + дано spot равно (запись «Spot» с «file» равным "ci" и «names» равным "" и «scripts» равным "\ntwo.sh\n") + ожидается нет + пусть named равно («Is marked» от (spot.«names») и (command.«name»)) + named или («Is called by file» от (command.«line») и (spot.«scripts»)) + +тотальная функция «Spot found» + принимает command: «Command», spots: список «Spot» + возвращает «Spot» + пусть found равно (отфильтровать spots где spot → («Calls it» от command и spot)) + разбор found + случай пусто + то «No spot» + случай голова и хвост + то голова + +тотальная функция «Post of» + принимает command: «Command», spots: список «Spot», marks: строка + возвращает «Post» + пусть spot равно («Spot found» от command и spots) + пусть built равно («Built pair» от (command.«name») и marks) + «Post made» от (command.«name») и (spot.«file») и built + +тотальная функция «Post named» + принимает name: строка, stands: список «Post» + возвращает «Post» + пример «The stand of the name is taken» + дано name равно "a:check" + дано stands равно [(запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "")] + ожидается (запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "") + пример «A name outside the stands stands nowhere» + дано name равно "b:check" + дано stands равно пустой список + ожидается (запись «Post» с «name» равным "b:check" и «file» равным "" и «built» равным "") + разбор (отфильтровать stands где stand → (stand.«name») равен name) + случай пусто + то «Post made» от name и "" и "" + случай голова и хвост + то голова + +тотальная функция «Sorted stands» + принимает stands: список «Post» + возвращает список «Post» + пусть names равно («Sorted» от (отобразить stands как stand → stand.«name»)) + отобразить names как name → («Post named» от name и stands) + +тотальная функция «Posts of» + принимает commands: список «Command», spots: список «Spot» + возвращает список «Post» + пусть marks равно («Marked» от (отобразить commands как command → command.«name»)) + пусть guards равно (отфильтровать commands где command → («Is guard» от (command.«name»))) + «Sorted stands» от (отобразить guards как command → («Post of» от command и spots и marks)) + +тотальная функция «Is probed» + принимает stand: «Post» + возвращает признак + пример «A guard whose probe stands somewhere is probed» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "") + ожидается да + пример «A guard without a called probe is not probed» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "p") + ожидается нет + не ((stand.«file») равен "") + +тотальная функция «Probed» + принимает stands: список «Post» + возвращает список «Post» + отфильтровать stands где stand → («Is probed» от stand) + +тотальная функция «In debt» + принимает stands: список «Post» + возвращает список «Post» + отфильтровать stands где stand → не («Is probed» от stand) + +тотальная функция «Built only» + принимает stands: список «Post» + возвращает список «Post» + отфильтровать («In debt» от stands) где stand → не ((stand.«built») равен "") + +примечание "── ПЕРЕПИСЬ ──────────────────────────────────────────────────────────────────" + +тотальная функция «Padded out» + принимает text: строка, width: число + возвращает строка + пример «A short name is padded to the column» + дано text равно "a:check" + дано width равно 10 + ожидается "a:check " + пример «A long name is left as it is» + дано text равно "a:very:long:check" + дано width равно 10 + ожидается "a:very:long:check" + если (длина text) меньше width + то соединить [text, («Padding» от (width минус (длина text)))] по "" + иначе text + +тотальная функция «Cut to» + принимает text: строка, width: число + возвращает строка + пример «A short reason is told whole» + дано text равно "дорог" + дано width равно 10 + ожидается "дорог" + пример «A long reason is cut» + дано text равно "дорог, и очень" + дано width равно 5 + ожидается "дорог" + если (длина text) больше width + то подстрока text с 1 по width + иначе text + +тотальная функция «Probe source» + принимает stand: «Post» + возвращает строка + пример «A built pair names itself as the source of the forgery» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "a:forgery") + ожидается "a:forgery" + пример «Without a pair the forgery stands in the step itself» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "") + ожидается "порча внешняя, в самом шаге" + если (stand.«built») равен "" + то "порча внешняя, в самом шаге" + иначе stand.«built» + +тотальная функция «Called line» + принимает stand: «Post» + возвращает строка + пример «A called probe is told with its file and its source» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci.yml" и «built» равным "") + ожидается " a:check ci.yml порча внешняя, в самом шаге" + пусть name равно («Padded out» от (stand.«name») и 30) + пусть file равно («Padded out» от (stand.«file») и 12) + соединить [" ", name, " ", file, " ", («Probe source» от stand)] по "" + +тотальная функция «Built line» + принимает stand: «Post» + возвращает строка + пример «A built but uncalled probe names its command» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "a:forgery") + ожидается " a:check команда a:forgery" + соединить [" ", («Padded out» от (stand.«name») и 30), " команда ", (stand.«built»)] по "" + +тотальная функция «Reason told» + принимает name: строка, entries: список «Entry» + возвращает строка + пример «The reason is read from the ledger» + дано name равно "a:check" + дано entries равно [(запись «Entry» с «guard» равным "a:check" и «reason» равным "дорог")] + ожидается "дорог" + пример «A guard outside the ledger has no reason» + дано name равно "a:check" + дано entries равно пустой список + ожидается "причина в ведомости не названа" + разбор (отфильтровать entries где entry → (entry.«guard») равен name) + случай пусто + то "причина в ведомости не названа" + случай голова и хвост + то голова.«reason» + +тотальная функция «Debt reason» + принимает stand: «Post», entries: список «Entry» + возвращает строка + пример «A built pair that nobody calls is the reason itself» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "a:forgery") + дано entries равно пустой список + ожидается "проба ПОСТРОЕНА командой a:forgery, но её не зовут" + пусть own равно (соединить ["проба ПОСТРОЕНА командой ", (stand.«built»), ", но её не зовут"] по "") + если (stand.«built») равен "" + то «Reason told» от (stand.«name») и entries + иначе own + +тотальная функция «Debt line» + принимает stand: «Post», entries: список «Entry» + возвращает строка + пример «A debt is told with its reason, cut to the column» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "") + дано entries равно [(запись «Entry» с «guard» равным "a:check" и «reason» равным "дорог")] + ожидается " a:check дорог" + пусть reason равно («Cut to» от («Debt reason» от stand и entries) и 80) + соединить [" ", («Padded out» от (stand.«name») и 30), " ", reason] по "" + +тотальная функция «Head lines» + принимает stands: список «Post» + возвращает список строки + пусть probed равно (к строке (длина («Probed» от stands))) + пусть built равно (к строке (длина («Built only» от stands))) + пусть debt равно (к строке (длина («In debt» от stands))) + ["ПЕРЕПИСЬ ПРОБ ПОРЧИ: у кого показано, что он краснеет", "", + (соединить [" сторожей в дереве ", (к строке (длина stands))] по ""), + (соединить [" ПРОБА ПОЗВАНА (CI требует красноты) ", probed] по ""), + (соединить [" проба построена, но НЕ позвана ", built] по ""), + (соединить [" ПРОБА НЕ ПОКАЗАНА (долг) ", debt] по "")] + +тотальная функция «Called lines» + принимает stands: список «Post» + возвращает список строки + пусть told равно (отобразить («Probed» от stands) как stand → («Called line» от stand)) + «Joined» от ["", "ПРОБА ПОЗВАНА, и где стоит:", ""] и told + +тотальная функция «Built lines» + принимает stands: список «Post» + возвращает список строки + пусть told равно (отобразить («Built only» от stands) как stand → («Built line» от stand)) + пусть head равно ["", "ПРОБА ПОСТРОЕНА, НО НИКТО ЕЁ НЕ ЗОВЁТ — она не срабатывает никогда:", ""] + если (длина told) равен 0 то (пустой список) иначе («Joined» от head и told) + +тотальная функция «Debt lines» + принимает stands: список «Post», entries: список «Entry» + возвращает список строки + пусть told равно (отобразить («In debt» от stands) как stand → («Debt line» от stand и entries)) + «Joined» от ["", "ДОЛГ — проба не показана, поимённо:", ""] и told + +тотальная функция «Tail lines» + возвращает список строки + обеспечивает «хвост зовёт тот же прибор» (длина результат) равен 3 + ["", "Сверка с ведомостью — тем же прибором:", + " bootstrap/flang io scripts/guards/guards-without-forgery-probe.fscript --plan Check"] + +тотальная функция «Census» + принимает stands: список «Post», entries: список «Entry» + возвращает строка + пусть head равно («Joined» от («Head lines» от stands) и («Called lines» от stands)) + пусть middle равно («Joined» от head и («Built lines» от stands)) + пусть body равно («Joined» от middle и («Debt lines» от stands и entries)) + соединить («Joined» от body и («Tail lines»)) по "\n" + +примечание "── СВЕРКА С ВЕДОМОСТЬЮ В ОБЕ СТОРОНЫ ──────────────────────────────────────" + +тотальная функция «Debt ledger» + возвращает строка + обеспечивает «ведомость лежит у ведомостей» результат содержит "scripts/ledgers/" + "scripts/ledgers/guards-without-forgery-probe.json" + +тотальная функция «New head» + принимает name: строка + возвращает строка + пример «The head of the word names the guard» + дано name равно "a:check" + ожидается "НОВЫЙ БЕЗ ПРОБЫ: «a:check» заведён, но ни один шаг CI не требует, чтобы он" + соединить ["НОВЫЙ БЕЗ ПРОБЫ: «", name, "» заведён, но ни один шаг CI не требует, чтобы он"] по "" + +тотальная функция «New tail» + возвращает строка + обеспечивает «назван и путь ведомости, и выход из долга» результат содержит "Либо построить пробу" + соединить [" покраснел на порче, и в ", («Debt ledger»), " его нет.\n Либо построить пробу,", + " либо записать в ведомость с причиной: сторож без пробы неотличим от выключенного."] по "" + +тотальная функция «New word» + принимает name: строка + возвращает строка + соединить [(«New head» от name), («New tail»)] по "" + +тотальная функция «Where probed» + принимает stand: «Post» + возвращает строка + пример «A probe that stands somewhere is named by its file» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci.yml" и «built» равным "") + ожидается "проба стоит в ci.yml" + пример «A command no longer kept is named so» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "") + ожидается "команда уже не заведена" + если («Is probed» от stand) + то соединить ["проба стоит в ", (stand.«file»)] по "" + иначе "команда уже не заведена" + +тотальная функция «Closed head» + принимает stand: «Post» + возвращает строка + пример «A closed debt is named with the place of its probe» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci.yml" и «built» равным "") + ожидается "ЗАПИСЬ СТАЛА НЕПРАВДОЙ: «a:check» числится беспробным, а проба стоит в ci.yml." + пусть place равно («Where probed» от stand) + соединить ["ЗАПИСЬ СТАЛА НЕПРАВДОЙ: «", (stand.«name»), "» числится беспробным, а ", place, "."] по "" + +тотальная функция «Closed tail» + возвращает строка + обеспечивает «назван тот, кто обязан убрать запись» результат содержит "обязан тот, кто закрыл" + соединить ["\n Долг закрыт — убрать запись из ", («Debt ledger»), " обязан тот, кто закрыл."] по "" + +тотальная функция «Closed word» + принимает stand: «Post» + возвращает строка + соединить [(«Closed head» от stand), («Closed tail»)] по "" + +тотальная функция «Troubles of» + принимает stands: список «Post», entries: список «Entry» + возвращает список строки + пример «A ledger that names every debt has no troubles» + дано stands равно [(запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "")] + дано entries равно [(запись «Entry» с «guard» равным "a:check" и «reason» равным "дорог")] + ожидается пустой список + пусть written равно (отобразить entries как entry → entry.«guard») + пусть debt равно (отобразить («In debt» от stands) как stand → stand.«name») + пусть fresh равно («Sorted» от (отфильтровать debt где name → не («Holds» от written и name))) + пусть closed равно («Sorted» от (отфильтровать written где name → не («Holds» от debt и name))) + пусть front равно (отобразить fresh как name → («New word» от name)) + «Joined» от front и (отобразить closed как name → («Closed word» от («Post named» от name и stands))) + +тотальная функция «Agreed word» + принимает stands: список «Post» + возвращает строка + пример «The debt that the ledger knows whole is told by its count» + дано stands равно [(запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "")] + ожидается "сторожа без пробы порчи: 1, все названы в ведомости — сходится" + пусть debt равно (к строке (длина («In debt» от stands))) + соединить ["сторожа без пробы порчи: ", debt, ", все названы в ведомости — сходится"] по "" + +тотальная функция «Judgement» + принимает stands: список «Post», troubles: список строки + возвращает «Продолжение» + пример «A ledger that knows every debt ends the work» + дано stands равно [(запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "")] + дано troubles равно пустой список + ожидается вариант «Конец работы» с значение равным "сторожа без пробы порчи: 1, все названы в ведомости — сходится" + если (длина troubles) равен 0 + то вариант «Конец работы» с значение равным («Agreed word» от stands) + иначе вариант «Провал» с код равным "FLANG_FORGERY_PROBE_DEBT" и сообщение равным (соединить troubles по "\n") + +примечание "── ПОРЧА В ПАМЯТИ: ПЯТЬ СТОРОН ────────────────────────────────────────────" + +примечание "ПРИБОР, КОТОРЫЙ СТЕРЕЖЁТ НАЛИЧИЕ ПРОБ, ОБЯЗАН НЕСТИ ПРОБУ ТЕМ БОЛЕЕ. Порча" +примечание "идёт над уже прочитанными ведомостью и переписью: ни один файл дерева не" +примечание "трогается, временный каталог не заводится, откатывать нечего даже если прогон" +примечание "убьют на середине." + +примечание "Пять сторон покрывают оба конца сверки и сам признак пробы:" +примечание " нулевая — перепись как она есть, бед быть не должно;" +примечание " первая — из ведомости вынута первая запись: долг вырос, его не назвали;" +примечание " вторая — в ведомость вписан сторож, у которого проба ЕСТЬ: запись — неправда;" +примечание " третья — заведён сторож, которого никто не зовёт и в ведомости его нет;" +примечание " четвёртая — у первого позванного сторожа проба ОТНЯТА: он обязан стать долгом." + +примечание "КОДЫ ПЕРЕВЁРНУТЫ: код 1 — подлог пойман на всех пяти сторонах; код 0 — сверка" +примечание "промолчала хотя бы на одной либо порча не собралась. Оба случая красят шаг." + +тотальная функция «Side made» + принимает name: строка, says: строка, stands: список «Post», entries: список «Entry» + возвращает «Side» + запись «Side» с «name» равным name и «says» равным says и «stands» равным stands и «entries» равным entries + +тотальная функция «First entry» + принимает entries: список «Entry» + возвращает строка + пример «The first record of the ledger is named» + дано entries равно [(запись «Entry» с «guard» равным "a:check" и «reason» равным "дорог")] + ожидается "a:check" + пример «Of an empty ledger nothing is named» + дано entries равно пустой список + ожидается "" + разбор entries + случай пусто + то "" + случай голова и хвост + то голова.«guard» + +тотальная функция «Without entry» + принимает entries: список «Entry», name: строка + возвращает список «Entry» + обеспечивает «записей не стало больше» (длина результат) не больше (длина entries) + пример «The named record leaves the ledger» + дано entries равно [(запись «Entry» с «guard» равным "a:check" и «reason» равным "дорог")] + дано name равно "a:check" + ожидается пустой список + отфильтровать entries где entry → не ((entry.«guard») равен name) + +тотальная функция «Extra entry» + принимает entries: список «Entry», name: строка + возвращает список «Entry» + обеспечивает «записей стало на одну больше» (длина результат) равен ((длина entries) плюс 1) + пример «A record about a probed guard joins the ledger» + дано entries равно пустой список + дано name равно "a:check" + ожидается [(запись «Entry» с «guard» равным "a:check" и «reason» равным "подлог: этого стерегут пробой")] + добавить (запись «Entry» с «guard» равным name и «reason» равным "подлог: этого стерегут пробой") к entries + +тотальная функция «First probed» + принимает stands: список «Post» + возвращает строка + пример «The first guard with a called probe is named» + дано stands равно [(запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "")] + ожидается "a:check" + пример «Without a probed guard nothing is named» + дано stands равно пустой список + ожидается "" + разбор («Probed» от stands) + случай пусто + то "" + случай голова и хвост + то голова.«name» + +тотальная функция «Unprobed one» + принимает stand: «Post», name: строка + возвращает «Post» + пример «The named guard loses its probe» + дано stand равно (запись «Post» с «name» равным "a:check" и «file» равным "ci" и «built» равным "") + дано name равно "a:check" + ожидается (запись «Post» с «name» равным "a:check" и «file» равным "" и «built» равным "") + если (stand.«name») равен name + то «Post made» от (stand.«name») и "" и (stand.«built») + иначе stand + +тотальная функция «Unprobed» + принимает stands: список «Post», name: строка + возвращает список «Post» + обеспечивает «сторожей столько же» (длина результат) равен (длина stands) + отобразить stands как stand → («Unprobed one» от stand и name) + +тотальная функция «Extra guard» + принимает stands: список «Post» + возвращает список «Post» + обеспечивает «сторожей стало на одного больше» (длина результат) равен ((длина stands) плюс 1) + пример «A guard nobody calls and nobody probes joins the census» + дано stands равно пустой список + ожидается [(запись «Post» с «name» равным "forged:check" и «file» равным "" и «built» равным "")] + добавить («Post made» от "forged:check" и "" и "") к stands + +тотальная функция «Side text» + принимает stands: список «Post», entries: список «Entry» + возвращает строка + пусть told равно (отобразить stands как stand → соединить [(stand.«name»), "|", (stand.«file»)] по "") + пусть kept равно (отобразить entries как entry → entry.«guard») + соединить [(соединить told по "\n"), "\n--\n", (соединить kept по "\n")] по "" + +тотальная функция «Title zero» + возвращает строка + "сторона нулевая: перепись как она есть, бед быть не должно" + +тотальная функция «Title one» + возвращает строка + "сторона первая: первая запись вынута из ведомости" + +тотальная функция «Title two» + возвращает строка + "сторона вторая: в ведомость вписан сторож, у которого проба есть" + +тотальная функция «Title three» + возвращает строка + "сторона третья: заведён сторож без зова и без пробы, в ведомости его нет" + +тотальная функция «Title four» + возвращает строка + "сторона четвёртая: у первого позванного сторожа проба отнята" + +тотальная функция «Sides of» + принимает stands: список «Post», entries: список «Entry» + возвращает список «Side» + пусть dropped равно («Without entry» от entries и («First entry» от entries)) + пусть added равно («Extra entry» от entries и («First probed» от stands)) + пусть taken равно («Unprobed» от stands и («First probed» от stands)) + пусть zero равно («Side made» от («Title zero») и "" и stands и entries) + пусть one равно («Side made» от («Title one») и "НОВЫЙ БЕЗ ПРОБЫ" и stands и dropped) + пусть two равно («Side made» от («Title two») и "ЗАПИСЬ СТАЛА НЕПРАВДОЙ" и stands и added) + пусть three равно («Side made» от («Title three») и "НОВЫЙ БЕЗ ПРОБЫ" и («Extra guard» от stands) и entries) + пусть four равно («Side made» от («Title four») и "НОВЫЙ БЕЗ ПРОБЫ" и taken и entries) + [zero, one, two, three, four] + +тотальная функция «Says it» + принимает found: список строки, says: строка + возвращает признак + пример «The words of the side stand among the troubles» + дано found равно ["НОВЫЙ БЕЗ ПРОБЫ: «a:check» заведён"] + дано says равно "НОВЫЙ БЕЗ ПРОБЫ" + ожидается да + пример «No trouble says it» + дано found равно пустой список + дано says равно "НОВЫЙ БЕЗ ПРОБЫ" + ожидается нет + (длина (отфильтровать found где trouble → trouble содержит says)) больше 0 + +тотальная функция «Side answered» + принимает says: строка, found: список строки + возвращает признак + пример «The clean side wants no trouble at all» + дано says равно "" + дано found равно пустой список + ожидается да + пример «A forged side wants its own words» + дано says равно "НОВЫЙ БЕЗ ПРОБЫ" + дано found равно ["НОВЫЙ БЕЗ ПРОБЫ: «a:check» заведён"] + ожидается да + пример «A forged side that raised nothing has not answered» + дано says равно "НОВЫЙ БЕЗ ПРОБЫ" + дано found равно пустой список + ожидается нет + если says равен "" + то (длина found) равен 0 + иначе «Says it» от found и says + +тотальная функция «Side shown» + принимает name: строка, says: строка, found: список строки + возвращает строка + пример «A shown side names its words and how many troubles it raised» + дано name равно "одна" + дано says равно "НОВЫЙ БЕЗ ПРОБЫ" + дано found равно ["НОВЫЙ БЕЗ ПРОБЫ: «a:check»"] + ожидается "── одна ──\nбед 1, сказано «НОВЫЙ БЕЗ ПРОБЫ»" + соединить ["── ", name, " ──\nбед ", (к строке (длина found)), ", сказано «", says, "»"] по "" + +тотальная функция «Side fault» + принимает name: строка, says: строка, found: список строки + возвращает строка + пример «A side that stayed silent is named» + дано name равно "одна" + дано says равно "НОВЫЙ БЕЗ ПРОБЫ" + дано found равно пустой список + ожидается "ПОДЛОГ НЕ ПОЙМАН — одна: ждали слова «НОВЫЙ БЕЗ ПРОБЫ», а бед найдено 0" + соединить ["ПОДЛОГ НЕ ПОЙМАН — ", name, ": ждали слова «", says, "», а бед найдено ", + (к строке (длина found))] по "" + +тотальная функция «Not assembled» + принимает name: строка + возвращает строка + пример «A forgery that changed nothing is named» + дано name равно "одна" + ожидается "ПОДЛОГ НЕ СОБРАЛСЯ — одна: перепись не изменилась, проверять ею нечего" + соединить ["ПОДЛОГ НЕ СОБРАЛСЯ — ", name, ": перепись не изменилась, проверять ею нечего"] по "" + +тотальная функция «Side judged» + принимает side: «Side», found: список строки + возвращает строка + если («Side answered» от (side.«says») и found) + то «Side shown» от (side.«name») и (side.«says») и found + иначе «Side fault» от (side.«name») и (side.«says») и found + +тотальная функция «Side assembled» + принимает side: «Side», base: строка + возвращает признак + пусть own равно («Side text» от (side.«stands») и (side.«entries»)) + если (side.«says») равен "" то да иначе (не (own равен base)) + +тотальная функция «Side words» + принимает side: «Side», base: строка + возвращает строка + пусть found равно («Troubles of» от (side.«stands») и (side.«entries»)) + если не («Side assembled» от side и base) + то «Not assembled» от (side.«name») + иначе «Side judged» от side и found + +тотальная функция «Forgery words» + принимает stands: список «Post», entries: список «Entry» + возвращает список строки + пусть base равно («Side text» от stands и entries) + отобразить («Sides of» от stands и entries) как side → («Side words» от side и base) + +тотальная функция «Is fault» + принимает word: строка + возвращает признак + пример «A side that was not shown is a fault» + дано word равно "ПОДЛОГ НЕ ПОЙМАН — одна" + ожидается да + пример «A forgery that did not assemble is a fault» + дано word равно "ПОДЛОГ НЕ СОБРАЛСЯ — одна" + ожидается да + пример «A shown side is not a fault» + дано word равно "── одна ──\nбед 1" + ожидается нет + (word начинается с "ПОДЛОГ НЕ ПОЙМАН") или (word начинается с "ПОДЛОГ НЕ СОБРАЛСЯ") + +тотальная функция «Caught word» + возвращает строка + "подлог пойман: все пять сторон показаны прогоном, ни один файл дерева не тронут." + +тотальная функция «Hollow word» + возвращает строка + "ПРОБА ХОЛОСТА: сверка промолчала там, где обязана была покраснеть." + +тотальная функция «Forgery verdict» + принимает stands: список «Post», entries: список «Entry» + возвращает «Продолжение» + пусть words равно («Forgery words» от stands и entries) + пусть faults равно (отфильтровать words где word → («Is fault» от word)) + пусть caught равно (соединить («Joined» от words и [(«Caught word»)]) по "\n\n") + пусть hollow равно (соединить («Joined» от words и [(«Hollow word»)]) по "\n\n") + если (длина faults) равен 0 + то вариант «Провал» с код равным "FLANG_FORGERY_PROBE_PODLOG" и сообщение равным caught + иначе вариант «Конец работы» с значение равным hollow + +примечание "── ПОРУЧЕНИЯ И ХОД РАБОТЫ ─────────────────────────────────────────────────" + +тотальная функция «Flows folder» + возвращает строка + обеспечивает «работы CI лежат у GitHub» результат содержит ".github/workflows" + "../../.github/workflows" + +тотальная функция «Flows order» + возвращает «Поручение» + пример «The folder of workflows is listed» + ожидается (вариант «Перечислить каталог» с путь равным "../../.github/workflows") + вариант «Перечислить каталог» с путь равным («Flows folder») + +тотальная функция «Flow order» + принимает name: строка + возвращает «Поручение» + пример «A workflow is read by its name» + дано name равно "ci.yml" + ожидается (вариант «Прочитать файл» с путь равным "../../.github/workflows/ci.yml") + вариант «Прочитать файл» с путь равным (соединить [(«Flows folder»), "/", name] по "") + +тотальная функция «Ledger order» + возвращает «Поручение» + пример «The ledger is read by an order, not by a grep» + ожидается (вариант «Прочитать файл» с путь равным "../../scripts/ledgers/guards-without-forgery-probe.json") + вариант «Прочитать файл» с путь равным (соединить ["../../", («Debt ledger»)] по "") + +тотальная функция «Settings order» + возвращает «Поручение» + пример «The settings file is read whole» + ожидается (вариант «Прочитать файл» с путь равным "../../.flangrc") + вариант «Прочитать файл» с путь равным "../../.flangrc" + +тотальная функция «Step on» + принимает order: «Поручение», stage: «Stage» + возвращает «Продолжение» + вариант «Сделать» с поручение равным order и потом равным stage + +тотальная функция «Nothing read» + принимает what: строка, code: строка, message: строка + возвращает «Продолжение» + пусть word равно (соединить [what, " не читается — перепись неполна и потому не считается: ", message] по "") + вариант «Не проверено» с код равным code и сообщение равным word + +тотальная функция «Wrong reply» + принимает what: строка + возвращает «Продолжение» + пример «A reply nobody asked for stops the census» + дано what равно "текст workflow" + ожидается вариант «Провал» с код равным "FLANG_IO_ORDER" и сообщение равным "ждали текст workflow" + вариант «Провал» с код равным "FLANG_IO_ORDER" и сообщение равным (соединить ["ждали ", what] по "") + +тотальная функция «Is flow» + принимает name: строка + возвращает признак + пример «A workflow is named by its ending» + дано name равно "ci.yml" + ожидается да + пример «A page is not a workflow» + дано name равно "README.md" + ожидается нет + «Ends with» от name и ".yml" + +тотальная функция «Ask settings» + принимает mode: строка, spots: список «Spot», entries: список «Entry» + возвращает «Продолжение» + пусть stage равно (вариант «Reading settings» с mode равным mode и spots равным spots и entries равным entries) + «Step on» от («Settings order») и stage + +тотальная функция «Ask debt» + принимает mode: строка, spots: список «Spot» + возвращает «Продолжение» + пусть stage равно (вариант «Reading the debt» с mode равным mode и spots равным spots) + если mode равен "list" + то «Ask settings» от mode и spots и (пустой список) + иначе «Step on» от («Ledger order») и stage + +тотальная функция «Ask flow» + принимает mode: строка, pending: список строки, spots: список «Spot», name: строка + возвращает «Продолжение» + пусть stage равно (вариант «Reading a flow» с mode равным mode и pending равным pending и spots равным spots) + «Step on» от («Flow order» от name) и stage + +тотальная функция «Reading on» + принимает mode: строка, pending: список строки, spots: список «Spot» + возвращает «Продолжение» + разбор pending + случай пусто + то «Ask debt» от mode и spots + случай голова и хвост + то «Ask flow» от mode и pending и spots и голова + +тотальная функция «After the folder» + принимает mode: строка, reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Пока ничего» + то «Step on» от («Flows order») и (вариант «Listing flows» с mode равным mode) + случай вариант «Перечислено» с имена как names + то «Reading on» от mode и (отфильтровать names где name → («Is flow» от name)) и (пустой список) + случай вариант «Сбой» с код как code и сообщение как message + то «Nothing read» от "каталог .github/workflows" и code и message + случай любое + то «Wrong reply» от "список каталога workflow" + +тотальная функция «After a flow read» + принимает mode: строка, pending: список строки, spots: список «Spot», reply: «Отклик» + возвращает «Продолжение» + разбор pending + случай пусто + то «Wrong reply» от "имя workflow, которого никто не спрашивал" + случай голова и хвост + то «After one flow» от mode и (голова) и хвост и spots и reply + +тотальная функция «After one flow» + принимает mode: строка, name: строка, rest: список строки, spots: список «Spot», reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Прочитано» с содержимое как text + то «Reading on» от mode и rest и («Joined» от spots и («Spots of» от name и text)) + случай вариант «Сбой» с код как code и сообщение как message + то «Nothing read» от (соединить [".github/workflows/", name] по "") и code и message + случай любое + то «Wrong reply» от "текст workflow" + +тотальная функция «No ledger» + принимает code: строка + возвращает «Продолжение» + пусть word равно (соединить ["ведомости ", («Debt ledger»), " нет — сверять не с чем"] по "") + вариант «Не проверено» с код равным code и сообщение равным word + +тотальная функция «Or census» + принимает mode: строка, spots: список «Spot», code: строка + возвращает «Продолжение» + если mode равен "census" + то «Ask settings» от mode и spots и (пустой список) + иначе «No ledger» от code + +тотальная функция «After debt» + принимает mode: строка, spots: список «Spot», reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Прочитано» с содержимое как text + то «Ask settings» от mode и spots и («Entries of» от text) + случай вариант «Сбой» с код как code и сообщение как message + то «Or census» от mode и spots и code + случай любое + то «Wrong reply» от "текст ведомости" + +тотальная функция «Told» + принимает mode: строка, stands: список «Post», entries: список «Entry» + возвращает «Продолжение» + пусть names равно (отобразить («In debt» от stands) как stand → stand.«name») + если mode равен "list" + то вариант «Конец работы» с значение равным (соединить names по "\n") + иначе вариант «Конец работы» с значение равным («Census» от stands и entries) + +тотальная функция «Or spoken» + принимает mode: строка, stands: список «Post», entries: список «Entry» + возвращает «Продолжение» + если mode равен "forgery" + то «Forgery verdict» от stands и entries + иначе «Told» от mode и stands и entries + +тотальная функция «Judged» + принимает mode: строка, stands: список «Post», entries: список «Entry» + возвращает «Продолжение» + если mode равен "check" + то «Judgement» от stands и («Troubles of» от stands и entries) + иначе «Or spoken» от mode и stands и entries + +тотальная функция «After settings» + принимает mode: строка, spots: список «Spot», entries: список «Entry», reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Прочитано» с содержимое как text + то «Judged» от mode и («Posts of» от («Commands of settings» от text) и spots) и entries + случай вариант «Сбой» с код как code и сообщение как message + то «Nothing read» от ".flangrc" и code и message + случай любое + то «Wrong reply» от "текст .flangrc" + +тотальная функция «Onward» + принимает stage: «Stage», reply: «Отклик» + возвращает «Продолжение» + разбор stage + случай вариант «Listing flows» с mode как mode + то «After the folder» от mode и reply + случай вариант «Reading a flow» с mode как mode и pending как pending и spots как spots + то «After a flow read» от mode и pending и spots и reply + случай вариант «Reading the debt» с mode как mode и spots как spots + то «After debt» от mode и spots и reply + случай вариант «Reading settings» с mode как mode и spots как spots и entries как entries + то «After settings» от mode и spots и entries и reply + +тотальная функция «Start check» + возвращает «Stage» + пример «The check compares the census with the ledger» + ожидается вариант «Listing flows» с mode равным "check" + вариант «Listing flows» с mode равным "check" + +тотальная функция «Start census» + возвращает «Stage» + пример «The census prints every count» + ожидается вариант «Listing flows» с mode равным "census" + вариант «Listing flows» с mode равным "census" + +тотальная функция «Start list» + возвращает «Stage» + пример «The list names the guards in debt only» + ожидается вариант «Listing flows» с mode равным "list" + вариант «Listing flows» с mode равным "list" + +тотальная функция «Start forgery» + возвращает «Stage» + пример «The forgery walks the same census» + ожидается вариант «Listing flows» с mode равным "forgery" + вариант «Listing flows» с mode равным "forgery" + +план «Check» + состояние «Stage» + начинает с «Start check» + обрабатывает «Onward» + +план «Census» + состояние «Stage» + начинает с «Start census» + обрабатывает «Onward» + +план «List» + состояние «Stage» + начинает с «Start list» + обрабатывает «Onward» + +план «Forgery» + состояние «Stage» + начинает с «Start forgery» + обрабатывает «Onward» + +тотальная функция «Объявление короткой команды forgery-probe:check» + возвращает строка + "bootstrap/flang io --plan Check — сторожа без пробы порчи сходятся с ведомостью в обе стороны" + +тотальная функция «Объявление короткой команды forgery-probe:census» + возвращает строка + "bootstrap/flang io --plan Census — перепись проб порчи целиком, код всегда 0" + +тотальная функция «Объявление короткой команды forgery-probe:list» + возвращает строка + "bootstrap/flang io --plan List — только имена беспробных, по одному в строке" + +тотальная функция «Объявление короткой команды forgery-probe:forgery» + возвращает строка + "bootstrap/flang io --plan Forgery — пять порч переписи в памяти краснят сверку, код 1" diff --git a/scripts/guards/guards-without-forgery-probe.sh b/scripts/guards/guards-without-forgery-probe.sh deleted file mode 100755 index 193e9a673..000000000 --- a/scripts/guards/guards-without-forgery-probe.sh +++ /dev/null @@ -1,275 +0,0 @@ -#!/bin/sh -# SPDX-FileCopyrightText: 2026 Digitable (Marat Zimnurov) -# SPDX-License-Identifier: BSD-2-Clause -# -# У КАКИХ СТОРОЖЕЙ НЕТ ПРОБЫ ПОРЧИ — поимённо, прибором, а не рукой. -# -# sh scripts/guards/guards-without-forgery-probe.sh # перепись целиком -# sh scripts/guards/guards-without-forgery-probe.sh --check # сверка с ведомостью, код 1 при расхождении -# sh scripts/guards/guards-without-forgery-probe.sh --список # только имена беспробных, по одному в строке -# -# ── Зачем ─────────────────────────────────────────────────────────────────── -# СТОРОЖ, КОТОРОГО НЕЛЬЗЯ ПОКРАСИТЬ, НЕОТЛИЧИМ ОТ ВЫКЛЮЧЕННОГО. За одни сутки -# 5 сентября 2026 эта порода поймана четыре раза, и ни разу прибором — всякий -# раз случайно: -# -# · `target-words:check` ПРОВЕРЯЛ ПУСТОТУ. Подделку, на которой он стоит, -# заменили тривиальным модулем без единого занятого слова — сторож остался -# зелёным и написал «занятые слова экранированы (8 из 8)». Раздел 1 не -# делал ничего, и сказать об этом было некому (задача 3223). -# · Шесть проверок чекера (`checker.c:1199`) НЕ ОТРАБАТЫВАЛИ НИ РАЗУ: они -# читают исходник по привязке `пример строка N`, а записи корпуса её не -# несут — напечатаны двоичным постарше (задача 8690). -# · Проба под правило 9999 ЛЕЖАЛА В ДЕРЕВЕ, а `run.sh` её не звал — -# сторож без зовущего (задача 9999). -# · Две пробы порчи у разных работников НЕ СОБРАЛИСЬ: правка не изменила -# файл, сторож честно остался зелёным, и заметно это было только по тому, -# что числа не сдвинулись (задачи 7855, 9751). -# -# Общее у всех четырёх — беспроверочная вера в то, что проверка работает. -# Прибор `who-calls-the-guards.sh` отвечает на вопрос «кого CI зовёт»; этот -# отвечает на второй, без которого первый мало стоит: «а показано ли, что -# позванный вообще способен покраснеть». -# -# ── Что считается пробой порчи ────────────────────────────────────────────── -# Проба — это то, что ЛОМАЕТ проверяемое и требует, чтобы сторож на этом -# покраснел. В дереве проба бывает ПОСТРОЕНА и отдельно — ПОЗВАНА, и путать -# эти два состояния нельзя: построенная, но никем не званная проба не -# срабатывает никогда, ровно как сторож без зовущего. -# -# ПРОБА ПОСТРОЕНА — в дереве есть парная команда `X:forgery` или `X:corrupt` -# рядом со сторожем `X:check`: -# "codes:check" … flang/scripts/code-guard.fscript --plan 'Коды целы' -# "codes:forgery" … flang/scripts/code-guard.fscript --plan 'Подлог кода' -# Такая команда портит вход изнутри сторожа: он не зависит от номеров строк -# и портит ровно то, что сторож смотрит. Лучший вид пробы. -# -# ПРОБА ПОЗВАНА — в теле `run:` какого-нибудь workflow стоит вызов сторожа -# В УСЛОВИИ `if`, и в том же теле есть `exit 1`: -# if sh scripts/guards/seed-knows-type-words-guard.sh --подлог; then exit 1; fi -# либо, для внешней порчи, — с правкой файла и откатом: -# sed -i '5s/|[0-9]*$/|9999/' "$podlog" -# if bootstrap/flang run-script proven:check; then git checkout -- "$podlog"; exit 1; fi -# Признак один и тот же и от вида порчи не зависит: шаг падает ровно -# тогда, когда сторож промолчал. -# -# Прибор считает оба и печатает раздельно. В долг («без пробы») попадает тот, -# у кого НЕТ НИ ОДНОГО из двух. -# -# ── Чего этот прибор НЕ говорит ───────────────────────────────────────────── -# Он НЕ говорит, что проба хороша. Проба бывает холостой: правка не собралась -# (строка съехала — `sed` смолчал), или испорчено не то, что сторож смотрит. -# Такую пробу прибор считает существующей, потому что отличить её от рабочей -# он не может — для этого надо прогнать сторожа с порчей и без. Это делает -# сама проба в CI; здесь считается только ЕЁ НАЛИЧИЕ. -# -# Отсюда же ловушка, о которой стоит знать: внешняя проба прибита к НОМЕРУ -# СТРОКИ. Съедет строка — `sed` смолчит, файл останется цел, сторож честно -# останется зелёным, и шаг покраснеет со словами «сторож промолчал», хотя -# виноват подлог. Поэтому у внешних проб в `ci.yml` стоит отдельная защита -# «ПОДЛОГ НЕ СОБРАЛСЯ» (сравнение файла до и после правки), и всякая новая -# внешняя проба обязана её нести. Прибор наличие этой защиты НЕ проверяет — -# это работа для следующего. -# -# ── Ведомость, а не запрет ────────────────────────────────────────────────── -# Беспробных сторожей больше половины; правило «беспробных быть не должно» -# красило бы CI всегда, а вечно красный сторож — это выключенный сторож. -# Поэтому `--check` сверяет с ведомостью `scripts/ledgers/guards-without-forgery-probe.json` -# В ОБЕ СТОРОНЫ, как заведено у сторожа ключей (flang/scripts/cli-keys-debt.json) -# и у переписи зова (scripts/ledgers/uncalled-guards.json): -# · беспробный, которого в ведомости НЕТ, — красно: появился новый долг; -# · запись, у которой проба УЖЕ есть, — тоже красно: долг закрыт, запись -# стала неправдой, и убрать её обязан тот, кто долг закрыл. -set -eu - -KOREN=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd) -cd "$KOREN" - -VEDOMOST=scripts/ledgers/guards-without-forgery-probe.json -REZHIM=${1:-} - -LC_ALL=C.UTF-8 python3 - "$REZHIM" "$VEDOMOST" <<'PY' -import glob, io, json, os, re, sys - -rezhim, vedomost = sys.argv[1], sys.argv[2] - -try: - import yaml -except ImportError: - print("нет модуля yaml — поставить: pip install pyyaml", file=sys.stderr) - sys.exit(3) - -SCRIPT_LINE = re.compile(r'^[ \t]*script\.([^\s=]+)[ \t]*=[ \t]*(\S.*?)[ \t\r]*$', re.M) -yarlyki = dict(SCRIPT_LINE.findall(io.open(".flangrc", encoding="utf-8").read())) - -storozha = sorted(i for i in yarlyki if i.endswith(":check")) - -# ── Тела `run:` целиком, а не построчно ───────────────────────────────────── -# Проба — конструкция из нескольких строк: порча, условие, откат. Резать её на -# строки значит потерять связь между вызовом и `exit 1`. -def tela_run(uzel, kuda): - if isinstance(uzel, dict): - for klyuch, znachenie in uzel.items(): - if klyuch == "run" and isinstance(znachenie, str): - kuda.append(znachenie) - else: - tela_run(znachenie, kuda) - elif isinstance(uzel, list): - for znachenie in uzel: - tela_run(znachenie, kuda) - -tela = [] -for fajl in sorted(glob.glob(".github/workflows/*.yml")): - # Сломанный workflow — не повод падать трассировкой, но и молча пропустить - # его нельзя: сторожа, чьи пробы он держит, стали бы «беспробными», и - # сверка покраснела бы, назвав не ту причину. - try: - derevo = yaml.safe_load(io.open(fajl, encoding="utf-8")) - except yaml.YAMLError as beda: - print(f"{fajl} не разбирается как YAML — перепись неполна и потому" - f" не считается:\n {beda}", file=sys.stderr) - sys.exit(3) - sobrano = [] - tela_run(derevo, sobrano) - for telo in sobrano: - tela.append((os.path.basename(fajl), telo)) - -# ── Признак пробы: вызов в условии `if`, и в том же теле `exit 1` ─────────── -ZOV_PO_IMENI = re.compile(r"bootstrap/flang run-script\s+([^\s;&|`\"')]+)") -PUT = re.compile(r"[\w./-]+\.(?:flang|fscript|mjs|sh|js)") -# Список запускающих снят с дерева тем же способом, что в переписи зова: путь, -# УПОМЯНУТЫЙ в строке, ещё не вызов — он бывает доводом echo, телом heredoc, -# целью перенаправления. Вызовом он считается, только если перед ним стоит -# запускающий. -ZAPUSKAYUSCHIE = {"sh", "bash", "io", "node", "python3", "python", - "check", "emit", "run", "--test", "--proof"} - -def zovy_v_stroke(stroka, puti_storozhey): - """Имена сторожей, которых зовёт эта строка — по имени и по файлу.""" - nashli = set() - for sovpalo in ZOV_PO_IMENI.finditer(stroka): - if sovpalo.group(1) in puti_storozhey["po_imeni"]: - nashli.add(sovpalo.group(1)) - slova = stroka.split() - for nomer, slovo in enumerate(slova): - slovo = slovo.strip("\"'`();&|") - if slovo not in puti_storozhey["po_fajlu"]: - continue - pered = slova[nomer - 1].strip("\"'`();&|") if nomer else None - if pered is None or pered in ZAPUSKAYUSCHIE: - nashli.update(puti_storozhey["po_fajlu"][slovo]) - return nashli - -# Разложение «путь файла → какие сторожа за ним стоят». Один файл бывает за -# двумя командами (у сторожа с ключом и без), поэтому значение — множество. -po_imeni = set(storozha) -po_fajlu = {} -for imya in storozha: - for put in PUT.findall(yarlyki[imya]): - po_fajlu.setdefault(put, set()).add(imya) -puti = {"po_imeni": po_imeni, "po_fajlu": po_fajlu} - -with_probe, where_probe = {}, {} -for fajl, telo in tela: - if "exit 1" not in telo: - continue # шаг не падает — требования покраснеть нет - for stroka in telo.split("\n"): - golaya = stroka.strip() - if golaya.startswith("#"): - continue # комментарий оболочки - # Вызов обязан стоять В УСЛОВИИ: `if <вызов>; then … exit 1`. - # Голый вызов в теле шага — это рабочий прогон, а не проба. - if not (golaya.startswith("if ") or golaya.startswith("elif ")): - continue - for imya in zovy_v_stroke(golaya, puti): - with_probe.setdefault(imya, (fajl, golaya[:70])) - -# ── Проба, ПОСТРОЕННАЯ короткой командой: `X:forgery` или `X:corrupt` рядом с `X:check` ─ -# Приставка берётся отбрасыванием последней доли имени: у «codes:check» это -# «codes», у «word:occupancy:check» — «word:occupancy». Так парность видна и у -# составных имён. -postroena = {} -for imya in storozha: - pristavka = imya.rsplit(":", 1)[0] - for hvost in ("forgery", "corrupt"): - parnyj = f"{pristavka}:{hvost}" - if parnyj in yarlyki: - postroena[imya] = parnyj - break - -# ── Долг: у кого проба НЕ ПОКАЗАНА ────────────────────────────────────────── -# Задача 1389 говорит «ПОКАЗАНО, что он краснеет». Показывает прогон, а не -# наличие: построенная, но никем не званная проба не срабатывает никогда и -# показывает ровно столько же, сколько её отсутствие. Поэтому в долг идут оба -# рода, а построенность отмечается причиной — она говорит, что доделать дёшево. -without_probe = [i for i in storozha if i not in with_probe] - -if rezhim == "--список": - for imya in without_probe: - print(imya) - sys.exit(0) - -if rezhim != "--check": - prichiny = {} - if os.path.exists(vedomost): - prichiny = {k: v for k, v in json.load(io.open(vedomost, encoding="utf-8")).items() - if not k.startswith("//")} - tolko_postroena = sorted(i for i in postroena if i not in with_probe) - print("ПЕРЕПИСЬ ПРОБ ПОРЧИ: у кого показано, что он краснеет\n") - print(f" сторожей в дереве {len(storozha)}") - print(f" ПРОБА ПОЗВАНА (CI требует красноты) {len(with_probe)}") - print(f" проба построена, но НЕ позвана {len(tolko_postroena)}") - print(f" ПРОБА НЕ ПОКАЗАНА (долг) {len(without_probe)}") - print("\nПРОБА ПОЗВАНА, и где стоит:\n") - for imya in sorted(with_probe): - fajl, stroka = with_probe[imya] - istochnik = postroena.get(imya, "порча внешняя, в самом шаге") - print(f" {imya:30} {fajl:12} {istochnik}") - if tolko_postroena: - print("\nПРОБА ПОСТРОЕНА, НО НИКТО ЕЁ НЕ ЗОВЁТ" - " — она не срабатывает никогда:\n") - for imya in tolko_postroena: - print(f" {imya:30} команда {postroena[imya]}") - print("\nДОЛГ — проба не показана, поимённо:\n") - for imya in without_probe: - prichina = prichiny.get(imya, "причина в ведомости не названа") - if imya in postroena: - prichina = f"проба ПОСТРОЕНА командой {postroena[imya]}, но её не зовут" - print(f" {imya:30} {prichina[:80]}") - print("\nСверка с ведомостью — тем же прибором:" - "\n sh scripts/guards/guards-without-forgery-probe.sh --check") - sys.exit(0) - -# ── Сверка с ведомостью в обе стороны ─────────────────────────────────────── -if not os.path.exists(vedomost): - print(f"ведомости {vedomost} нет — сверять не с чем", file=sys.stderr) - sys.exit(3) - -zapisano = json.load(io.open(vedomost, encoding="utf-8")) -zapisano = {k: v for k, v in zapisano.items() if not k.startswith("//")} - -novye = [i for i in without_probe if i not in zapisano] # долг вырос -zakrytye = [i for i in zapisano if i not in without_probe] # долг закрыт - -if not novye and not zakrytye: - print(f"сторожа без пробы порчи: {len(without_probe)}," - " все названы в ведомости — сходится") - sys.exit(0) - -for imya in sorted(novye): - print(f"НОВЫЙ БЕЗ ПРОБЫ: «{imya}» заведён, но ни один шаг CI не требует," - f" чтобы он покраснел на порче, и в {vedomost} его нет.", file=sys.stderr) - print(" Либо построить пробу, либо записать в ведомость с причиной:" - " сторож без пробы неотличим от выключенного.", file=sys.stderr) -for imya in sorted(zakrytye): - if imya in with_probe: - fajl, _ = with_probe[imya] - poyasnenie = f"проба стоит в {fajl}" - else: - poyasnenie = "команда уже не заведена" - print(f"ЗАПИСЬ СТАЛА НЕПРАВДОЙ: «{imya}» числится беспробным," - f" а {poyasnenie}.", file=sys.stderr) - print(f" Долг закрыт — убрать запись из {vedomost} обязан тот, кто закрыл.", - file=sys.stderr) -sys.exit(1) -PY diff --git a/scripts/guards/proved-share-vs-tree.fscript b/scripts/guards/proved-share-vs-tree.fscript new file mode 100644 index 000000000..0d3f76c76 --- /dev/null +++ b/scripts/guards/proved-share-vs-tree.fscript @@ -0,0 +1,1267 @@ +модуль «Proved share vs tree» + +примечание "СВЕРКА ВЕДОМОСТИ ДОКАЗАННОГО С ДЕРЕВОМ. Зовут тремя ярлыками:" +примечание " bootstrap/flang run-script proved-share-tree:check сверка, код 1 при беде" +примечание " bootstrap/flang run-script proved-share-tree:numbers только итоги, код 0" +примечание " bootstrap/flang run-script proved-share-tree:forgery четыре стороны порчи описи" + +примечание "ЗАЧЕМ. scripts/ledgers/proved-share-ledger.txt — опись, из которой берут числа" +примечание "для Г7 и для доли доказанного. Прибора, который снимал бы её заново и сверял с" +примечание "деревом, в репозитории НЕ БЫЛО: числа 13 347 и 13 399 ходили по документам" +примечание "разовым проходом, который в дерево не переехал. Порода та же, что в задачах 7298" +примечание "(сторожей считали рукой, и счёт был неверен в обе стороны) и 7855 (прибор" +примечание "кругооборота лежит во времянке)." + +примечание "ЧТО СВЕРЯЕТСЯ ТОЧНО, А ЧТО ТОЛЬКО ДАТИРУЕТСЯ. Разница не косметическая." +примечание "ЗНАМЕНАТЕЛЬ («написано», «без приговора») считается ПО ИСХОДНИКУ — это строки" +примечание "«обеспечивает», «утверждение», «требует», «закон». Двоичный для него не нужен," +примечание "счёт точен, и расхождение с описью есть ОШИБКА ОПИСИ здесь и сейчас." +примечание "ЧИСЛИТЕЛЬ («доказано», «сетка», «объявлено») — приговор ядра. Чтобы снять его" +примечание "заново, надо прогнать двоичный по каждому файлу; на ядре доказательств это часы" +примечание "и десятки гигабайт памяти. Прибор его НЕ пересчитывает и не делает вида, что" +примечание "пересчитал. Он сверяет md5 исходника и тем ДАТИРУЕТ строку: разошёлся md5 —" +примечание "приговор в строке относится к файлу, которого уже нет." + +примечание "СВЕРЯЕТСЯ В ОБЕ СТОРОНЫ, по образцу flang/scripts/cli-keys-debt.json:" +примечание " · файл дерева несёт обязательства, а строки в описи нет — красно;" +примечание " · строка описи есть, а файла в дереве нет — красно;" +примечание " · строка описи есть, а обязательств в файле не осталось — красно;" +примечание " · «написано» в описи не сходится со счётом по исходнику — красно;" +примечание " · md5 разошёлся, а «написано» сошлось — НЕ красно: это протухший приговор," +примечание " он печатается числом и ждёт того, кто перемерит." + +примечание "ДВЕ ФОРМЫ ОБЯЗАТЕЛЬСТВА, И ПЕРВАЯ РЕДАКЦИЯ ЗНАЛА ОДНУ. Кроме голого" +примечание "«обеспечивает» язык пишет обязательство с квантором, и имён за «для всех» —" +примечание "список (ADR-0026 К2/К6/К5). Третья форма — «утверждение» от края (К3b)." +примечание "Все три стоят в одном образце grep, и сумма по дереву сходится с описью." + +примечание "ЧЕМ ЭТОТ ФАЙЛ ОТЛИЧАЕТСЯ ОТ ПРЕЖНЕГО НА ОБОЛОЧКЕ. До 4 октября 2026 то же" +примечание "сверял scripts/guards/proved-share-vs-tree.sh, 139 строк. Довод переписи «место" +примечание "вызова — хук до сборки двоичного» УСТАРЕЛ: с задачи 1219 хук сам стал планом" +примечание "(.githooks/pre-push зовёт bootstrap/flang io .githooks/pre-push.fscript), и" +примечание "двоичный к этому часу уже собран. Перенос снял две вещи, которых у оболочки" +примечание "быть не могло. ПЕРВОЕ: разбор описи и счёт по строке проверяются ПРИМЕРАМИ на" +примечание "месте, а не прогоном на всём дереве. ВТОРОЕ: порча описи идёт В ПАМЯТИ, файл" +примечание "дерева не трогается и откатывать нечего, тогда как проба оболочки правила опись" +примечание "на диске и возвращала её копией. Слово согласия и каждая беда списаны у" +примечание "прежнего сторожа ЗНАК В ЗНАК: прогон обоих на этом дереве 4 октября 2026 дал" +примечание "одни и те же строки." + +примечание "ЧЕГО ЗДЕСЬ НЕТ. «Доказано», «сетка», «объявлено» не пересчитываются — их" +примечание "снимает scripts/ledgers/take-proof-ledger.fscript по одному файлу, и это часы." +примечание "Расхождение кода возврата названо: у плана нет кода 5, «описи нет» и «это не" +примечание "рабочая копия» отвечают кодом 3, а у оболочки был 5." + +объект «Count» + «path»: строка + «number»: число + +объект «Row» + «path»: строка + «written»: число + «unjudged»: число + +объект «Side» + «name»: строка + «rows»: список строки + «says»: строка + +тип «Step» + вариант «Listing» содержит mode: строка + вариант «Counting written» содержит mode: строка, paths: список строки + вариант «Counting unjudged» содержит mode: строка, written: список «Count» + вариант «Hashing» содержит mode: строка, rows: список «Row» + вариант «Reading ledger» содержит mode: строка, rows: список «Row», hashes: строка + +примечание "── РАЗБОР СТРОК ────────────────────────────────────────────────────────────" + +тотальная функция «Joined» от «Kind» + принимает front: список «Kind», back: список «Kind» + возвращает список «Kind» + пример «The back list follows the front one» + дано front равно ["one"] + дано back равно ["two", "three"] + ожидается ["one", "two", "three"] + свёртка back начиная с front как joined и piece → добавить piece к joined + +тотальная функция «Lines of» + принимает text: строка + возвращает список строки + пример «Empty lines are dropped» + дано text равно "раз\n\nдва\n" + ожидается ["раз", "два"] + отфильтровать (разделить text по "\n") где line → не (line равен "") + +тотальная функция «Piece number» + принимает which: число, pieces: список строки + возвращает строка + обеспечивает «куска за краем списка нет» если which больше (длина pieces) то (результат равен "") иначе да + пример «The second piece» + дано which равно 2 + дано pieces равно ["a", "b"] + ожидается "b" + пример «Beyond the edge there is nothing» + дано which равно 9 + дано pieces равно ["a"] + ожидается "" + пример «Before the first piece there is nothing» + дано which равно 0 + дано pieces равно пустой список + ожидается "" + пусть outside равно ((which больше (длина pieces)) или (which меньше 1)) + если outside то "" иначе (элемент which в pieces) + +тотальная функция «Last of» + принимает pieces: список строки + возвращает строка + пример «The last piece is taken» + дано pieces равно ["a", "b", "33"] + ожидается "33" + пример «Of nothing nothing is taken» + дано pieces равно пустой список + ожидается "" + «Piece number» от (длина pieces) и pieces + +тотальная функция «Without last» + принимает pieces: список строки + возвращает список строки + обеспечивает «список не длиннее прежнего» (длина результат) не больше (длина pieces) + пример «The last piece is dropped» + дано pieces равно ["a", "b", "33"] + ожидается ["a", "b"] + пример «Of one piece nothing is left» + дано pieces равно ["33"] + ожидается пустой список + разбор pieces + случай пусто + то пустой список + случай голова и хвост + то если (длина хвост) равен 0 + то пустой список + иначе приписать голова к («Without last» от хвост) + +тотальная функция «Digit kept» + принимает acc: признак, sign: строка + возвращает признак + пример «A digit keeps the answer» + дано acc равно да + дано sign равно "7" + ожидается да + пример «Another sign breaks the answer» + дано acc равно да + дано sign равно "a" + ожидается нет + acc и притом ("0123456789" содержит sign) + +тотальная функция «Is digits» + принимает text: строка + возвращает признак + пример «A count is digits» + дано text равно "33" + ожидается да + пример «A cross is not digits» + дано text равно "×" + ожидается нет + пример «An empty text is not digits» + дано text равно "" + ожидается нет + пусть digits равно (свёртка (разложить text на символы) начиная с да как acc и sign → «Digit kept» от acc и sign) + ((длина text) больше 0) и притом digits + +тотальная функция «Number of» + принимает text: строка + возвращает число + обеспечивает «что не цифры — то ноль» если («Is digits» от text) то да иначе (результат равен 0) + пример «Digits become a number» + дано text равно "33" + ожидается 33 + пример «A cross counts as nothing» + дано text равно "×" + ожидается 0 + если («Is digits» от text) то (к числу text) иначе 0 + +тотальная функция «Is measured» + принимает text: строка + возвращает признак + пример «A number is a measured field» + дано text равно "19" + ожидается да + пример «A cross is not measured» + дано text равно "×" + ожидается нет + пример «A dash is not measured» + дано text равно "-" + ожидается нет + не ((text равен "×") или (text равен "-")) + +тотальная функция «Measured number» + принимает text: строка + возвращает число + обеспечивает «неизмеренного поля не складывают» если («Is measured» от text) то да иначе (результат равен 0) + пример «A measured field gives its number» + дано text равно "19" + ожидается 19 + пример «An unmeasured field gives nothing» + дано text равно "×" + ожидается 0 + если («Is measured» от text) то («Number of» от text) иначе 0 + +тотальная функция «Without front» + принимает text: строка, front: строка + возвращает строка + пример «The front of the path is cut off» + дано text равно "../../scripts/one.flang" + дано front равно "../../" + ожидается "scripts/one.flang" + пример «A text no longer than the front stays as it is» + дано text равно "../../" + дано front равно "../../" + ожидается "../../" + если (text начинается с front) и притом ((длина text) больше (длина front)) + то подстрока text с ((длина front) плюс 1) по (длина text) + иначе text + +примечание "── МЕТКИ: НАБОР СТРОК ДЛЯ ПОИСКА ПО ЦЕЛОМУ КУСКУ ──────────────────────────" + +тотальная функция «Marked» + принимает pieces: список строки + возвращает строка + пример «Every piece stands on a line of its own» + дано pieces равно ["one", "two"] + ожидается "\none\ntwo\n" + соединить ["\n", (соединить pieces по "\n"), "\n"] по "" + +тотальная функция «Is marked» + принимает marks: строка, piece: строка + возвращает признак + пример «A whole piece is found» + дано marks равно "\na.flang\nb.flang\n" + дано piece равно "b.flang" + ожидается да + пример «A part of a piece is not found» + дано marks равно "\nscripts/one.flang\n" + дано piece равно "one.flang" + ожидается нет + marks содержит (соединить ["\n", piece, "\n"] по "") + +тотальная функция «Keyed» + принимает path: строка + возвращает строка + пример «The key of a path stands between a line break and a tab» + дано path равно "a.flang" + ожидается "\na.flang\t" + соединить ["\n", path, "\t"] по "" + +тотальная функция «At mark» + принимает index: строка, key: строка + возвращает строка + пример «What stands behind the mark is taken» + дано index равно "\na.flang\t3\nb.flang\t7\n" + дано key равно "\nb.flang\t" + ожидается "7" + пример «Without the mark nothing is taken» + дано index равно "\na.flang\t3\n" + дано key равно "\nb.flang\t" + ожидается "" + пусть pieces равно (разделить index по key) + если (длина pieces) меньше 2 + то "" + иначе голова (разделить («Piece number» от 2 и pieces) по "\n") + +примечание "── СЧЁТ ПО ДЕРЕВУ: ВЫВОД grep -c РАЗБИРАЕТСЯ В ПАРЫ «ПУТЬ — ЧИСЛО» ────────" + +тотальная функция «Count of line» + принимает line: строка, front: строка + возвращает «Count» + пример «The count stands after the last colon» + дано line равно "../../a.flang:33" + дано front равно "../../" + ожидается (запись «Count» с «path» равным "a.flang" и «number» равным 33) + пример «A colon inside the path stays in the path» + дано line равно "../../a:b.flang:7" + дано front равно "../../" + ожидается (запись «Count» с «path» равным "a:b.flang" и «number» равным 7) + пусть pieces равно (разделить line по ":") + пусть whole равно (соединить («Without last» от pieces) по ":") + пусть path равно («Without front» от whole и front) + запись «Count» с «path» равным path и «number» равным («Number of» от («Last of» от pieces)) + +тотальная функция «Counts of» + принимает text: строка, front: строка + возвращает список «Count» + пример «Every line of the output is a pair» + дано text равно "../../a.flang:3\n../../b.flang:0\n" + дано front равно "../../" + ожидается [(запись «Count» с «path» равным "a.flang" и «number» равным 3), + (запись «Count» с «path» равным "b.flang" и «number» равным 0)] + отобразить («Lines of» от text) как line → («Count of line» от line и front) + +тотальная функция «Count mark» + принимает count: «Count» + возвращает строка + пример «A pair is marked by its path» + дано count равно (запись «Count» с «path» равным "a.flang" и «number» равным 3) + ожидается "a.flang\t3" + соединить [(count.«path»), "\t", (к строке (count.«number»))] по "" + +тотальная функция «Count index» + принимает counts: список «Count» + возвращает строка + пример «The index holds every pair» + дано counts равно [(запись «Count» с «path» равным "a.flang" и «number» равным 3)] + ожидается "\na.flang\t3\n" + «Marked» от (отобразить counts как count → («Count mark» от count)) + +тотальная функция «Number at» + принимает index: строка, path: строка + возвращает число + пример «The number of the path is taken from the index» + дано index равно "\na.flang\t3\n" + дано path равно "a.flang" + ожидается 3 + пример «A path outside the index carries nothing» + дано index равно "\na.flang\t3\n" + дано path равно "b.flang" + ожидается 0 + «Number of» от («At mark» от index и («Keyed» от path)) + +тотальная функция «Row of count» + принимает count: «Count», unjudged: строка + возвращает «Row» + пример «A row takes its two counts» + дано count равно (запись «Count» с «path» равным "a.flang" и «number» равным 3) + дано unjudged равно "\na.flang\t2\n" + ожидается (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 2) + пусть laws равно («Number at» от unjudged и (count.«path»)) + запись «Row» с «path» равным (count.«path») и «written» равным (count.«number») и «unjudged» равным laws + +тотальная функция «Carries obligations» + принимает row: «Row» + возвращает признак + пример «A file with a postcondition carries obligations» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0) + ожидается да + пример «A file with a precondition only carries obligations too» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 0 и «unjudged» равным 1) + ожидается да + пример «An empty file carries none» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 0 и «unjudged» равным 0) + ожидается нет + ((row.«written») больше 0) или ((row.«unjudged») больше 0) + +тотальная функция «Rows of» + принимает written: список «Count», unjudged: строка + возвращает список «Row» + пример «Only the files that carry obligations become rows» + дано written равно [(запись «Count» с «path» равным "a.flang" и «number» равным 3), + (запись «Count» с «path» равным "b.flang" и «number» равным 0)] + дано unjudged равно "\na.flang\t0\nb.flang\t0\n" + ожидается [(запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0)] + пусть all равно (отобразить written как count → («Row of count» от count и unjudged)) + отфильтровать all где row → («Carries obligations» от row) + +тотальная функция «Row paths» + принимает rows: список «Row» + возвращает строка + пример «The paths of the rows stand one on a line» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0)] + ожидается "\na.flang\n" + «Marked» от (отобразить rows как row → row.«path») + +примечание "── md5 ИСХОДНИКОВ: ВЫВОД md5sum РАЗБИРАЕТСЯ В ПАРЫ «ПУТЬ — ОТПЕЧАТОК» ─────" + +тотальная функция «Hash mark» + принимает line: строка, front: строка + возвращает строка + пример «The sum stands before the path» + дано line равно "0eb8181532ae602de4c212cbde33749e ../../a.flang" + дано front равно "../../" + ожидается "a.flang\t0eb8181532ae602de4c212cbde33749e" + пусть whole равно (соединить (хвост (разделить line по " ")) по " ") + соединить [(«Without front» от whole и front), "\t", (голова (разделить line по " "))] по "" + +тотальная функция «Hash index» + принимает text: строка, front: строка + возвращает строка + пример «The index holds every sum» + дано text равно "aa ../../a.flang\n" + дано front равно "../../" + ожидается "\na.flang\taa\n" + «Marked» от (отобразить («Lines of» от text) как line → («Hash mark» от line и front)) + +примечание "── ОПИСЬ: «md5|написано|доказано|сетка|объявлено|без приговора|путь» ───────" + +тотальная функция «Is ledger line» + принимает text: строка + возвращает признак + пример «A row of the ledger carries bars» + дано text равно "aa|1|1|0|0|0|a.flang" + ожидается да + пример «A note of the ledger is not a row» + дано text равно "// опись" + ожидается нет + пример «A line without bars is not a row» + дано text равно "опись" + ожидается нет + (не (text начинается с "//")) и притом (text содержит "|") + +тотальная функция «Field» + принимает which: число, line: строка + возвращает строка + пример «The second field is what is written» + дано which равно 2 + дано line равно "aa|33|19|5|1|0|a.flang" + ожидается "33" + пример «The seventh field is the path» + дано which равно 7 + дано line равно "aa|33|19|5|1|0|a.flang" + ожидается "a.flang" + «Piece number» от which и (разделить line по "|") + +тотальная функция «Path of» + принимает line: строка + возвращает строка + пример «The path of a row is its seventh field» + дано line равно "aa|33|19|5|1|0|a.flang" + ожидается "a.flang" + «Field» от 7 и line + +тотальная функция «Ledger rows of» + принимает text: строка + возвращает список строки + пример «Notes are dropped and rows are kept» + дано text равно "// опись\naa|1|1|0|0|0|a.flang\n" + ожидается ["aa|1|1|0|0|0|a.flang"] + отфильтровать («Lines of» от text) где line → («Is ledger line» от line) + +тотальная функция «Ledger mark» + принимает line: строка + возвращает строка + пример «A row is found by its path and is kept whole» + дано line равно "aa|1|1|0|0|0|a.flang" + ожидается "a.flang\taa|1|1|0|0|0|a.flang" + соединить [(«Path of» от line), "\t", line] по "" + +тотальная функция «Ledger index» + принимает lines: список строки + возвращает строка + пример «Every row is found by its path» + дано lines равно ["aa|1|1|0|0|0|a.flang"] + ожидается "\na.flang\taa|1|1|0|0|0|a.flang\n" + «Marked» от (отобразить lines как line → («Ledger mark» от line)) + +тотальная функция «Line at» + принимает index: строка, path: строка + возвращает строка + пример «The row of the path is taken whole» + дано index равно "\na.flang\taa|1|1|0|0|0|a.flang\n" + дано path равно "a.flang" + ожидается "aa|1|1|0|0|0|a.flang" + пример «A path outside the index gives nothing» + дано index равно "\na.flang\taa|1|1|0|0|0|a.flang\n" + дано path равно "b.flang" + ожидается "" + «At mark» от index и («Keyed» от path) + +примечание "── ИТОГИ ───────────────────────────────────────────────────────────────────" + +тотальная функция «Tree written» + принимает rows: список «Row» + возвращает число + пример «The postconditions of the tree are summed» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0)] + ожидается 3 + свёртка rows начиная с 0 как total и row → total плюс (row.«written») + +тотальная функция «Tree unjudged» + принимает rows: список «Row» + возвращает число + пример «The preconditions and the laws of the tree are summed» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 0 и «unjudged» равным 2)] + ожидается 2 + свёртка rows начиная с 0 как total и row → total плюс (row.«unjudged») + +тотальная функция «Summed field» + принимает which: число, lines: список строки + возвращает число + пример «Only measured fields are summed» + дано which равно 3 + дано lines равно ["aa|1|7|0|0|0|a.flang", "bb|1|×|×|×|0|b.flang"] + ожидается 7 + свёртка lines начиная с 0 как total и line → total плюс («Measured number» от («Field» от which и line)) + +тотальная функция «Judged» + принимает lines: список строки + возвращает число + пример «A row with a verdict is judged» + дано lines равно ["aa|1|7|0|0|0|a.flang", "bb|1|×|×|×|0|b.flang"] + ожидается 1 + длина (отфильтровать lines где line → («Is measured» от («Field» от 3 и line))) + +тотальная функция «Hash at» + принимает hashes: строка, path: строка + возвращает строка + пример «The sum of the file is taken from the index» + дано hashes равно "\na.flang\taa\n" + дано path равно "a.flang" + ожидается "aa" + «At mark» от hashes и («Keyed» от path) + +тотальная функция «Is stale» + принимает row: «Row», index: строка, hashes: строка + возвращает признак + пример «A row whose sum has moved is stale» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0) + дано index равно "\na.flang\taa|1|7|0|0|0|a.flang\n" + дано hashes равно "\na.flang\tbb\n" + ожидается да + пример «A row whose sum stands is fresh» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0) + дано index равно "\na.flang\taa|1|7|0|0|0|a.flang\n" + дано hashes равно "\na.flang\taa\n" + ожидается нет + пусть line равно («Line at» от index и (row.«path»)) + пусть moved равно (не ((«Field» от 1 и line) равен («Hash at» от hashes и (row.«path»)))) + (не (line равен "")) и притом moved + +тотальная функция «Stale lines» + принимает rows: список «Row», index: строка, hashes: строка + возвращает список строки + пример «The stale rows of the ledger are named» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0)] + дано index равно "\na.flang\taa|1|7|0|0|0|a.flang\n" + дано hashes равно "\na.flang\tbb\n" + ожидается ["aa|1|7|0|0|0|a.flang"] + пусть stale равно (отфильтровать rows где row → («Is stale» от row и index и hashes)) + отобразить stale как row → («Line at» от index и (row.«path»)) + +примечание "── БЕДЫ ────────────────────────────────────────────────────────────────────" + +тотальная функция «Missing word» + принимает row: «Row» + возвращает строка + пример «A file without a row of its own is named with its count» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0) + ожидается "НЕТ СТРОКИ: a.flang несёт 3 обязательств, а в описи его нет" + соединить ["НЕТ СТРОКИ: ", (row.«path»), " несёт ", (к строке (row.«written»)), + " обязательств, а в описи его нет"] по "" + +тотальная функция «Extra word» + принимает path: строка + возвращает строка + пример «A row without a file of its own is named» + дано path равно "a.flang" + ожидается "ЛИШНЯЯ СТРОКА: a.flang есть в описи, а в дереве обязательств не несёт" + соединить ["ЛИШНЯЯ СТРОКА: ", path, " есть в описи, а в дереве обязательств не несёт"] по "" + +тотальная функция «Differing word» + принимает row: «Row», written: строка + возвращает строка + пример «Both counts are named» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0) + дано written равно "4" + ожидается "«НАПИСАНО» НЕ СХОДИТСЯ: a.flang — 4 против 3" + соединить ["«НАПИСАНО» НЕ СХОДИТСЯ: ", (row.«path»), " — ", written, " против ", + (к строке (row.«written»))] по "" + +тотальная функция «Is missing» + принимает row: «Row», index: строка + возвращает признак + пример «A file the ledger does not know is missing» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0) + дано index равно "\nb.flang\tbb|1|1|0|0|0|b.flang\n" + ожидается да + («Line at» от index и (row.«path»)) равен "" + +тотальная функция «Is differing» + принимает row: «Row», index: строка + возвращает признак + пример «A measured count that does not meet the source is differing» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0) + дано index равно "\na.flang\taa|4|1|0|0|0|a.flang\n" + ожидается да + пример «An unmeasured count is not differing» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0) + дано index равно "\na.flang\taa|×|1|0|0|0|a.flang\n" + ожидается нет + пусть line равно («Line at» от index и (row.«path»)) + пусть written равно («Field» от 2 и line) + пусть apart равно (не ((«Number of» от written) равен (row.«written»))) + пусть off равно ((«Is measured» от written) и притом apart) + (не (line равен "")) и притом off + +тотальная функция «Missing troubles» + принимает rows: список «Row», index: строка + возвращает список строки + пример «Every file without a row is named» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0)] + дано index равно "\nb.flang\tbb|1|1|0|0|0|b.flang\n" + ожидается ["НЕТ СТРОКИ: a.flang несёт 1 обязательств, а в описи его нет"] + пусть found равно (отфильтровать rows где row → («Is missing» от row и index)) + отобразить found как row → («Missing word» от row) + +тотальная функция «Extra troubles» + принимает lines: список строки, paths: строка + возвращает список строки + пример «Every row without a file is named» + дано lines равно ["aa|1|1|0|0|0|a.flang"] + дано paths равно "\nb.flang\n" + ожидается ["ЛИШНЯЯ СТРОКА: a.flang есть в описи, а в дереве обязательств не несёт"] + пусть found равно (отфильтровать lines где line → не («Is marked» от paths и («Path of» от line))) + отобразить found как line → («Extra word» от («Path of» от line)) + +тотальная функция «Differing of» + принимает row: «Row», index: строка + возвращает строка + пример «The word names what the ledger says» + дано row равно (запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0) + дано index равно "\na.flang\taa|4|1|0|0|0|a.flang\n" + ожидается "«НАПИСАНО» НЕ СХОДИТСЯ: a.flang — 4 против 3" + «Differing word» от row и («Field» от 2 и («Line at» от index и (row.«path»))) + +тотальная функция «Differing troubles» + принимает rows: список «Row», index: строка + возвращает список строки + пример «Every count that does not meet the source is named» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 3 и «unjudged» равным 0)] + дано index равно "\na.flang\taa|4|1|0|0|0|a.flang\n" + ожидается ["«НАПИСАНО» НЕ СХОДИТСЯ: a.flang — 4 против 3"] + пусть found равно (отфильтровать rows где row → («Is differing» от row и index)) + отобразить found как row → («Differing of» от row и index) + +тотальная функция «Troubles of» + принимает rows: список «Row», lines: список строки + возвращает список строки + пример «A ledger that meets the tree has no troubles» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0)] + дано lines равно ["aa|1|1|0|0|0|a.flang"] + ожидается пустой список + пусть index равно («Ledger index» от lines) + пусть missing равно («Missing troubles» от rows и index) + пусть extra равно («Extra troubles» от lines и («Row paths» от rows)) + пусть front равно («Joined» от missing и extra) + «Joined» от front и («Differing troubles» от rows и index) + +тотальная функция «Summary word» + принимает rows: список «Row», lines: список строки + возвращает строка + пример «The troubles are counted apart» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0)] + дано lines равно ["bb|1|1|0|0|0|b.flang"] + ожидается "бед 2: нет строки 1, лишних 1, «написано» не сходится 0" + пусть index равно («Ledger index» от lines) + пусть missing равно (длина («Missing troubles» от rows и index)) + пусть extra равно (длина («Extra troubles» от lines и («Row paths» от rows))) + пусть differing равно (длина («Differing troubles» от rows и index)) + соединить ["бед ", (к строке ((missing плюс extra) плюс differing)), ": нет строки ", (к строке missing), + ", лишних ", (к строке extra), ", «написано» не сходится ", (к строке differing)] по "" + +примечание "── ОТЧЁТ ───────────────────────────────────────────────────────────────────" + +тотальная функция «Report» + принимает rows: список «Row», lines: список строки, hashes: строка + возвращает строка + пусть index равно («Ledger index» от lines) + пусть stale равно («Stale lines» от rows и index и hashes) + пусть judged равно («Judged» от lines) + соединить ["ПОЛ ДОКАЗАННОГО: опись против дерева\n\n", + " ЗНАМЕНАТЕЛЬ — счёт по исходнику, точен\n", + " файлов с обязательствами в дереве ", (к строке (длина rows)), "\n", + " строк в описи ", (к строке (длина lines)), "\n", + " «обеспечивает» по дереву ", (к строке («Tree written» от rows)), "\n", + " «написано» по описи ", (к строке («Summed field» от 2 и lines)), "\n", + " «требует»+«закон» по дереву ", (к строке («Tree unjudged» от rows)), "\n", + " «без приговора» по описи ", (к строке («Summed field» от 6 и lines)), "\n", + "\n ЧИСЛИТЕЛЬ — приговор ядра, прибор его НЕ пересчитывает\n", + " файлов с ведомостью ", (к строке judged), "\n", + " файлов без ведомости (× или прочерк) ", (к строке ((длина lines) минус judged)), "\n", + " доказано ", (к строке («Summed field» от 3 и lines)), "\n", + " на сетке ", (к строке («Summed field» от 4 и lines)), "\n", + " объявлено ", (к строке («Summed field» от 5 и lines)), "\n", + "\n ПРОТУХЛОСТЬ — md5 исходника разошёлся с описью\n", + " строк протухло ", (к строке (длина stale)), " из ", + (к строке (длина lines)), "\n", + " из них несут «доказано» ", (к строке («Summed field» от 3 и stale)), "\n", + " и «написано» ", (к строке («Summed field» от 2 и stale))] по "" + +примечание "── ПРИГОВОР ────────────────────────────────────────────────────────────────" + +тотальная функция «Verdict» + принимает report: строка, troubles: список строки, summary: строка + возвращает «Продолжение» + пример «A ledger that meets the tree ends the work» + дано report равно "ПОЛ ДОКАЗАННОГО" + дано troubles равно пустой список + дано summary равно "бед 0" + ожидается вариант «Конец работы» с значение равным "ПОЛ ДОКАЗАННОГО\n\nопись сходится с деревом" + пусть agreed равно (соединить [report, "\n\nопись сходится с деревом"] по "") + пусть red равно (соединить [report, "\n\n", (соединить troubles по "\n"), "\n\n", summary] по "") + если (длина troubles) равен 0 + то вариант «Конец работы» с значение равным agreed + иначе вариант «Провал» с код равным "FLANG_PROVED_SHARE_RAZOSHLIS" и сообщение равным red + +тотальная функция «Judge» + принимает mode: строка, rows: список «Row», lines: список строки, hashes: строка + возвращает «Продолжение» + пусть report равно («Report» от rows и lines и hashes) + пусть troubles равно («Troubles of» от rows и lines) + пусть summary равно («Summary word» от rows и lines) + если mode равен "numbers" + то вариант «Конец работы» с значение равным report + иначе «Verdict» от report и troubles и summary + +примечание "── ПОРЧА ОПИСИ В ПАМЯТИ: ЧЕТЫРЕ СТОРОНЫ ───────────────────────────────────" + +примечание "ФАЙЛ ОПИСИ НЕ ТРОГАЕТСЯ: порча идёт над уже прочитанным списком строк, и" +примечание "откатывать нечего. Это то же решение, что у плана «Подлог» описи дерева" +примечание "(scripts/guards/tree-inventory.fscript): подлог в памяти не оставляет грязи в" +примечание "рабочей копии, если прогон убьют на середине. Проба оболочки правила опись на" +примечание "диске и возвращала её копией — на убитом прогоне опись оставалась порченой." + +примечание "КОДЫ ПЕРЕВЁРНУТЫ, как у пары про опись дерева: код 1 — подлог пойман, сверка" +примечание "жива; код 0 — сверка промолчала хотя бы на одной стороне. Оба случая обязаны" +примечание "красить шаг CI, и шаг написан как «if … then exit 1»." + +тотальная функция «Side made» + принимает name: строка, rows: список строки, says: строка + возвращает «Side» + пример «A side carries its name, its ledger and the words it wants» + дано name равно "одна" + дано rows равно пустой список + дано says равно "" + ожидается (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "") + запись «Side» с «name» равным name и «rows» равным rows и «says» равным says + +тотальная функция «Is bumpable» + принимает line: строка + возвращает признак + пример «A row with a measured count can be bumped» + дано line равно "aa|33|19|5|1|0|a.flang" + ожидается да + пример «A row without a measured count cannot» + дано line равно "aa|×|19|5|1|0|a.flang" + ожидается нет + «Is digits» от («Field» от 2 и line) + +тотальная функция «Bumped line» + принимает line: строка + возвращает строка + пример «The count of the row grows by one» + дано line равно "aa|33|19|5|1|0|a.flang" + ожидается "aa|34|19|5|1|0|a.flang" + пусть pieces равно (разделить line по "|") + пусть grown равно (к строке ((«Number of» от («Field» от 2 и line)) плюс 1)) + пусть rest равно (соединить (хвост (хвост pieces)) по "|") + соединить [(«Piece number» от 1 и pieces), grown, rest] по "|" + +тотальная функция «Bumped» + принимает lines: список строки, which: строка + возвращает список строки + пример «Only the named row grows» + дано lines равно ["aa|33|19|5|1|0|a.flang", "bb|1|1|0|0|0|b.flang"] + дано which равно "a.flang" + ожидается ["aa|34|19|5|1|0|a.flang", "bb|1|1|0|0|0|b.flang"] + отобразить lines как line → (если («Path of» от line) равен which то («Bumped line» от line) иначе line) + +тотальная функция «Dropped» + принимает lines: список строки, which: строка + возвращает список строки + обеспечивает «строк не стало больше» (длина результат) не больше (длина lines) + пример «The named row leaves the ledger» + дано lines равно ["aa|33|19|5|1|0|a.flang", "bb|1|1|0|0|0|b.flang"] + дано which равно "a.flang" + ожидается ["bb|1|1|0|0|0|b.flang"] + отфильтровать lines где line → не ((«Path of» от line) равен which) + +тотальная функция «Ghost line» + возвращает строка + обеспечивает «подложная строка говорит о файле, которого нет» результат содержит "there-is-no-such-file" + "00000000000000000000000000000000|1|×|×|×|0|docs/there-is-no-such-file.flang" + +тотальная функция «Added» + принимает lines: список строки + возвращает список строки + обеспечивает «строк стало на одну больше» (длина результат) равен ((длина lines) плюс 1) + пример «A row about a file that is not there joins the ledger» + дано lines равно ["bb|1|1|0|0|0|b.flang"] + ожидается ["bb|1|1|0|0|0|b.flang", + "00000000000000000000000000000000|1|×|×|×|0|docs/there-is-no-such-file.flang"] + добавить («Ghost line») к lines + +тотальная функция «First path» + принимает rows: список «Row» + возвращает строка + пример «The first row of the tree names its file» + дано rows равно [(запись «Row» с «path» равным "a.flang" и «written» равным 1 и «unjudged» равным 0)] + ожидается "a.flang" + пример «Of no rows no file is named» + дано rows равно пустой список + ожидается "" + разбор rows + случай пусто + то "" + случай голова и хвост + то голова.«path» + +тотальная функция «First bumpable» + принимает lines: список строки + возвращает строка + пример «The first row with a measured count is named» + дано lines равно ["aa|×|19|5|1|0|a.flang", "bb|1|1|0|0|0|b.flang"] + ожидается "b.flang" + пример «Without such a row nothing is named» + дано lines равно ["aa|×|19|5|1|0|a.flang"] + ожидается "" + разбор (отфильтровать lines где line → («Is bumpable» от line)) + случай пусто + то "" + случай голова и хвост + то «Path of» от голова + +тотальная функция «Title zero» + возвращает строка + "сторона нулевая: опись как она есть, бед быть не должно" + +тотальная функция «Title one» + возвращает строка + "сторона первая: «написано» первой мерной строки описи +1" + +тотальная функция «Title two» + возвращает строка + "сторона вторая: строка о первом файле дерева вынута из описи" + +тотальная функция «Title three» + возвращает строка + "сторона третья: в опись вписана строка о файле, которого в дереве нет" + +тотальная функция «Sides of» + принимает rows: список «Row», lines: список строки + возвращает список «Side» + пусть bumped равно («Bumped» от lines и («First bumpable» от lines)) + пусть dropped равно («Dropped» от lines и («First path» от rows)) + пусть zero равно («Side made» от («Title zero») и lines и "") + пусть one равно («Side made» от («Title one») и bumped и "«НАПИСАНО» НЕ СХОДИТСЯ") + пусть two равно («Side made» от («Title two») и dropped и "НЕТ СТРОКИ") + пусть three равно («Side made» от («Title three») и («Added» от lines) и "ЛИШНЯЯ СТРОКА") + [zero, one, two, three] + +тотальная функция «Side shown» + принимает side: «Side», found: список строки + возвращает строка + пример «A shown side names its words and how many troubles it raised» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "НЕТ СТРОКИ") + дано found равно ["НЕТ СТРОКИ: a.flang"] + ожидается "── одна ──\nбед 1, сказано «НЕТ СТРОКИ»" + соединить ["── ", (side.«name»), " ──\nбед ", (к строке (длина found)), ", сказано «", + (side.«says»), "»"] по "" + +тотальная функция «Says it» + принимает found: список строки, telling: строка + возвращает признак + пример «The words of the side stand among the troubles» + дано found равно ["НЕТ СТРОКИ: a.flang несёт 1 обязательств, а в описи его нет"] + дано telling равно "НЕТ СТРОКИ" + ожидается да + пример «No trouble says it» + дано found равно пустой список + дано telling равно "НЕТ СТРОКИ" + ожидается нет + (длина (отфильтровать found где trouble → trouble содержит telling)) больше 0 + +тотальная функция «Side answered» + принимает side: «Side», found: список строки + возвращает признак + пример «The clean side wants no trouble at all» + дано side равно (запись «Side» с «name» равным "нулевая" и «rows» равным пустой список и «says» равным "") + дано found равно пустой список + ожидается да + пример «A forged side wants its own words» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "НЕТ СТРОКИ") + дано found равно ["НЕТ СТРОКИ: a.flang"] + ожидается да + пример «A forged side that raised nothing has not answered» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "НЕТ СТРОКИ") + дано found равно пустой список + ожидается нет + если (side.«says») равен "" + то (длина found) равен 0 + иначе «Says it» от found и (side.«says») + +тотальная функция «Side fault» + принимает side: «Side», found: список строки + возвращает строка + пример «A side that stayed silent is named» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "НЕТ СТРОКИ") + дано found равно пустой список + ожидается "ПОДЛОГ НЕ ПОЙМАН — одна: ждали слова «НЕТ СТРОКИ», а бед найдено 0" + соединить ["ПОДЛОГ НЕ ПОЙМАН — ", (side.«name»), ": ждали слова «", (side.«says»), + "», а бед найдено ", (к строке (длина found))] по "" + +тотальная функция «Side assembled» + принимает side: «Side», lines: список строки + возвращает признак + пример «A forged side differs from the ledger it came from» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным ["y"] и «says» равным "НЕТ СТРОКИ") + дано lines равно ["x"] + ожидается да + пример «A forgery that changed nothing did not assemble» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным ["x"] и «says» равным "НЕТ СТРОКИ") + дано lines равно ["x"] + ожидается нет + пример «The clean side is the ledger itself» + дано side равно (запись «Side» с «name» равным "нулевая" и «rows» равным ["x"] и «says» равным "") + дано lines равно ["x"] + ожидается да + пусть moved равно (не ((соединить (side.«rows») по "\n") равен (соединить lines по "\n"))) + если (side.«says») равен "" то да иначе moved + +тотальная функция «Not assembled» + принимает side: «Side» + возвращает строка + пример «A forgery that changed nothing is named» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "НЕТ СТРОКИ") + ожидается "ПОДЛОГ НЕ СОБРАЛСЯ — одна: опись не изменилась, проверять ею нечего" + соединить ["ПОДЛОГ НЕ СОБРАЛСЯ — ", (side.«name»), + ": опись не изменилась, проверять ею нечего"] по "" + +тотальная функция «Side judged» + принимает side: «Side», found: список строки + возвращает строка + пример «A side that answered is shown» + дано side равно (запись «Side» с «name» равным "одна" и «rows» равным пустой список и «says» равным "НЕТ СТРОКИ") + дано found равно ["НЕТ СТРОКИ: a.flang"] + ожидается "── одна ──\nбед 1, сказано «НЕТ СТРОКИ»" + если («Side answered» от side и found) + то «Side shown» от side и found + иначе «Side fault» от side и found + +тотальная функция «Side words» + принимает side: «Side», rows: список «Row», lines: список строки + возвращает строка + пусть found равно («Troubles of» от rows и (side.«rows»)) + если не («Side assembled» от side и lines) + то «Not assembled» от side + иначе «Side judged» от side и found + +тотальная функция «Forgery words» + принимает rows: список «Row», lines: список строки + возвращает список строки + отобразить («Sides of» от rows и lines) как side → («Side words» от side и rows и lines) + +тотальная функция «Is fault» + принимает word: строка + возвращает признак + пример «A side that was not shown is a fault» + дано word равно "ПОДЛОГ НЕ ПОЙМАН — первая" + ожидается да + пример «A forgery that did not assemble is a fault» + дано word равно "ПОДЛОГ НЕ СОБРАЛСЯ — первая" + ожидается да + пример «A shown side is not a fault» + дано word равно "── первая ──\nбед 1" + ожидается нет + (word начинается с "ПОДЛОГ НЕ ПОЙМАН") или (word начинается с "ПОДЛОГ НЕ СОБРАЛСЯ") + +тотальная функция «Caught word» + возвращает строка + "подлог пойман: все четыре стороны показаны прогоном, опись на диске не тронута." + +тотальная функция «Hollow word» + возвращает строка + "ПРОБА ХОЛОСТА: сверка промолчала там, где обязана была покраснеть." + +тотальная функция «Forgery verdict» + принимает rows: список «Row», lines: список строки + возвращает «Продолжение» + пусть words равно («Forgery words» от rows и lines) + пусть faults равно (отфильтровать words где word → («Is fault» от word)) + пусть caught равно (соединить («Joined» от words и [(«Caught word»)]) по "\n\n") + пусть hollow равно (соединить («Joined» от words и [(«Hollow word»)]) по "\n\n") + если (длина faults) равен 0 + то вариант «Провал» с код равным "FLANG_PROVED_SHARE_PODLOG" и сообщение равным caught + иначе вариант «Конец работы» с значение равным hollow + +примечание "── ПОРУЧЕНИЯ ───────────────────────────────────────────────────────────────" + +тотальная функция «Front» + возвращает строка + обеспечивает «корень дерева стоит двумя шагами выше плана» результат равен "../../" + "../../" + +тотальная функция «Ledger file» + возвращает строка + обеспечивает «опись лежит у ведомостей» результат содержит "scripts/ledgers/" + "../../scripts/ledgers/proved-share-ledger.txt" + +тотальная функция «Git arguments» + возвращает список строки + обеспечивает «кириллические пути не прячутся в кавычки» результат содержит "core.quotepath=false" + ["-C", "../..", "-c", "core.quotepath=false", "ls-files", "*.flang", "*.fscript"] + +тотальная функция «Written pattern» + возвращает строка + обеспечивает «образец знает и квантор, и утверждение» результат содержит "утверждение" + соединить ["^ *(для всех [^ ]+( и [^ ]+)*( для всех [^ ]+( и [^ ]+)*)*( таких что .*)? )?", + "обеспечивает |^утверждение «"] по "" + +тотальная функция «Unjudged pattern» + возвращает строка + обеспечивает «без приговора — предусловие и закон» результат содержит "закон" + "^ *(требует|закон) " + +тотальная функция «Prefixed» + принимает paths: список строки + возвращает список строки + обеспечивает «путей столько же» (длина результат) равен (длина paths) + пример «Every path is taken from the root of the tree» + дано paths равно ["a.flang"] + ожидается ["../../a.flang"] + отобразить paths как path → соединить [(«Front»), path] по "" + +тотальная функция «Git order» + возвращает «Поручение» + пример «The list of the tree is asked of git» + ожидается (вариант «Запустить процесс» с программа равным "git" и аргументы равным ["-C", "../..", + "-c", "core.quotepath=false", "ls-files", "*.flang", "*.fscript"]) + вариант «Запустить процесс» с программа равным "git" и аргументы равным («Git arguments») + +тотальная функция «Grep order» + принимает pattern: строка, paths: список строки + возвращает «Поручение» + пример «The files are counted by one grep over all of them» + дано pattern равно "^закон " + дано paths равно ["a.flang"] + ожидается (вариант «Запустить процесс» с программа равным "grep" и аргументы равным ["-acE", "^закон ", + "../../a.flang"]) + пусть arguments равно («Joined» от ["-acE", pattern] и («Prefixed» от paths)) + вариант «Запустить процесс» с программа равным "grep" и аргументы равным arguments + +тотальная функция «Md5 order» + принимает paths: список строки + возвращает «Поручение» + пример «The sums are taken by one md5sum over all the files» + дано paths равно ["a.flang"] + ожидается (вариант «Запустить процесс» с программа равным "md5sum" и аргументы равным ["../../a.flang"]) + вариант «Запустить процесс» с программа равным "md5sum" и аргументы равным («Prefixed» от paths) + +тотальная функция «Ledger order» + возвращает «Поручение» + пример «The ledger is read by an order, not by a grep» + ожидается (вариант «Прочитать файл» с путь равным "../../scripts/ledgers/proved-share-ledger.txt") + вариант «Прочитать файл» с путь равным («Ledger file») + +тотальная функция «Step on» + принимает order: «Поручение», step: «Step» + возвращает «Продолжение» + вариант «Сделать» с поручение равным order и потом равным step + +примечание "── СЛОВА ОТКАЗА ────────────────────────────────────────────────────────────" + +тотальная функция «Nothing word» + принимает what: строка + возвращает строка + пример «An empty answer of a tool is named» + дано what равно "grep" + ожидается "СВЕРКА НЕ НАЧАТА: grep не назвал ни одной строки — считать нечем" + соединить ["СВЕРКА НЕ НАЧАТА: ", what, " не назвал ни одной строки — считать нечем"] по "" + +тотальная функция «Nothing to count» + принимает what: строка + возвращает «Продолжение» + вариант «Не проверено» с код равным "FLANG_PROVED_SHARE_NECHEM" и сообщение равным («Nothing word» от what) + +тотальная функция «Broken word» + принимает what: строка, code: строка, message: строка + возвращает строка + пример «A tool that did not run is named with its code» + дано what равно "md5sum" + дано code равно "FLANG_IO_DENIED" + дано message равно "нельзя" + ожидается "СВЕРКА НЕ НАЧАТА: md5sum не запустился (FLANG_IO_DENIED): нельзя" + соединить ["СВЕРКА НЕ НАЧАТА: ", what, " не запустился (", code, "): ", message] по "" + +тотальная функция «Broken tool» + принимает what: строка, code: строка, message: строка + возвращает «Продолжение» + пусть word равно («Broken word» от what и code и message) + вариант «Не проверено» с код равным "FLANG_PROVED_SHARE_NECHEM" и сообщение равным word + +тотальная функция «Not a copy» + принимает errors: строка + возвращает «Продолжение» + пусть word равно (соединить ["ни одного файла языка — это не рабочая копия: ", errors] по "") + «Broken tool» от "git ls-files" и "FLANG_PROVED_SHARE_NECHEM" и word + +тотальная функция «Wrong reply» + принимает what: строка + возвращает «Продолжение» + пример «A reply nobody asked for stops the check» + дано what равно "вывод grep" + ожидается вариант «Провал» с код равным "FLANG_IO_ORDER" и сообщение равным "ждали вывод grep" + вариант «Провал» с код равным "FLANG_IO_ORDER" и сообщение равным (соединить ["ждали ", what] по "") + +примечание "── ХОД РАБОТЫ ──────────────────────────────────────────────────────────────" + +тотальная функция «Ask tree» + принимает mode: строка + возвращает «Продолжение» + «Step on» от («Git order») и (вариант «Listing» с mode равным mode) + +тотальная функция «Ask written» + принимает mode: строка, paths: список строки + возвращает «Продолжение» + пусть step равно (вариант «Counting written» с mode равным mode и paths равным paths) + «Step on» от («Grep order» от («Written pattern») и paths) и step + +тотальная функция «Ask unjudged» + принимает mode: строка, written: список «Count», paths: список строки + возвращает «Продолжение» + пусть step равно (вариант «Counting unjudged» с mode равным mode и written равным written) + если (длина written) равен 0 + то «Nothing to count» от "grep" + иначе «Step on» от («Grep order» от («Unjudged pattern») и paths) и step + +тотальная функция «Ask hashes» + принимает mode: строка, rows: список «Row» + возвращает «Продолжение» + пусть step равно (вариант «Hashing» с mode равным mode и rows равным rows) + если (длина rows) равен 0 + то «Nothing to count» от "счёт обязательств" + иначе «Step on» от («Md5 order» от (отобразить rows как row → row.«path»)) и step + +тотальная функция «Ask ledger» + принимает mode: строка, rows: список «Row», hashes: строка + возвращает «Продолжение» + пусть step равно (вариант «Reading ledger» с mode равным mode и rows равным rows и hashes равным hashes) + «Step on» от («Ledger order») и step + +тотальная функция «After tree» + принимает mode: строка, paths: список строки, errors: строка + возвращает «Продолжение» + если (длина paths) равен 0 + то «Not a copy» от errors + иначе «Ask written» от mode и paths + +тотальная функция «After listing» + принимает mode: строка, reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Пока ничего» + то «Ask tree» от mode + случай вариант «Процесс завершён» с код как code и вывод как output и ошибки как errors + то «After tree» от mode и («Lines of» от output) и errors + случай вариант «Сбой» с код как code и сообщение как message + то «Broken tool» от "git ls-files" и code и message + случай любое + то «Wrong reply» от "список файлов дерева" + +тотальная функция «After written» + принимает mode: строка, paths: список строки, reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Процесс завершён» с код как code и вывод как output и ошибки как errors + то «Ask unjudged» от mode и («Counts of» от output и («Front»)) и paths + случай вариант «Сбой» с код как code и сообщение как message + то «Broken tool» от "grep" и code и message + случай любое + то «Wrong reply» от "счёт обязательств" + +тотальная функция «After unjudged» + принимает mode: строка, written: список «Count», reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Процесс завершён» с код как code и вывод как output и ошибки как errors + то «Ask hashes» от mode и («Rows of» от written и («Count index» от («Counts of» от output и («Front»)))) + случай вариант «Сбой» с код как code и сообщение как message + то «Broken tool» от "grep" и code и message + случай любое + то «Wrong reply» от "счёт без приговора" + +тотальная функция «After hashes» + принимает mode: строка, rows: список «Row», reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Процесс завершён» с код как code и вывод как output и ошибки как errors + то «Ask ledger» от mode и rows и («Hash index» от output и («Front»)) + случай вариант «Сбой» с код как code и сообщение как message + то «Broken tool» от "md5sum" и code и message + случай любое + то «Wrong reply» от "отпечатки исходников" + +тотальная функция «Spoken» + принимает mode: строка, rows: список «Row», lines: список строки, hashes: строка + возвращает «Продолжение» + если mode равен "forgery" + то «Forgery verdict» от rows и lines + иначе «Judge» от mode и rows и lines и hashes + +тотальная функция «After ledger» + принимает mode: строка, rows: список «Row», hashes: строка, reply: «Отклик» + возвращает «Продолжение» + разбор reply + случай вариант «Прочитано» с содержимое как text + то «Spoken» от mode и rows и («Ledger rows of» от text) и hashes + случай вариант «Сбой» с код как code и сообщение как message + то «Broken tool» от "опись доказанного" и code и message + случай любое + то «Wrong reply» от "текст описи" + +тотальная функция «Next» + принимает step: «Step», reply: «Отклик» + возвращает «Продолжение» + разбор step + случай вариант «Listing» с mode как mode + то «After listing» от mode и reply + случай вариант «Counting written» с mode как mode и paths как paths + то «After written» от mode и paths и reply + случай вариант «Counting unjudged» с mode как mode и written как written + то «After unjudged» от mode и written и reply + случай вариант «Hashing» с mode как mode и rows как rows + то «After hashes» от mode и rows и reply + случай вариант «Reading ledger» с mode как mode и rows как rows и hashes как hashes + то «After ledger» от mode и rows и hashes и reply + +тотальная функция «Begin check» + возвращает «Step» + пример «The check compares the ledger with the tree» + ожидается вариант «Listing» с mode равным "check" + вариант «Listing» с mode равным "check" + +тотальная функция «Begin numbers» + возвращает «Step» + пример «The numbers are only told» + ожидается вариант «Listing» с mode равным "numbers" + вариант «Listing» с mode равным "numbers" + +тотальная функция «Begin forgery» + возвращает «Step» + пример «The forgery walks the same measurement» + ожидается вариант «Listing» с mode равным "forgery" + вариант «Listing» с mode равным "forgery" + +план «Check» + состояние «Step» + начинает с «Begin check» + обрабатывает «Next» + +план «Numbers» + состояние «Step» + начинает с «Begin numbers» + обрабатывает «Next» + +план «Forgery» + состояние «Step» + начинает с «Begin forgery» + обрабатывает «Next» + +тотальная функция «Объявление короткой команды proved-share-tree:check» + возвращает строка + "bootstrap/flang io --plan Check — опись доказанного сходится с деревом в обе стороны" + +тотальная функция «Объявление короткой команды proved-share-tree:numbers» + возвращает строка + "bootstrap/flang io --plan Numbers — те же числа без приговора, код всегда 0" + +тотальная функция «Объявление короткой команды proved-share-tree:forgery» + возвращает строка + "bootstrap/flang io --plan Forgery — четыре порчи описи в памяти краснят сверку, код 1" diff --git a/scripts/guards/proved-share-vs-tree.sh b/scripts/guards/proved-share-vs-tree.sh deleted file mode 100755 index 038e24b1d..000000000 --- a/scripts/guards/proved-share-vs-tree.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/sh -# СВЕРКА ВЕДОМОСТИ ДОКАЗАННОГО С ДЕРЕВОМ. -# -# ЗАЧЕМ. `scripts/ledgers/proved-share-ledger.txt` — опись, из которой берут числа для -# Г7 и для доли доказанного. Прибора, который снимал бы её заново и сверял с -# деревом, в репозитории НЕ БЫЛО: числа 13 347 и 13 399 ходят по документам -# разовым проходом, который в дерево не переехал. Порода та же, что в задачах -# 7298 (сторожей считали рукой, и счёт был неверен в обе стороны) и 7855 -# (прибор кругооборота лежит во времянке). -# -# ЧТО СВЕРЯЕТСЯ ТОЧНО, А ЧТО ТОЛЬКО ДАТИРУЕТСЯ. Разница не косметическая: -# -# ЗНАМЕНАТЕЛЬ («написано», «без приговора») считается ПО ИСХОДНИКУ — это -# строки `обеспечивает`, `требует`, `закон`. Двоичный для него не нужен, -# счёт точен, и расхождение с описью есть ОШИБКА ОПИСИ здесь и сейчас. -# -# ЧИСЛИТЕЛЬ («доказано», «сетка», «объявлено») — приговор ядра. Чтобы снять -# его заново, надо прогнать двоичный по каждому файлу; на ядре доказательств -# это часы и десятки гигабайт памяти (шапка описи: sets-oracle — 999 с и -# 16,6 ГиБ на один файл). Прибор его НЕ пересчитывает и не делает вида, что -# пересчитал. Он делает другое: сверяет md5 исходника и тем ДАТИРУЕТ строку. -# Разошёлся md5 — приговор в строке относится к файлу, которого уже нет. -# -# СВЕРЯЕТСЯ В ОБЕ СТОРОНЫ, по образцу flang/scripts/cli-keys-debt.json и -# scripts/ledgers/uncalled-guards.json: -# · файл дерева несёт обязательства, а строки в описи нет — красно; -# · строка описи есть, а файла в дереве нет — красно; -# · строка описи есть, а обязательств в файле не осталось — красно; -# · «написано» в описи не сходится со счётом по исходнику — красно; -# · md5 разошёлся, а «написано» сошлось — НЕ красно: это протухший приговор, -# он печатается числом и ждёт того, кто перемерит. -# -# ЗВАТЬ: sh scripts/guards/proved-share-vs-tree.sh сверка, код 1 при беде -# sh scripts/guards/proved-share-vs-tree.sh --числа только итоги, код 0 -set -u -REZHIM=сверка -for d in "$@"; do - case "$d" in - --числа) REZHIM=числа ;; - *) printf 'непонятный ключ: %s (знаю только --числа)\n' "$d" >&2; exit 2 ;; - esac -done -ROOT=$(cd "$(dirname "$0")/../.." && pwd) -cd "$ROOT" || exit 5 -OPIS=scripts/ledgers/proved-share-ledger.txt -[ -f "$OPIS" ] || { printf 'нет описи %s\n' "$OPIS" >&2; exit 5; } -RAB=${FLANG_TMP:-/srv/tmp}/pol-dokazannogo.$$ -mkdir -p "$RAB" || exit 5 -trap 'rm -rf "$RAB"' EXIT INT TERM - -# ── дерево: md5, обеспечивает, требует, закон — по каждому .flang ──────────── -# core.quotepath=false ОБЯЗАТЕЛЕН: без него git отдаёт кириллические пути в -# кавычках с восьмеричными кодами, и прибор молча пропускает 508 файлов из 955. -# Именно на этом первая редакция считала знаменатель по одним латинским именам. -git -c core.quotepath=false ls-files '*.flang' '*.fscript' | while IFS= read -r f; do - [ -f "$f" ] || continue - # grep -c при нуле совпадений печатает 0 И ВЫХОДИТ КОДОМ 1. Поэтому «|| echo 0» - # дописывал бы второй ноль и портил счёт; берём вывод как есть. - # ДВЕ ФОРМЫ ОБЯЗАТЕЛЬСТВА, и первая редакция знала одну. Кроме голого - # «обеспечивает» язык пишет обязательство с квантором: - # для всех элементы обеспечивает «длина неотрицательна» результат не меньше 0 - # Их в дереве 165 в 94 файлах, и 79 файлов несут ТОЛЬКО такую форму — прибор - # считал их пустыми и объявлял их строки в описи лишними. Все 69 «лишних» - # живых файлов оказались этой породы: врал прибор, а не опись. - # ИМЁН ЗА «для всех» — СПИСОК (ADR-0026 К2/К6/К5, 10 сентября 2026): `для всех - # а и б обеспечивает`, вложенное `для всех а для всех б обеспечивает`, - # ограничение `для всех н таких что … обеспечивает`. Прежний образец брал ОДНО - # слово за «для всех», и такое постусловие молча выпадало из знаменателя: - # `tests/families/quantifier/two-names.flang` (три постусловия) считался 2, а не 3. - OB=$(LC_ALL=C.UTF-8 grep -acE '^ *(для всех [^ ]+( и [^ ]+)*( для всех [^ ]+( и [^ ]+)*)*( таких что .*)? )?обеспечивает ' "$f" 2>/dev/null); OB=${OB:-0} - # УТВЕРЖДЕНИЕ БЕЗ ФУНКЦИИ (ADR-0026 К3b, 10 сентября 2026) — тоже обязательство: - # `утверждение «И»` от края. Считается вместе с «обеспечивает» с того же коммита, - # что сверщик переигрывает его доказательство, — знаменатель описи честен ровно - # с того часа, как такое обязательство может быть проверено (решение overagent'а). - ST=$(LC_ALL=C.UTF-8 grep -ac '^утверждение «' "$f" 2>/dev/null); OB=$((OB + ${ST:-0})) - TR=$(LC_ALL=C.UTF-8 grep -ac '^ *требует ' "$f" 2>/dev/null); TR=${TR:-0} - ZA=$(LC_ALL=C.UTF-8 grep -ac '^ *закон ' "$f" 2>/dev/null); ZA=${ZA:-0} - [ "$OB" = 0 ] && [ "$TR" = 0 ] && [ "$ZA" = 0 ] && continue - printf '%s|%s|%s|%s|%s\n' "$(md5sum "$f" | cut -d' ' -f1)" "$OB" "$TR" "$ZA" "$f" -done > "$RAB/derevo" - -LC_ALL=C.UTF-8 grep -av '^//' "$OPIS" | LC_ALL=C.UTF-8 grep -a '|' > "$RAB/opis" - -awk -F'|' -v rezhim="$REZHIM" ' - FILENAME ~ /derevo$/ { - d_md5[$5]=$1; d_ob[$5]=$2; d_tr[$5]=$3; d_za[$5]=$4; d_est[$5]=1; next - } - { - p=$7; o_md5[p]=$1; o_nap[p]=$2; o_dok[p]=$3; o_set[p]=$4; o_obj[p]=$5; o_bez[p]=$6; o_est[p]=1 - strok++ - if($2!="×" && $2!="-") o_nap_sum+=$2 - if($3!="×" && $3!="-"){ o_dok_sum+=$3; s_vedom++ } else bez_vedom++ - if($4!="×" && $4!="-") o_set_sum+=$4 - if($5!="×" && $5!="-") o_obj_sum+=$5 - if($6!="×" && $6!="-") o_bez_sum+=$6 - } - END{ - for(p in d_est){ - d_nap_sum += d_ob[p]; d_bez_sum += d_tr[p]+d_za[p]; d_fajlov++ - if(!(p in o_est)){ net_stroki[p]=d_ob[p]; net_n++; beda++ ; continue } - if(o_nap[p]!="×" && o_nap[p]!="-" && o_nap[p]+0 != d_ob[p]+0){ - raz_nap[p]=o_nap[p]" против "d_ob[p]; raz_n++; beda++ - } - if(o_md5[p]!=d_md5[p]){ prot[p]=1; prot_n++ - if(o_dok[p]!="×" && o_dok[p]!="-") prot_dok+=o_dok[p] - if(o_nap[p]!="×" && o_nap[p]!="-") prot_nap+=o_nap[p] - } - } - for(p in o_est){ - if(!(p in d_est)){ lishn[p]=1; lishn_n++; beda++ } - } - printf "ПОЛ ДОКАЗАННОГО: опись против дерева\n\n" - printf " ЗНАМЕНАТЕЛЬ — счёт по исходнику, точен\n" - printf " файлов с обязательствами в дереве %d\n", d_fajlov - printf " строк в описи %d\n", strok - printf " «обеспечивает» по дереву %d\n", d_nap_sum - printf " «написано» по описи %d\n", o_nap_sum - printf " «требует»+«закон» по дереву %d\n", d_bez_sum - printf " «без приговора» по описи %d\n", o_bez_sum - printf "\n ЧИСЛИТЕЛЬ — приговор ядра, прибор его НЕ пересчитывает\n" - printf " файлов с ведомостью %d\n", s_vedom - printf " файлов без ведомости (× или прочерк) %d\n", bez_vedom - printf " доказано %d\n", o_dok_sum - printf " на сетке %d\n", o_set_sum - printf " объявлено %d\n", o_obj_sum - printf "\n ПРОТУХЛОСТЬ — md5 исходника разошёлся с описью\n" - printf " строк протухло %d из %d\n", prot_n, strok - printf " из них несут «доказано» %d\n", prot_dok - printf " и «написано» %d\n", prot_nap - if(rezhim=="числа"){ exit 0 } - if(beda==0){ printf "\nопись сходится с деревом\n"; exit 0 } - printf "\n" - for(p in net_stroki) printf "НЕТ СТРОКИ: %s несёт %d обязательств, а в описи его нет\n", p, net_stroki[p] > "/dev/stderr" - for(p in lishn) printf "ЛИШНЯЯ СТРОКА: %s есть в описи, а в дереве обязательств не несёт\n", p > "/dev/stderr" - for(p in raz_nap) printf "«НАПИСАНО» НЕ СХОДИТСЯ: %s — %s\n", p, raz_nap[p] > "/dev/stderr" - printf "\nбед %d: нет строки %d, лишних %d, «написано» не сходится %d\n", beda, net_n+0, lishn_n+0, raz_n+0 > "/dev/stderr" - exit 1 - } -' "$RAB/derevo" "$RAB/opis" diff --git a/scripts/ledgers/link-guard-known-not-a-path.tsv b/scripts/ledgers/link-guard-known-not-a-path.tsv index 5d299e3a6..4c069d34d 100644 --- a/scripts/ledgers/link-guard-known-not-a-path.tsv +++ b/scripts/ledgers/link-guard-known-not-a-path.tsv @@ -184,3 +184,11 @@ docs/tasks/0049-the-last-javascript-leaves-the-tree.md flang/scripts/word-occupa docs/tasks/1219-comments-in-shell-scripts-fall-below-a-fifth.md scripts/guards/version-derivations-guard.sh история: замер доли комментариев того дня считал этот файл; он снят 4 октября 2026 (задача 5821), сверка стала планом scripts/guards/version-derivations-guard.fscript docs/tasks/5821-shell-scripts-that-can-become-flang-are-counted-and-moved.md scripts/seed/seed-freshness.sh история: пункт задачи про снятый переходник; имя оставлено зачёркнутым, чтобы было видно, ЧТО снято docs/tasks/5821-shell-scripts-that-can-become-flang-are-counted-and-moved.md version-derivations-guard.sh история: пункт задачи про снятый сторож; имя оставлено зачёркнутым, чтобы было видно, ЧТО снято +docs/tasks/3593-the-proved-share-collapses-on-code-that-touches-the-world.md scripts/guards/proved-share-vs-tree.sh история: сторож перенесён на план scripts/guards/proved-share-vs-tree.fscript 4 октября 2026; в задаче он назван тем именем, какое носил тогда +docs/tasks/4416-the-checker-rejects-an-honest-instantiation-proof.md scripts/guards/proved-share-vs-tree.sh история: сторож перенесён на план scripts/guards/proved-share-vs-tree.fscript 4 октября 2026; в задаче он назван тем именем, какое носил тогда +docs/tasks/5821-shell-scripts-that-can-become-flang-are-counted-and-moved.md proved-share-vs-tree.sh история: список кандидатов на перенос, снятый до переноса; сам перенос сделан 4 октября 2026 в scripts/guards/proved-share-vs-tree.fscript +docs/tasks/5821-shell-scripts-that-can-become-flang-are-counted-and-moved.md guards-without-forgery-probe.sh история: список кандидатов на перенос, снятый до переноса; сам перенос сделан 4 октября 2026 в scripts/guards/guards-without-forgery-probe.fscript +docs/tasks/1177-a-quantifier-is-refused-inside-a-formula-and-binds-only-a-whole-goal.md scripts/guards/proved-share-vs-tree.sh история: сторож перенесён на план scripts/guards/proved-share-vs-tree.fscript 4 октября 2026; в задаче он назван тем именем, какое носил тогда +docs/tasks/1188-existence-without-a-named-witness-has-no-rule.md scripts/guards/proved-share-vs-tree.sh история: сторож перенесён на план scripts/guards/proved-share-vs-tree.fscript 4 октября 2026; в задаче он назван тем именем, какое носил тогда +docs/tasks/2277-the-law-judges-of-monoid-functor-and-monad-are-written-and-called-by-nobody.md scripts/guards/proved-share-vs-tree.sh история: сторож перенесён на план scripts/guards/proved-share-vs-tree.fscript 4 октября 2026; в задаче он назван тем именем, какое носил тогда +docs/tasks/4433-the-uncalled-checks-guard-does-not-see-a-judge-in-the-closure.md scripts/guards/guards-without-forgery-probe.sh история: сторож перенесён на план scripts/guards/guards-without-forgery-probe.fscript 4 октября 2026; в задаче он назван тем именем, какое носил тогда diff --git a/scripts/ledgers/proved-share-ledger.txt b/scripts/ledgers/proved-share-ledger.txt index bfed5db88..82b5a88ec 100644 --- a/scripts/ledgers/proved-share-ledger.txt +++ b/scripts/ledgers/proved-share-ledger.txt @@ -1544,6 +1544,7 @@ d45fead194fa7d93bc7afffb0f6b2a04|12|12|0|0|0|scripts/guards/delivery-guard.flang 9a1d779542ab08a5a1416bbdc99c0563|10|10|0|0|0|scripts/guards/dictionary-guard.fscript 35bc4b6ceba5235a93625a25ded7023f|12|12|0|0|0|scripts/guards/emit-promises-guard.fscript bb9f8dadc0aa937a5fc4dbda79707edd|18|16|2|0|0|scripts/guards/file-extensions.fscript +ce0f26e8f64ce11b7f2f8e559d0f090b|11|11|0|0|0|scripts/guards/guards-without-forgery-probe.fscript d29d464d969d58822bc10e6e696017ef|14|14|0|0|0|scripts/flangrc.fscript 001c0ecd7217d8ae84b4133d3dca9085|4|4|0|0|0|scripts/guards/flangrc-guard.fscript baa3170dc90958c56352eb9b3f49ab9b|62|49|10|3|0|scripts/guards/homebrew-formula-guard.fscript @@ -1560,6 +1561,7 @@ b227c0ad335b884661247019d31270e6|22|22|0|0|0|scripts/guards/name-splicing-guard. c5506e0d519db2384994e5edb50f9ad8|13|7|6|0|0|scripts/guards/no-comments-guard.fscript 323f8525a0746bf647873edd7ba3eaf7|9|9|0|0|0|scripts/guards/no-package-json-guard.fscript 76e306cbb502d04abaef8d8b0807eb8d|7|7|0|0|0|scripts/guards/occupancy-check.fscript +01aef169c0bbf946d103d0efc22f3d7e|13|13|0|0|0|scripts/guards/proved-share-vs-tree.fscript 7feca661ed8e0a679823c1b6f0a431fe|24|24|0|0|0|scripts/guards/occupied-names-guard.fscript bcb9a4bd2f77da1cc1fdfe50b7385bed|2|2|0|0|0|scripts/guards/record-follows-its-source.fscript 1083cc30fab03e5f16e2060519b7c8c1|8|8|0|0|0|scripts/guards/release-guard.fscript