Skip to content

feat(ownir)!: OwnIR v2 — must-understand proven_call (H1) + T0 Amendment 2 - #390

Merged
PhysShell merged 2 commits into
mainfrom
ccr-d3ed89e2-vnl6fk
Oct 3, 2026
Merged

PhysShell merged 2 commits into
mainfrom
ccr-d3ed89e2-vnl6fk

Conversation

@PhysShell

Copy link
Copy Markdown
Owner

Что и зачем

H1: state-protocol регионы впервые потребляют общую межпроцедурную heap-effect summary-архитектуру (H0). Вызов внутри [ProtocolRegion], который не касается ни entity, ни токена и диспатчится direct, больше не отказывается экстрактором: он уходит в ядро как must-understand flow op proven_call вместе с H0 source facts (новая секция heap_effects). Ядро допускает его только если общий summary-слой доказал, что вызов безвреден. Всё недоказанное остаётся отказом. Для этого OWNIR_VERSION 1 → 2 (по решению владельца) и T0 Amendment 2 (минимальная перепривязка harness identity из-за литерала версии).

Вызов в регионе До H1 С H1
Twice(21): direct, ничего не трогает, доказан harmless refusal (экстрактор) допущен, clean
TouchesGlobalState() / A→B→global / polluted SCC refusal (экстрактор) refusal (ядро, exit 2): writes.static is may
A → Console.WriteLine (transitive Unknown) refusal (экстрактор) refusal (ядро): writes.instance is unknown
Fill(buffer), внешний массив refusal (экстрактор) refusal (ядро): parameter 0 is borrow_mut
Mutates(order) / Escapes(order) use → OWN013 без изменений
Console.WriteLine("x"), вызов через интерфейс refusal (экстрактор) без изменений, тот же текст
R9 backdoor AnnotateLast() refusal (экстрактор) refusal (ядро): writes.instance is may

Transport.

  • proven_call {site, callee, line}, только внутри borrow_mut.
  • Секция heap_effects несёт только факты: запись call-site (выражение вызова; любая внешняя переменная читается как heap) и записи методов, достижимых по direct-рёбрам. Решает ядро.
  • Старое ядро v1 на v2-фактах: отказ по штампу (IR1), а без штампа — по неизвестному op (IR4).
  • Compatibility shim нет ни в одну сторону.

Решение. Принимается одним проходом по всему документу до любого lowering (ownlang/ownir.py::_admit_proven_calls, own-bridge/src/proven.rs).

Предикат (heap_effects.harmless / site_verdict) живёт в summary-слое, а не в typestate:

  • каждый callee внутри site и сам site;
  • каждый параметр и receiver ≤ borrow;
  • никаких instance/static/indirect writes;
  • returns == [];
  • ни одного Unknown.

Вне scope: logger/BCL allowlist, annotations, devirtualization, getters/ctors/operators в регионе, DB-side gaps.

Подробно: docs/notes/h1-proven-call.md, spec/OwnIR.md §2/§5.4, spec/Bridge.md BR-L14, T0 Amendment 2 в docs/notes/p022-263-t0-protocol-freeze.md.

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

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

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

  • python tests/run_tests.py (rc=0, ноль FAIL)
  • ruff check . и mypy
  • селфтесты затронутых скриптов (python scripts/<...>.py --selftest, audit selftests)
  • cargo fmt --check, cargo clippy --all-targets (новых предупреждений нет), cargo test --no-fail-fast
  • python scripts/protocol_gate.py --rust …/own-cli: 28 кейсов, 19 refusals, EF backend 24/24, 29 документов байт-в-байт на обоих CLI, 0 failures
  • python scripts/heap_effects_gate.py: H0 sidecar не сдвинулся, 50 inertness-прогонов
  • tests/test_proven_call.py:
    • C1: настоящее ядро v1 (ownlang/ @ 1c70e86 из git history) отказывает на v2-фактах, со штампом и без него;
    • C2/C3: 11 производных refusals, тексты закреплены Layer 2 goldens и реплеятся Rust;
    • C4: мутант «Unknown → harmless» ловится;
    • C5: мутант с выброшенным admission или выброшенным op ловится.
  • Rust-мутанты C4/C5 краснят replay-тесты
  • Ledgers перегенерированы своими writers: lowered, summaries, verdicts, renders, CLI, validation, repro (two-phase), byte-variants
  • S0 fix-candidates: additivity по всем 8 секциям (включая heap_effects), flag-off golden отличается одной строкой (третий amendment записан)
  • P-022 merge gate:
    • на коммите 1 allowed;
    • только литерал инструмента — REFUSED (b92f08c990fc vs 1a26aa63fd5f);
    • после Amendment 2 allowed;
    • все T0-контроли совпадают с Amendment 1 (17/17, 10/10, 10/10, 7/7, 4/4, 9/9, 12/12, 26/26, 15/15, 12/12).
  • CI-джоб C# extractor прогнан локально шаг за шагом:
    • шаги 3–23 и 27 зелёные, включая Tier B с OWN_TIERB_REQUIRED=1 (verify-delta 28/28, verify-target 65/65, certify 32/32);
    • шаги 24–26 (owen-rewrite «read-only parent / failed publication») падают одинаково и на нетронутом main при запуске под root: root игнорирует права на запись. Это артефакт контейнера, не этого PR; на GitHub runner'ах (non-root) они проверяются по-настоящему.

