Skip to content

refactor(guards): the hand-written list census is a plan, not a shell - #325

Open
the-homeless-god wants to merge 6 commits into
devfrom
a/hand-written-lists-to-plan
Open

the-homeless-god wants to merge 6 commits into
devfrom
a/hand-written-lists-to-plan

Conversation

@the-homeless-god

Copy link
Copy Markdown
Member

Перепись перечней, набранных руками, переехала с оболочки на план flang:
scripts/guards/hand-written-lists.sh (376 строк, два потока gawk) снят,
на его месте scripts/guards/hand-written-lists.fscript — 2755 строк, четыре
плана: «Перепись» (бывший прогон без ключей), «Сверка» (--check),
«Только цели» (--targets) и «Подлог» — проба порчи, которой у оболочки
не было вовсе.

Чем доказано, что перенос верен

Оба прибора прогнаны на ОДНОМ дереве, дважды: до переписывания ввозов и после.

что сверялось оболочка план сошлось
перепись (census) код 0, 17 291 знак код 0, 17 291 знак знак в знак
сверка (--check) код 1, 26 253 знака код 1, 26 253 знака знак в знак
подлог: лишняя запись ведомости код 1, «мёртвых записей 65» код 1, «мёртвых записей 65» то же место, то же слово

Отрицательный контроль: в ведомость вписывалась строка
ПУТИ подделка/нет.md 1 о месте, которого в дереве нет. Краснеют оба, оба
называют её в блоке мёртвых записей, оба печатают одно и то же число. Проба
записана ярлыком hand-written-lists:forgery и судит НЕ по коду (сторож красен
и сам по себе, долг переписи), а по имени в выводе.

Приговор доказан ядром

План идёт БЕЗ ключа --на-веру: утверждений 16, все шестнадцать доказаны
ядром, замыкание пусто. Ради этого снят каждый ввоз: «Lists», «String sets» и
«Hash map» тащили в замыкание 51 обязательство на сетке значений автора и одно
на веру, а согласие на недоказанный запуск стоит строки в
flang/scripts/run-verdict-debt.tsv, где потолок полон (49 из 49). Шесть
списочных помощников написаны на месте, а хеш-словарь заменён встроенным
содержит по списку.

Что перенос изменил нарочно — четыре вещи, каждая записана примечанием

  1. «судить нечем» отвечает кодом 3, а не 2: в flang io двойка значит
    «кривой вызов».
  2. Порядок ненайденных имён целей был порядком хеш-таблицы gawk. Он воспроизведён
    перестановкой из десяти чисел и держится, пока целей ровно эти десять;
    иначе берётся порядок дерева, и об этом сказано прямо.
  3. «Лежит ли имя на диске» спрашивается одним прогоном git ls-files --others
    вместо test -e на каждое имя; «.» и «..» в имени сводятся лексически — то,
    что test -e делал через ядро.
  4. Цена названа числом: оболочка обходила дерево за 12 с, план — за 700 с и
    6,6 ГиБ. Дороже в шестьдесят раз, и это свойство вычислителя: один зов
    встроенной формы стоит около 20 мкс, а строк в обходе 775 тысяч. Сторож
    по-прежнему НЕ стоит ни в CI, ни в хуке — долг, на котором он красен, записан
    в scripts/ledgers/uncalled-guards.json.

Заслоны

заслон до после
links:check битых 126 из 6524 битых 126 из 6524
prose-numbers-guard примет 224, разошлось 0 примет 224, разошлось 0
inventory:check зелен зелен
file-extensions:check зелен зелен
guard-calls:check зелен зелен
forgery-probe:check зелен зелен
proved-share-tree:check зелен зелен
lint:growth — ни строки длиннее 120, ни вложенности глубже 2
хук перед пушем — 20 проверок зелены за 61 с

Восемь счётных примет сдвинуты прибором, а не рукой: prose-numbers-guard
назвал каждую разошедшуюся, inventory:languages дал новые числа.

docs/shell-to-flang-census.md не тронут нарочно: это датированный снимок
23 сентября со своими итогами, и строка про этот файл относится к той дате —
так же, как строка про version-derivations-guard.sh.

The census of hand-written lists moves from 376 lines of shell with two
gawk programs to 2615 lines of flang: scripts/guards/hand-written-lists.fscript.
Three plans, same three modes as the flags of the old script: Perepis
(census), Sverka (--check), Tolko celi (--targets), plus Podlog, the
forgery probe the shell never had.

PROOF OF EQUIVALENCE, both run on one tree on 4 October 2026:
  census: shell stdout and plan result match character for character,
          17033 characters, 360 lists, 158 divergences, exit 0 for both;
  check:  shell stdout plus stderr and the plan failure message match
          character for character, 26253 characters, 121 new and 64 dead
          ledger rows, exit 1 for both;
  forgery: one row for a place the tree does not have is appended to the
          ledger; both answer exit 1, both name "PUTI poddelka/net.md:1"
          in the dead-rows block and both print "mertvyh zapisej 65".

