feat(obligations): obligation protocols — barrier-sensitive project invariants (P-025, first slice)#176
Conversation
…nvariants (P-025, first slice)
A new sidecar analysis family (the di.py/effects.py pattern): project-declared
obligation protocols checked path-sensitively per method. An opening event
(IsLoaded = false) creates an obligation, a closing event discharges it, and it
must be closed before every declared barrier (OnPropertyChanged(Document)) and,
by default, every method exit (return / throw / end of body).
- ownlang/obligations.py: matchers, protocols, event trees (assign/call/return/
throw/if/while), the {OPEN, CLOSED} set lattice with union joins (the
definite/maybe split of OWN002 vs OWN009), local loop fixpoints with
single-shot emission, open-site provenance, the opaque-write discharge
asymmetry (may discharge, never invents), and explicit method scoping as the
false-positive throttle.
- ownlang/ownir.py: additive OwnIR blocks protocols[]/protocol_functions[]
(no version bump — the services/effects precedent; internal vocabularies are
fail-loud per IR4, duplicate protocol names rejected at load),
_protocol_findings beside _di_findings/_effect_findings, line-free messages
(OwnAudit fingerprints on path|rule|message), evidence flow
opened -> barrier -> late close (SARIF codeFlows).
- Codes OBL001-004 (barrier/exit x definite/maybe) + OBL005 (dead-scope
advisory, never fails the build) in diagnostics.TITLES/EXPLANATIONS; the
cmd_ownir summary now names the advisory codes present instead of
hardcoding OWN050.
- spec/OwnIR.md §8 (Rules -> §9, Conformance -> §10) + ownir.schema.json
$defs (protocol/protocolMatcher/protocolOpenClose/protocolEvent/
protocolFunction), vocabularies pinned both ways by the tests.
- tests/test_obligations.py (70 checks) + killer-demo fixtures: OBL001 at
BigDocumentViewModel.cs:241 (IsLoaded=false at 184, PropertyChanged(Document)
at 241 on the warnings branch, closed only at 260), and its fixed twin
staying silent.
- docs/proposals/P-025-obligation-protocols.md: decisions on the record, the
Roslyn extractor emission slice (designed; extractor is CI-only), the
MOS-based interprocedural phase, and non-goals.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NXzqX7Qwn5QzBLGVCATdgm
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a new obligation-protocol analysis feature (P-025 "Own.Protocols") with a path-sensitive checker module, OwnIR schema/spec extensions for ChangesObligation protocol analysis feature
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Facts as OwnIR facts
participant OwnIR as ownir.load/check_facts
participant Obligations as obligations.check_protocols
participant Walker as _Walker
participant Diagnostics as diagnostics.TITLES
Facts->>OwnIR: protocols[], protocol_functions[]
OwnIR->>Obligations: parse_protocol/parse_method, check_protocols
Obligations->>Walker: run(protocol, method)
Walker-->>Obligations: Violation list
Obligations-->>OwnIR: sorted Violations / unmatched_scopes
OwnIR->>Diagnostics: map to OBL001-OBL005 codes
Diagnostics-->>OwnIR: titles/explanations
OwnIR-->>Facts: Finding objects (errors + advisory)
Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Живое демо слайса (обе фикстуры лежат в Тот же finding в SARIF несёт кликабельный Чистый близнец ( Правило целиком — данные, не код (фрагмент из фикстуры): {"name": "DocumentLoading",
"opens": {"kind": "assign", "target": "IsLoaded", "value": false},
"closes": {"kind": "assign", "target": "IsLoaded", "value": true},
"barriers": [{"kind": "call", "callee": "OnPropertyChanged",
"args": ["Document", "Rows", "Totals", "SelectedItem"]}],
"allow": [{"kind": "call", "callee": "OnPropertyChanged",
"args": ["IsLoaded", "IsBusy", "Progress", "StatusText"]}],
"scope": {"methods": ["BigDocumentViewModel.LoadBigDocument"]}}Следующие слайсы по P-025: эмиссия событий из Generated by Claude Code |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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-025-obligation-protocols.md`:
- Around line 26-33: The fenced examples in the proposal document are missing
language tags, which will trigger markdownlint MD040. Update the unlabeled code
fences in the relevant sample blocks, using csharp for the C# snippet and text
(or a list-style fence) for the protocol-verbs example. Check the surrounding
proposal sections so both affected fenced blocks are labeled consistently.
In `@ownlang/__main__.py`:
- Around line 351-359: The advisory summary has been generalized beyond OWN050,
but nearby documentation still refers to OWN050-only behavior. Update the
`cmd_ownir` docstring and the comment block above the summary logic in
`ownlang.__main__` so they describe advisory notes generically and mention both
OWN050 and OBL005 where appropriate, keeping the wording aligned with the
existing `summary`/`note_codes` behavior.
In `@ownlang/diagnostics.py`:
- Around line 190-214: Add missing EXPLANATIONS entries for OBL002 and OBL004 in
diagnostics.py so they have the same fix guidance as OBL001 and OBL003. Mirror
the existing OBL001/OBL003 wording style and keep the descriptions aligned with
the corresponding “maybe” versions emitted by _OBL_CODE in ownlang/ownir.py.
Ensure the new entries are discoverable by ownlang explain for OBL002 and
OBL004, not just the title.
🪄 Autofix (Beta)
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: 9e81d411-ac48-4f1d-9625-23cfcf64e138
📒 Files selected for processing (12)
docs/ROADMAP.mddocs/proposals/P-025-obligation-protocols.mddocs/proposals/README.mdownlang/__main__.pyownlang/diagnostics.pyownlang/obligations.pyownlang/ownir.pyspec/OwnIR.mdspec/ownir.schema.jsontests/fixtures/ownir/protocol_isloaded_clean.facts.jsontests/fixtures/ownir/protocol_isloaded_violation.facts.jsontests/test_obligations.py
| ```csharp | ||
| IsLoaded = false; // the document tree is now inconsistent — on purpose | ||
| RebuildIndexes(); | ||
| if (hasWarnings) | ||
| OnPropertyChanged(nameof(Document)); // ← published the broken object | ||
| IsLoaded = true; | ||
| OnPropertyChanged(nameof(Document)); // this one is fine | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add language tags to the fenced examples.
Both fenced blocks are unlabeled, which will trip markdownlint MD040. Use csharp for the sample and text (or a list) for the protocol-verbs block.
Also applies to: 50-55
🤖 Prompt for 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.
In `@docs/proposals/P-025-obligation-protocols.md` around lines 26 - 33, The
fenced examples in the proposal document are missing language tags, which will
trigger markdownlint MD040. Update the unlabeled code fences in the relevant
sample blocks, using csharp for the C# snippet and text (or a list-style fence)
for the protocol-verbs example. Check the surrounding proposal sections so both
affected fenced blocks are labeled consistently.
Source: Linters/SAST tools
- P-025: tag the protocol-verbs fence as text (MD040; the C# fence was already tagged) - __main__: de-OWN050-ify the cmd_ownir docstring and the advisory comment block — the band now carries OBL005 too - diagnostics: EXPLANATIONS for the maybe-siblings OBL002/OBL004, mirroring OBL001/OBL003 so ownlang explain answers all four symmetrically Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NXzqX7Qwn5QzBLGVCATdgm
Что и зачем
Новое sidecar-семейство анализов (паттерн di.py/effects.py): obligation-протоколы — проектные темпоральные инварианты вида «
IsLoaded = falseобязан статьtrueдоOnPropertyChanged("Document")и до любого выхода из метода».opensсоздаёт обязательство,closesгасит, барьеры — сконфигурированные вызовы (с различающим аргументом и allow-списком) плюс по умолчаниюreturn/throw/конец тела. Проверка path-sensitive: решётка-множество над {OPEN, CLOSED} с union на слияниях (definite/maybe-расщепление — прецедент OWN002 vs OWN009), локальный fixpoint для циклов с одноразовой эмиссией. Коды OBL001–004 + advisory OBL005 (мёртвый scope). Правила и события — аддитивные блоки OwnIRprotocols[]/protocol_functions[](без бампа версии, прецедентservices/effects; словари fail-loud по IR4; сообщения line-free под фингерпринты OwnAudit). Killer demo:python -m ownlang ownir tests/fixtures/ownir/protocol_isloaded_violation.facts.json→ OBL001 вBigDocumentViewModel.cs:241с трейсом открыто@184 → барьер@241 → закрыто только@260 (в SARIF — codeFlows). Дизайн, границы и слайс эмиссии из Roslyn-экстрактора — вdocs/proposals/P-025-obligation-protocols.md(экстрактор не тронут: CI-only, правится отдельным слайсом).Тип изменения
Как проверено
python tests/run_tests.py— зелёный, включая новые 70/70 obligation-проверок (tests/test_obligations.py)ruff check .иmypy(strict) — чистоpython -m ownlang ownir(нарушение → exit 1 + OBL001; чистый близнец → exit 0; OBL005-only → exit 0, warning); SARIF codeFlows проверенload()+ first-wins на прямом пути; барьер, затенённыйopens, отклоняется; схема↔парсер выровнены:protocolOpenCloseсо структурно обязательнымvalue, null-семантика,minLength)Связанные issue
Нет. Refs:
docs/proposals/P-025-obligation-protocols.md(roadmap: эмиссия из экстрактора → межпроцедурные summaries на MOS/SCC → атрибуты/инференс правил → потребление в OwnAudit).Чеклист
🤖 Generated with Claude Code
https://claude.ai/code/session_01NXzqX7Qwn5QzBLGVCATdgm
Generated by Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation