diff --git a/apps/website/src/data/blog/bodies/ninety-tests-were-unreachable.ts b/apps/website/src/data/blog/bodies/ninety-tests-were-unreachable.ts new file mode 100644 index 0000000000..124daf09a9 --- /dev/null +++ b/apps/website/src/data/blog/bodies/ninety-tests-were-unreachable.ts @@ -0,0 +1,57 @@ +import type { Block } from '../types' + +export const body: Block[] = [ + { kind: 'p', text: '[measured in merged PR #778] A Zig codegen subtree became importable, exposing 90 tests that had been present but unreachable. The reported verification moved from 155 to 157 steps and from 2,832 to 2,939 tests.' }, + { kind: 'p', text: 'The interesting part is not the size of the diff. It is the distinction between a gate that can parse a file and a test root that can execute it. Several Sema errors prevented the tree from being imported, while ast-check and the tree-wide format gate still treated the files as clean.' }, + { kind: 'h', text: 'The hidden gate was a missing field default' }, + { kind: 'p', text: '[reported verification] Ten `.test_cases = .{}` sites were missing the `capacity` field after the Zig 0.16 ArrayListUnmanaged change. Twelve `Behavior.owner` literals also lacked a default. These were compile-time shape errors, not runtime failures, and they kept the codegen tree outside the test graph.' }, + { kind: 'p', text: 'After those declarations were repaired, `src/vibeec/zig_codegen.zig` became a test root. The merged PR reports 157/157 build steps and 2,939 tests, compared with 155/155 and 2,832 before the tree was reachable.' }, + { kind: 'h', text: 'Reachability exposed two different failures' }, + { kind: 'ul', items: [ + 'Option panicked because the parser sliced after 8 characters even though `Option<` has length 7. The constant is now expressed as `"Option<".len` at four sites.', + 'List had the wrong expected type. Treating it as `[]const u8` would collapse a list of strings into one string; the sibling List> test establishes `[]const []const i64` instead.', + ] }, + { kind: 'p', text: 'The second failure matters because it distinguishes an implementation defect from an expectation defect. The implementation already preserved nested list structure; the expectation had never run far enough to be corrected by the test suite.' }, + { kind: 'h', text: 'The signature story was narrower than expected' }, + { kind: 'p', text: '[measured in the merged PR] A sweep covered 558 combinations: 62 behaviour-name prefixes crossed with 9 `then` phrases. The emitter wrote `pub fn () !void` in every case. The inference code is consulted by body_emitter and tests_gen, but not by the code that writes the generated function header.' }, + { kind: 'p', text: 'That explains the earlier failure without claiming a repair that was not made. Two tests now pin the current boundary: a signature promising a value must eventually have a returning body, and the current emitter still produces `!void`. Wiring inferred return types into headers remains a separate change.' }, + { kind: 'h', text: 'One error class became a scope problem' }, + { kind: 'p', text: '[reported verification] The undeclared-identifier census fell from 151 errors across 36 files to 66 errors, while total errors fell from 354 to 272 and rejected files from 100 to 94. The dominant shape was an ArrayList 0.16 migration that added allocator arguments without binding an allocator in the enclosing function.' }, + { kind: 'p', text: 'The safe repair was scoped structurally: walk to the enclosing function and use `self.allocator` when the function has a self binding. A same-line text heuristic missed calls inside methods and could have changed a legitimate local allocator. The remaining 66 errors are a different class and were left for reading rather than folded into this fix.' }, + { kind: 'h', text: 'What is established, and what is not' }, + { kind: 'p', text: 'The merged PR establishes a reachable Zig codegen test root, two newly visible test failures that were corrected or pinned, and a narrower classification of the remaining compiler errors. It is a software repository result.' }, + { kind: 'ul', items: [ + 'The verification commands and counts are reported by PR #778; they were not independently rerun in this blog run.', + 'The post does not establish FPGA or AX7203 behavior, timing, energy, model quality, or a physical-chip result.', + 'The 66 remaining errors are not resolved by this PR, and inferred return types are not connected to ordinary generated headers.', + 'The change says nothing about the 83-format numeric catalogue.', + ] }, +] + +export const ruBody: Block[] = [ + { kind: 'p', text: '[измерено в смерженном PR #778] Поддерево Zig codegen стало импортируемым, и стали достижимы 90 тестов, которые уже существовали, но не входили в исполняемое дерево. В отчёте проверки число шагов выросло со 155 до 157, а число тестов — с 2 832 до 2 939.' }, + { kind: 'p', text: 'Интересен не размер диффа, а различие между гейтом, который может разобрать файл, и test root, который действительно может его запустить. Несколько ошибок Sema не давали импортировать дерево, хотя ast-check и общий format-gate продолжали считать файлы чистыми.' }, + { kind: 'h', text: 'Скрытым гейтом оказался пропущенный default поля' }, + { kind: 'p', text: '[отчёт проверки] В десяти местах `.test_cases = .{}` не хватало поля `capacity` после изменения ArrayListUnmanaged в Zig 0.16. Ещё в двенадцати литералах `Behavior.owner` не было значения по умолчанию. Это ошибки формы на этапе компиляции, не падения во время исполнения; именно они оставляли дерево codegen вне тестового графа.' }, + { kind: 'p', text: 'После исправления объявлений `src/vibeec/zig_codegen.zig` стал test root. Смерженный PR сообщает о 157/157 шагах сборки и 2 939 тестах против 155/155 и 2 832 до того, как дерево стало достижимым.' }, + { kind: 'h', text: 'Достижимость показала два разных отказа' }, + { kind: 'ul', items: [ + 'Option падал, потому что парсер отрезал строку после 8 символов, хотя длина `Option<` равна 7. Теперь на четырёх местах используется `"Option<".len`.', + 'Для List ожидался неправильный тип. `[]const u8` превратил бы список строк в одну строку; соседний тест List> фиксирует корректный результат `[]const []const i64`.', + ] }, + { kind: 'p', text: 'Второй отказ важен тем, что разделяет дефект реализации и дефект ожидания. Реализация уже сохраняла вложенную структуру списков; ожидание просто не успевало дойти до проверки, которая могла бы показать ошибку.' }, + { kind: 'h', text: 'История с сигнатурой оказалась уже' }, + { kind: 'p', text: '[измерено в смерженном PR] Развёртка покрыла 558 комбинаций: 62 префикса имён behaviours и 9 фраз `then`. Emitter во всех случаях записал `pub fn () !void`. Код inference вызывается из body_emitter и tests_gen, но не участвует в записи заголовка сгенерированной функции.' }, + { kind: 'p', text: 'Это объясняет прежний отказ без заявления о незавершённом ремонте. Теперь два теста фиксируют границу: сигнатура, обещающая значение, должна в будущем иметь возвращающее тело, а текущий emitter всё ещё выдаёт `!void`. Подключение выведенных return types к заголовкам остаётся отдельной правкой.' }, + { kind: 'h', text: 'Один класс ошибок оказался проблемой области видимости' }, + { kind: 'p', text: '[отчёт проверки] Перепись undeclared-identifier снизилась со 151 ошибки в 36 файлах до 66 ошибок; общее число ошибок упало с 354 до 272, а число отвергнутых файлов — со 100 до 94. Основной класс возник после миграции ArrayList на Zig 0.16: вызовы получили allocator-аргументы, но allocator не был связан во внешней функции.' }, + { kind: 'p', text: 'Безопасная правка была структурной: подняться к внешней функции и использовать `self.allocator`, только если у функции есть self binding. Текстовая эвристика по той же строке пропускала вызовы внутри методов и могла изменить настоящий локальный allocator. Оставшиеся 66 ошибок относятся к другому классу; их оставили для чтения, а не включили в это исправление.' }, + { kind: 'h', text: 'Что установлено, а что нет' }, + { kind: 'p', text: 'Смерженный PR устанавливает достижимый test root для Zig codegen, две ранее скрытые ошибки тестов, которые были исправлены или зафиксированы, и более узкую классификацию оставшихся ошибок компилятора. Это результат программного репозитория.' }, + { kind: 'ul', items: [ + 'Команды проверки и числа приведены по отчёту PR #778; в этом запуске блога они независимо не повторялись.', + 'Пост не устанавливает поведение FPGA или AX7203, timing, энергию, качество модели или результат на физическом кристалле.', + 'Оставшиеся 66 ошибок этим PR не исправлены, а выведенные return types не подключены к обычным заголовкам генератора.', + 'Изменение ничего не говорит о каталоге числовых форматов из 83 форматов.', + ] }, +] diff --git a/apps/website/src/data/blog/index.ts b/apps/website/src/data/blog/index.ts index 80def31193..0986046e04 100644 --- a/apps/website/src/data/blog/index.ts +++ b/apps/website/src/data/blog/index.ts @@ -2,6 +2,38 @@ import type { PostMeta } from './types' /** Индекс блога: список и метаданные без тяжёлых тел публикаций. */ export const postsIndex: PostMeta[] = [ + { + slug: 'ninety-tests-were-unreachable', + title: 'Ninety tests were present, but unreachable', + summary: '[measured in merged PR #778] A Zig codegen subtree became importable, exposing 90 previously unreachable tests; the reported verification moved from 155 to 157 steps and from 2,832 to 2,939 tests.', + date: '2026-09-07', + readingMinutes: 6, + tags: ['Zig', 'Compiler', 'Testing', 'Reproducibility'], + receipts: [ + { label: 'Merged PR #778 — codegen tree import and test reachability', href: 'https://github.com/gHashTag/trinity-fpga/pull/778' }, + { label: 'Merge commit 515bc8e1 — the landed codegen changes', href: 'https://github.com/gHashTag/trinity-fpga/commit/515bc8e1b56ae45cfc25a34808aeee2f4ee0d89d' }, + { label: 'Commit 311abb7a — the 90 tests become reachable', href: 'https://github.com/gHashTag/trinity-fpga/commit/311abb7a57f36e4c27c91d825ab18db04eae009f' }, + { label: 'Commit f361b8a8 — signature behavior pinned by tests', href: 'https://github.com/gHashTag/trinity-fpga/commit/f361b8a802f79c4dde8e4f1a084ea42fae02d0aa' }, + { label: 'Commit eebeae43 — allocator scope repair', href: 'https://github.com/gHashTag/trinity-fpga/commit/eebeae4344de90a9d30dbe9832b371591ef4f113' }, + ], + openQuestions: [ + 'The verification commands and counts are reported by PR #778; they were not independently rerun in this blog run.', + 'The change is a software repository result. It does not establish FPGA or AX7203 behavior, timing, energy, model quality, or a physical-chip result.', + 'The 66 remaining errors are not resolved by this PR, and inferred return types are not connected to ordinary generated headers.', + 'The change says nothing about the 83-format numeric catalogue.', + ], + published: true, + ru: { + title: '90 тестов существовали, но были недостижимы', + summary: '[измерено в смерженном PR #778] Поддерево Zig codegen стало импортируемым, и стали достижимы 90 ранее скрытых тестов; в отчёте проверки число шагов выросло со 155 до 157, а число тестов — с 2 832 до 2 939.', + openQuestions: [ + 'Команды проверки и числа приведены по отчёту PR #778; в этом запуске блога они независимо не повторялись.', + 'Это результат программного репозитория. Он не устанавливает поведение FPGA или AX7203, timing, энергию, качество модели или результат на физическом кристалле.', + 'Оставшиеся 66 ошибок этим PR не исправлены, а выведенные return types не подключены к обычным заголовкам генератора.', + 'Изменение ничего не говорит о каталоге числовых форматов из 83 форматов.', + ], + }, + }, { slug: 'one-saturation-rule-five-artefacts', title: 'One saturation rule, five artefacts', diff --git a/apps/website/src/data/blog/posts.ts b/apps/website/src/data/blog/posts.ts index 4cf065226f..45d42c67ad 100644 --- a/apps/website/src/data/blog/posts.ts +++ b/apps/website/src/data/blog/posts.ts @@ -4,6 +4,7 @@ import { body as body_clara_proposal_submitted_not_reviewed, ruBody as ruBody_cl import { body as body_tri_claw_an_agent_you_can_audit, ruBody as ruBody_tri_claw_an_agent_you_can_audit } from './bodies/tri-claw-an-agent-you-can-audit' import { body as body_a_health_snapshot_changed_its_denominator, ruBody as ruBody_a_health_snapshot_changed_its_denominator } from './bodies/a-health-snapshot-changed-its-denominator' import { body as body_one_saturation_rule_five_artefacts, ruBody as ruBody_one_saturation_rule_five_artefacts } from './bodies/one-saturation-rule-five-artefacts' +import { body as body_ninety_tests_were_unreachable, ruBody as ruBody_ninety_tests_were_unreachable } from './bodies/ninety-tests-were-unreachable' import type { Post, PostBody } from './types' import { body as body_the_only_stable_speed_belonged_to_the_tool, ruBody as ruBody_the_only_stable_speed_belonged_to_the_tool } from './bodies/the-only-stable-speed-belonged-to-the-tool' import { body as body_queen_review_lifecycle_queues, ruBody as ruBody_queen_review_lifecycle_queues } from './bodies/queen-review-lifecycle-queues' @@ -65,6 +66,7 @@ import { body as body_real_value_in_integer_container, ruBody as ruBody_real_val import { body as body_one_commit_nine_workflow_outcomes, ruBody as ruBody_one_commit_nine_workflow_outcomes } from './bodies/one-commit-nine-workflow-outcomes' const bodies: Record = { + 'ninety-tests-were-unreachable': { body: body_ninety_tests_were_unreachable, ruBody: ruBody_ninety_tests_were_unreachable }, 'one-saturation-rule-five-artefacts': { body: body_one_saturation_rule_five_artefacts, ruBody: ruBody_one_saturation_rule_five_artefacts }, 'queen-foundation-snapshot-contract': { body: body_queen_foundation_snapshot_contract, ruBody: ruBody_queen_foundation_snapshot_contract }, 'clara-proposal-submitted-not-reviewed': { body: body_clara_proposal_submitted_not_reviewed, ruBody: ruBody_clara_proposal_submitted_not_reviewed },