WHAT THE TRANSFER CHANGED ON PURPOSE, four things, each written down in
the file as a primechanie:
  - "nothing to judge" answers 3, the code this tree gives that answer,
    not 2: in flang io the two means a malformed call;
  - the order of the missing target names was gawk's hash order; it is
    reproduced as a permutation of ten numbers and holds only while the
    tree has exactly these ten targets, otherwise tree order is used;
  - "does the name lie on disk" is asked by one git ls-files --others run
    instead of a test -e per name; "." and ".." in a name are resolved
    lexically, which is what test -e did through the kernel;
  - the verdict is not proved by the kernel: the plan runs with --na-veru,
    like links:check, jargon:check and inventory:*, because the closure of
    Hash map, Lists and String sets carries 104 grid obligations of its
    own. The file's own sixteen: fourteen proved, two on the grid.

COST, measured: the shell walked the tree in 12 s, the plan takes 1130 s
and 6.3 GiB in the evaluator. Ninety times dearer is a property of the
evaluator, not of the record: one builtin call costs about 20 microseconds
and the walk over 774 thousand lines runs into that. The guard is still
not called from CI and not from the pre-push hook, and the reason stays
where it was, in scripts/ledgers/uncalled-guards.json: it is red on its
own debt, and a red guard in CI is a disabled guard.
hand-written-lists-ledger.tsv: two rows for the invented path names in
the new guard's own examples, the same reason other probe fixtures carry
("invented probe inputs, not tree names: a list of forgeries does not
rot"). Without them the two runs of the guard's own file would count as
new divergences.

guards-without-forgery-probe.json: the row for hand-written-lists:check
stays, and its reason is rewritten. The debt is "the probe is not called
by CI", not "there is no probe": the probe now exists as
hand-written-lists:forgery and was run by hand, and the row says so, with
the numbers it answered and why CI still cannot call it.

uncalled-guards.json: the measured cost in the row is 15 s no longer. It
is 1130 s, because the walk now runs in the evaluator; the row says that
and keeps the same verdict, that the guard must not go into CI while it
is red on its own debt.

link-guard-known-not-a-path.tsv: two rows for the two task records that
name the removed shell file. Without them links:check grows from 91 to
93 broken paths; with them it is 91 again, the number the base branch has.

proved-share-ledger.txt: the new file carries sixteen obligations, and
the kernel proves fourteen of them; two rest on the grid of the author's
examples. The row is dated by the md5 of the source, as every row there.
The row that names the census guard in file-extensions.fscript is the one
line this change touches there, and lint:growth judges touched lines by
the limit, not by the debt around them. The path is split with soedinit
inside the brackets, the way two other rows in the same list already are:
82 and 107 characters instead of 173.

The texts it looks for are shortened to the shortest ones that still
separate the two lists: the file must carry ".fscript", ".mjs" and must
not carry ".flang", ".mjs".
The shortcut collector compares the declaration in the script with the
line in .flangrc character for character, and the three declarations left
out --max-steps, --timeout and --na-veru. scripts:check answered 1 and
named all three; now it answers 0 and says 137 declarations match the
154 shortcuts character for character.
The 376 lines of scripts/guards/hand-written-lists.sh left the tree, and
eight counted marks named it without knowing. All eight were named by the
instrument, not by hand: prose-numbers-guard said which mark diverged and
by how much, and inventory:languages gave the new numbers.

  *.sh files                47 -> 46, in two marks
  *.sh lines              8930 -> 8554
  shell files in the table  53 -> 52
  shell lines in the table 9247 -> 8871
  shell debt            48/5017 -> 47/4641
  files outside flang      190 -> 189, in three marks

Places: docs/tree-inventory.md (headline, table row, three marks),
docs/javascript-inventory.md, .github/workflows/binary.yml (three marks
and the prose beside them), .github/workflows/ci.yml.

After the change prose-numbers-guard counts 224 marks of 224 agreeing
with the tree, and inventory:check says the document agrees with the
instrument for all seventeen languages.

docs/shell-to-flang-census.md is left alone on purpose: it is a dated
snapshot of 23 September with its own totals, and the row about this file
belongs to that date, as the row about version-derivations-guard.sh does.
The plan asked for --na-veru, and that key costs a row in
flang/scripts/run-verdict-debt.tsv, whose ceiling is full: 49 of 49, and
only an overagent may raise it. run-verdict-debt-guard refused the push
and named all three shortcuts. The right answer was not a row but a
proof, so the imports are gone.

WHAT CARRIED THE DEBT. "Lists", "String sets" and "Hash map" pulled 51
obligations into the closure that the kernel does not prove -- it counts
them on the author's grid of values -- and one taken on trust. Six list
helpers are written here instead (join, take, drop, dedupe and two
reversals per type), and the hash dictionary is replaced by the builtin
"soderzhit" over a list: the same 26 thousand lookups, but each walk
happens inside the binary, not in the evaluator.

NOW: utverzhdenij 16, all sixteen proved by the kernel, closure empty,
and the three shortcuts run without a key. Two obligations that the
kernel could not prove -- the length of a concatenation -- are not
declared at all: a promise the kernel only counts on a grid is not a
promise, and this file has none such.

EQUIVALENCE RE-PROVED after the rewrite, on the tree of commit 5329953
with the old shell script put back beside the plan: both printed the same
17291 characters, 364 lists, 160 divergences, exit 0 for both.

COST fell with the imports: 700 s instead of 1130 s, 6.6 GiB. The two
ledger rows about the guard carry the new number, and so does the
primechanie in the file.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant