Skip to content

docs(P-022): parity-work discipline + status reconciliation at fdcb222 - #322

Merged
PhysShell merged 2 commits into
mainfrom
claude/p022-parity-discipline
Aug 7, 2026
Merged

docs(P-022): parity-work discipline + status reconciliation at fdcb222#322
PhysShell merged 2 commits into
mainfrom
claude/p022-parity-discipline

Conversation

@PhysShell

@PhysShellPhysShell commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Что и зачем

Две половины одного изменения, намеренно вместе: правила, как перестать допускать status drift, и сверка, убирающая тот drift, на котором эти правила и выучены.

Разводить их было бы третьим заходом на те же грабли — чинить статус отдельным PR от правила «обе поверхности меняются одним изменением».

Тип изменения

  • feat — новая возможность
  • fix — исправление бага
  • docs — документация
  • refactor / chore / test / ci — без изменения поведения

Как проверено

  • python tests/run_tests.py
  • ruff check . и mypy
  • селфтесты затронутых скриптов (python scripts/<...>.py --selftest)

Изменение docs-only; гейты прогнаны, чтобы подтвердить отсутствие побочных эффектов. Все факты сверены прогоном против дерева на fdcb222, а не по памяти — первое же правило нового раздела.

Связанные issue

Refs #250, #255, #256, #258, #259. Ничего не закрывает.

Чеклист

  • изменение покрыто тестом/селфтестом (или объяснено, почему нет)
  • README/docs обновлены при необходимости
  • коммиты в conventional-commit стиле (feat:, fix:, docs: …)

Раздел Parity-work discipline

Четыре правила, каждое оплачено настоящим дефектом на шаге 5a (#255, PR #319/#320/#321). Формулировки намеренно шире этого порта — ни одно не зависит от Rust, Python или слоя диагностик, поэтому они переживут P-022 и пригодятся следующей миграции, которая прикалывает одну реализацию к другой.

ПравилоОплачено дефектом
Oracle over reviewer prose — находка это гипотеза, пока не воспроизведена против эталона; сохраняем наблюдаемое поведение, а не объяснение ревьюераревью выводило правило границы слова из односторонних проб (\b-foo), тогда как эталон строит двусторонний шаблон. Вывод верен, обоснование — нет; реализовать обоснование значило бы ошибиться
Mutation over plausible tests — тест на регрессию не доказательство, пока мутация не роняет его через ту production-поверхность, которую он берётся защищатьreplay упорядочивания сортировал параллельный вектор копией ключа — он прошёл бы против sort_unstable_by, ровно того дефекта, ради которого написан
No fail-fast during mutation campaigns — мутация должна показать все независимые слои-ловцы, а не первый упавший таргетcargo test останавливается на первом таргете; с --no-fail-fast та же мутация дала три ловца, а вторая ловилась только на replay-слое
Insertion-stable generated goldens — форма, выведенная из словаря, обязана зависеть от стабильной идентичности элемента, не от порядковой позицииledger ротировал формы по индексу: вставка одного кода переписывала 42 из 47 записей (замерено). Докстринг при этом утверждал «deterministic, so the golden stays stable»

Инвариант нормативен, хеш — нет

Для четвёртого правила закон записан как acceptance, а не как рецепт:

insert one synthetic vocabulary member
existing-record churn == 0
new-record delta == 1

Content hash — сегодняшний способ это выполнить, а не требование. Любой стабильный маппинг, держащий обе строки, соответствует норме, и его замена не нарушение. Иначе через два года корректная замена выглядела бы ересью при правильном поведении.

Единственная оговорка по механизму: он обязан быть воспроизводим между процессами — hash() в Python рандомизирует хеширование строк и не годится.

Один дом

Правила не дублируются в AGENTS.execution-surfaces.md. Они родились как доказательная дисциплина конкретной parity-миграции, а не как общая инструкция агенту; две копии одного закона разъезжаются — ровно то, что призвано предотвращать правило про status drift.

Сверка статуса

Написана заново против дерева на fdcb222. Предыдущая (неслитая) сверка не переносилась: протухший блок, залатанный протухшим фиксом, остаётся протухшим — она сама успела устареть, объявляя #255 «ready». Старая ветка брошена, а не cherry-pick'нута.

Что было неверно на main:

  • #258 описан как «land with PR spec(bridge): #258 — executable own-bridge contract (Bridge.md + behavior matrix) #297, in independent review; not on main yet» — закрыт completed, оба spec-документа на main;
  • own-lowered и own-bridge отсутствовали в списке воркспейса, хотя оба его члены;
  • шаг 5a значился будущим — #255 закрыт completed сегодня;
  • own-diagnostics описан как data-only слой — он несёт полный нормализованный контракт.

Что теперь: checkpoint-level статус, где у каждого открытого шага различены нормативный блокер и предпочтительная последовательность из #250. #259 разложен по его собственным пяти checkpoint'ам — cp2 и cp3 complete с числами (27/27 lowering, 35 summaries goldens), cp1 partial, cp4 not started, cp5 разблокирован #255, но не сделан: его набор сравнения теперь есть, а сравнивать пока нечего без wiring из cp4. У #260/#269 сохранено различие sliceable-инфраструктуры и недостижимого пока final acceptance.

Зафиксирована очередь: #256 → остаток #259 (cp1 → cp4 → cp5) → #260/#269.

Строка P-022 в индексе предложений исправлена тем же изменением — это третья статусная поверхность того же факта, и оставить её протухшей значило бы повторить дефект прямо в PR, который его лечит.

Про #250

Это GitHub issue, он физически не едет в git-коммите. Его body синхронизируется тем же ходом — по его же правилу, что обе поверхности меняются вместе. Там: #255 отмечен Done, #256 — Ready с удовлетворённым блокером, у #259 cp5 явно перечислен остаток acceptance, allocation переставлен на #256 → остаток #259, и из status-drift правила дана ссылка на новый раздел.

Что НЕ входит

Исполняемый guard для правила №4 сейчас реализует только churn == 0. Доведение до delta == 1 плюс три nitpick'а из ревью #321 — следующим отдельным test-PR, и он обязан мутационно доказать обе половины acceptance.

Раунд ревью (267e38c)

CodeRabbit дал 4 находки на 2cb3822. Каждая проверена против дерева до правки — это первое правило раздела, который тот же PR и вводит, так что применить его именно здесь было принципиально.

НаходкаИтог
delta == 1 не гарантируется тестомисправлено — самая ценная из четырёх
MD001: уровень заголовка Implementation statusисправлено
MD018: #258 / #319 в начале строкиисправлено
in executionin progress в индексеотклонено; ревьюер снял находку

Про delta == 1. Проверено в дереве: _insertion_churn() возвращает только счётчик churn, run() гейтит по if churn: — delta не вычисляется нигде. То есть генератор, который вовсе выбросил бы новую запись, прошёл бы все исполняемые проверки, пока документ читался так, будто закрыты обе строки. Ровно тот разрыв документа и дерева, ради которого этот PR и существует. Теперь разрыв назван явно; сама норма не менялась — по тексту правила №4 законом является инвариант, а не текущая обвязка.

Про отклонённую находку.in execution уже был на main в этой же ячейке (diff менял только текст после статуса), а P-022-rust-core-migration.md:3 содержит Status: **in execution** на строке, которую PR не трогает. Переписать только строку индекса значило бы оставить индекс противоречащим тому предложению, которое он индексирует, — то есть изготовить тот самый drift. Плюс словарь применён избирательно: в той же таблице живут v0 built, first slice built, draft (stub), accepted (design; impl post-cutover, #304).

Обе committable-подсказки ревьюера были к тому же синтаксически битые — (`#214/`#249) и `#319/`#320/#321 с непарными бэктиками. Ещё одна причина не принимать подсказки на веру.

MD018, для точности: на CommonMark это ложное срабатывание — ATX-заголовок требует пробела после #, поэтому #258 на GitHub рендерится текстом. Переформатировано всё равно: вне CommonMark паттерн ломается, а цена — два переноса строки. Отдельно: markdownlint в этом репозитории не настроен и не запускается в CI, это собственный линтер ревьюера, не гейт.

Two halves of one change, deliberately together: the rules that say how to
stop status drift, and the reconciliation that clears the drift those rules
were learned from.
## Parity-work discipline (new section)
Four rules, each paid for by a real defect during step 5a (#255, PRs
#319/#320/#321), written wider than this port so they outlive P-022:
1. Oracle over reviewer prose — a finding is a hypothesis until reproduced
against the reference; keep the observed behaviour, not the reviewer's
explanation. (A review argued the word-boundary rule from single-ended
probes; the reference builds a both-ended pattern. Right conclusion,
wrong reason — implementing the reason would have been wrong.)
2. Mutation over plausible tests — a regression test is not evidence until
the matching mutation fails it THROUGH the production surface it claims
to protect. (The ordering replay sorted a parallel vector with a copy of
the key; it would have passed against sort_unstable_by, the exact defect
it existed for.)
3. No fail-fast during mutation campaigns — expose all catching layers, not
the first failing target. (cargo test halts on the first target; with
--no-fail-fast the same mutation showed three catchers, and a second
mutation was caught only at the replay layer.)
4. Insertion-stable generated goldens — vocabulary-derived shape must depend
on stable item identity, never ordinal position.
Rule 4's law is the INVARIANT, not the mechanism:
insert one synthetic vocabulary member
existing-record churn == 0
new-record delta == 1
A content hash is today's way of satisfying it, not the requirement; any
stable mapping conforms and swapping it is not a violation. Writing the hash
into the norm would turn an implementation detail into scripture.
Single home by design — not duplicated into AGENTS.execution-surfaces.md,
because two copies of one law drift, which is what the status-drift rule
exists to prevent.
## Status reconciliation
Written fresh against the tree at fdcb222, NOT carried over from the earlier
unmerged reconciliation: a stale block patched with a stale fix stays stale.
The old branch is abandoned rather than cherry-picked.
What was wrong on main:
- #258 still described as "land with PR #297, in independent review; not on
main yet" — closed completed, both spec documents on main.
- own-lowered and own-bridge absent from the workspace list; both are
members.
- 5a listed as a future step — #255 closed completed today.
- own-diagnostics described as the data-only layer — it now carries the full
normalized contract.
What it says now: checkpoint-level status with each open step separating its
normative blocker from #250's preferred sequencing, #259 broken out per its
own five checkpoints (2 and 3 complete with counts, 1 partial, 4 not
started, 5 unblocked-but-not-done), and #260/#269 keeping the
sliceable-vs-declarable distinction. Preferred queue recorded: #256#259 remaining → #260/#269.
The proposals index row is corrected in the same change — a third status
surface for the same fact, and leaving it stale would repeat the defect.
#250 is a GitHub issue and cannot ride in a git commit; its body is
synchronised in the same move, per its own rule that both surfaces change
together.
Docs only. No code, fixtures or acceptance touched. The executable guard for
rule 4 currently implements `churn == 0`; extending it to `delta == 1`, plus
three review nitpicks from #321, lands in the follow-up test PR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJF7MBi1ijU5m9cJVWgQsM
@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The P-022 documentation now contains reconciled migration statuses, detailed own-bridge checkpoints, an updated proposal index entry, and four rules for parity validation and generated golden stability.

Changes

P-022 migration documentation

Layer / File(s)Summary
Reconcile migration status
docs/proposals/P-022-rust-core-migration.md, docs/proposals/README.md
The documents identify completed and active migration steps, own-bridge checkpoints, blockers, evidence, issue order, and the next planned step.
Define parity-work discipline
docs/proposals/P-022-rust-core-migration.md
The proposal defines oracle-based validation, mutation-backed regression tests, non-fail-fast mutation campaigns, and insertion-stable vocabulary-derived goldens.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers:claude

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly identifies the documentation changes: parity-work discipline and status reconciliation for P-022.
Description check✅ PassedThe description includes all required sections, explains the changes and verification, lists related issues, and completes the checklist.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/p022-parity-discipline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

@coderabbitai review

@PhysShellClaude

Copy link
Copy Markdown
OwnerAuthor

@coderabbitai review

Повторный триггер: автоматический nudge отработал в 09:11Z, а лимит сбрасывался ~09:19Z — на восемь минут раньше, поэтому команда прошла впустую. Сейчас квота доступна.

CI зелёный, combined status success, mergeable_state: clean. Изменение docs-only: раздел Parity-work discipline в P-022 плюс пере-сверка статуса против дерева на fdcb222.


Generated by Claude Code

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

@PhysShell, I will review PR #322, including the new parity-work rules and the status reconciliation against fdcb222.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/proposals/P-022-rust-core-migration.md`:
- Line 49: Update the Markdown lines containing issue references `#258` and `#259`
so each reference is prefixed with normal prose rather than beginning the line.
Apply the same adjustment to the corresponding reference at the later reported
location, preserving the surrounding wording and meaning while eliminating MD018
violations.
- Around line 660-672: Update the “Normative acceptance” section to explicitly
mark the new-record delta == 1 assertion as pending/not yet enforced, while
retaining churn == 0 as the currently executable guard. Ensure the documentation
does not imply that both acceptance criteria are already covered by tests.
- Line 9: Update the “Implementation status” heading to use the expected
Markdown heading hierarchy by changing it from level three to level two, unless
a valid missing parent heading is intentionally added.
In `@docs/proposals/README.md`:
- Line 44: Update the P-022 status in the proposals index to use the documented
“in progress” value instead of “in execution,” preserving the rest of the status
description unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ee760d9-8660-4847-a42d-3f6835e36c9c

📥 Commits

Reviewing files that changed from the base of the PR and between fdcb222 and 2cb3822.

📒 Files selected for processing (2)
  • docs/proposals/P-022-rust-core-migration.md
  • docs/proposals/README.md

Comment threaddocs/proposals/P-022-rust-core-migration.md Outdated
Comment threaddocs/proposals/P-022-rust-core-migration.md Outdated
Comment threaddocs/proposals/P-022-rust-core-migration.md
Comment threaddocs/proposals/README.md
Three of four CodeRabbit findings on 2cb3822, each checked against the tree
before acting (rule 1 of the section this PR adds).
- Rule 4 declared `churn == 0` AND `delta == 1` as normative acceptance while
`_insertion_churn()` gates only the first. A generator that dropped the new
record entirely would pass every executable check. The norm stays as written;
the gap is now stated rather than implied, which is the whole point of the
status-drift rule this PR introduces.
- `## Implementation status`: every other top-level section in the file is `##`;
this one was the only `###` hanging directly off the h1.
- Reflowed two paragraphs so `#258` and `#319` no longer begin a line. Renders
the same on GFM (ATX needs a space), but the pattern is fragile on
non-CommonMark renderers and trips MD018.
The fourth finding is rejected in the PR thread: "in execution" is pre-existing
on main, matches the proposal's own Status line, and changing only the index row
would manufacture the exact drift this PR removes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJF7MBi1ijU5m9cJVWgQsM
@PhysShell
PhysShell merged commit 3736ec0 into mainAug 7, 2026
42 checks passed
PhysShell added a commit that referenced this pull request Aug 7, 2026
…itpicks (#323)
P-022 rule 4 states two lines as normative acceptance; the executable guard
implemented only the first. This brings the guard up to the norm accepted in
#322, and no further.
_insertion_effect() returns churn / added / removed. Each of the three
mutations is caught by exactly one number, with the other two structurally
blind to it:
seed = sorted index churn=42 added=1 removed=0
iterate the golden's codes churn=0 added=0 removed=0
cap ledger at previous size churn=0 added=1 removed=1
(baseline) churn=0 added=1 removed=0
The third number came from a Codex finding during review: a generator capped at
its previous size emits the probe AND drops an existing code. The dropped
record never enters the churn comparison and the addition still counts one, so
both original numbers read clean while the ledger had not grown at all. This
does not widen rule 4 — a delta is a gain, and counting only additions was
measuring the stated norm wrong.
The churn gate sits behind the staleness check, so it was additionally verified
after regenerating under the mutation, where it fires with its own message.
Three nitpicks from the #321 review, also mutation-checked:
* analyzer_corpus read with expect, matching every other accessor in the file;
dropping the key from one case now fails naming it, where unwrap_or(false)
would have silently under-counted coverage.
* changed == unexplained asserted explicitly, since they move together by
construction and an added explanation channel must split them deliberately.
Recorded honestly: on a green tree this is 0 == 0 and proves nothing. Shown
to have teeth by a compound mutation (corrupt one recorded text so a
divergence exists, drop the unexplained increment) — it fires first, naming
the counter split rather than the divergence.
* every_optional_field_shape_is_still_exercised guards the nine arms the
generator rotates. Collapsing the two-evidence arm and regenerating fails
only this test: the divergence check still passes 47/47, because it asks
whether each case matches its own recorded text, never whether a shape
disappeared.
Test-only; no production code touched on either side.
Refs #255, #250.
PhysShell pushed a commit that referenced this pull request Aug 7, 2026
Review nitpick, and it is the same failure as the last three: the depth
test asserted something weaker than it claimed.
It built a FIXED 50-wrapper document and said it was "the deepest
document `from_json` still accepts". It was not — the parser reaches ~61
wrappers. Any guard between the two passes the test while rejecting
documents the door accepts, which is precisely the new-rejection-rule
the test exists to forbid.
Measured, by restoring the old shape and mutating against both:
guard 55 fixed-50: caught discovered: caught
guard 105 fixed-50: PASSES discovered: caught
So the boundary is now discovered rather than sampled: walk depth upward
until `from_json` refuses, keep the deepest document it accepted, and
require that one to survive `to_value`. That states the contract exactly
— "the guard never fires on anything the parser accepts" — instead of
picking a depth that happens to sit under it.
Three guard mutations caught (55, 105, and 16 as a regression).
Also fixed, from the same review: `#260/#269` opened line 76 of P-022 and
markdownlint read it as an ATX heading (MD018). Same class as the one
caught in #322; reflowed.
DECLINED, with the measurement: the review also asked to reconcile
P-022's "31/162, 31 mutations" against the PR body's "29/162, 27". The
direction is inverted — P-022 is right and the BODY is stale. Measured:
ownir validation ledger OK: 193 controls (31 accept / 162 reject)
31 accepts and 162 rejects is the post-`WellFormedness` ledger, and 31
mutations is 27 plus the four that category needed. The PR body still
carried the pre-seventh-category numbers; it is corrected there rather
than by editing the correct figures to match the wrong ones.
Refs #250, #259.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJF7MBi1ijU5m9cJVWgQsM
Sign up for freeto 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.

2 participants

@PhysShell@claude