Связанные issue

Refs P-036 / P-037 / P-022 #263 (T0 Amendment 2). Отдельного issue нет.

Чеклист

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

🤖 Generated with Claude Code

https://claude.ai/code/session_011ZFvhLx1fM9Gerg4dKsZcL


Generated by Claude Code

claude added 2 commits October 3, 2026 15:42
A call inside a state-protocol region that touches neither the entity nor the
token used to be refused by the extractor. It is now handed to the core as the
must-understand flow op `proven_call` (site, callee) together with the H0
heap-effect FACTS it is judged against (a new top-level `heap_effects`
section), and the core admits it only when the shared summary layer proves it
harmless. Everything unproven stays refused; nothing the frontend could not
classify `direct` reaches the core at all, so external, virtual, delegate and
local-function calls are refused exactly as before, with the same text.

    Twice(21) in a region           admitted, clean
    TouchesGlobalState()            refused by the core: writes.static is may
    A -> B -> Console.WriteLine     refused by the core: writes.instance is unknown
    Console.WriteLine("x")          refused by the extractor, unchanged
    Mutates(order)/Escapes(order)   use -> OWN013, unchanged

The decision lives in the summary layer (heap_effects.harmless/site_verdict)
and is applied by one document-level pass before anything is lowered
(ownir.py _admit_proven_calls, own-bridge proven.rs), so no lowering path can
carry a proven_call past the proof. Predicate v1 is strict: every parameter
and the receiver <= borrow, no write of any kind, nothing returned, no Unknown,
checked on every callee in the site and on the site itself. The frontend
emits facts only; the dispatch classifier is shared with H0.

A new flow op is a vocabulary change, so OWNIR_VERSION moves 1 -> 2 on every
producer (core, Rust door, extractor, OwnTS). A v1 core refuses v2 facts on
the stamp and, with the stamp stripped, on the unknown op; a v2 core refuses
v1 facts. No shim either way. LOWERED_VERSION does not move: an admitted
proven_call lowers to nothing.

Evidence: the protocol-sample cases H1a-H1j (positive, transitive, SCC,
global, polluted SCC, transitive Unknown, outer mutation, entity use) and
refused R18/R19; R9's backdoor is now refused by the core
(writes.instance is may). tests/test_proven_call.py holds C1 (the real v1
core, taken out of git history, refuses v2 facts), C2/C3 (eleven derived
refusals pinned by the Layer 2 goldens and replayed by Rust), C4 (an
Unknown-is-harmless mutant is caught) and C5 (a dropped admission or a dropped
op is caught). Python and Rust refusal texts are byte-identical.

Migration: current input documents restamped by a JSON-aware move (top-level
key only, verified by re-parse); the C#-derived typestate documents
regenerated from C# (one line each); every golden family regenerated by its
own writer (Layer 2, summaries, verdicts, renders, CLI, validation ledger,
repro two-phase); the SARIF stamp copy in own-bridge render.rs bumped and
tied to own_ir::OWNIR_VERSION at compile time. The S0 additivity fixture
gains a protocol region so the new section is covered; the flag-off golden
moves one line (third amendment, tests/goldens/README.md). Historical evidence
(corpus/ownership-lab/h29, docs/evidence) is not rewritten.

The T0 instrument's generated facts follow in the next commit (Amendment 2);
until then `perf-calibration-facts-current` is red by design.

BREAKING CHANGE: `ownir_version` is 2. Facts stamped 1 are refused; build the
extractor and the core from the same commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ZFvhLx1fM9Gerg4dKsZcL
OwnIR moved to v2 in the previous commit (the must-understand `proven_call`
of H1). The instrument's `facts` calibration generator stamps `ownir_version`
on every document it writes, so one literal moves: "ownir_version": 1 -> 2.
Nothing else in the harness source set changes. That literal is the only
cause of the identity move:

    1a26aa63fd5fbbe06e7ae72dd5e1c8f2d611bff8856af4a5b93ae36d2d23a9b1   before
    b92f08c990fcf6d74df29aad333b330b6c3c4f9e1c1bad55efe8164c39dea57c   after

Re-bound, in the order the chain runs, exactly as Amendment 1 did: the digest
in the policy freeze (step 4), in the ratified design constants (step 5), and
in the training preregistration's bindings (step 6) — and with it
design_constants_blob_sha1 (0ff316d -> 1059a69), which moved because
the design-constants artifact itself was re-bound. The pyproject comment that
names the identity follows.

The frozen T0 records this as Amendment 2, a new state of the contract under
the owner's ruling (OwnIR v2 and this amendment approved for H1, on the
Amendment 1 principle, for nothing else): T0-1 names the new identity, the
status block points at the amendment, and the amendment says what moved and
what did not. FROZEN and collection_authorized are unchanged. No rule,
budget, population, statistic, roll-up, host predicate or retry budget
changes; the measurement methodology is untouched — this is a schema-transport
change carried by the generated calibration documents, not a change to the
experiment. Committed evidence of past runs is not rewritten.

Merge gate, observed: with the literal moved and nothing re-bound it REFUSED
(instrument_matches_t0: b92f08c990fc vs T0's 1a26aa63fd5f); after the
re-binding it allows. perf-calibration-facts-current was red between the
core's version move and this literal, and holds after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ZFvhLx1fM9Gerg4dKsZcL
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.

2 participants