spec(ownir): add machine-readable JSON Schema, pinned to code with no new dep - #175
Conversation
… new dep OwnIR now has a machine grammar to sit alongside the prose spec (spec/OwnIR.md): spec/ownir.schema.json (JSON Schema draft 2020-12, ownir_version as const:0). It mirrors the contract the Python validator (ownlang/ownir.py::load) enforces — envelope, owned-resource records, flow bodies, DI graph, reactive effects — and is shaped for the P-022 `own-ir` Rust crate to generate serde types from: the flow-op vocabulary is a `oneOf` discriminated on `op`, and the enums (resource kinds, DI lifetimes, param effects) are closed. The schema's trigger has fired: a second language-native type set (the Rust crate in #170) is arriving, so a single source both are generated from stops the two hand-maintained validators from drifting. The core cannot import a jsonschema validator (zero-dependency constraint), so instead of validating documents this binds the schema's *vocabulary* to the code's authoritative sets in tests/test_ownir.py: - resourceKind enum == _KNOWN_RESOURCE_KINDS (the load() routing set) - diLifetime enum == di.LIFETIMES - ownir_version const == OWNIR_VERSION - every flowOp const lowers through _lower_flow without the fail-loud "unknown op" raise; a bogus op the schema omits still raises Schema and validator therefore cannot drift without a red build, no dependency added. Registered in spec/README.md; tech-debt register item 3 updated to shipped. 228/228 bridge checks pass; full suite green.
📝 WalkthroughWalkthroughAdds a JSON Schema ( ChangesOwnIR schema formalization
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 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 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:45ac5cc783
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The schema-consistency imports (_KNOWN_RESOURCE_KINDS, DI_LIFETIMES) tripped ruff's import-order check on the PR; merge them into the sorted block.
…inds Three P2 findings from the Codex review on the schema PR: 1. Null resource types. The reference loaders (Python load(), the Rust own-ir parity tests) accept and preserve `"type": null` — load() only rejects a non-null non-string. The schema made `type`/`source_type` string-only, so it (and generated serde types) would reject documents the pipeline accepts. Widen them to ["string","null"] — maps to Option<String>. `source` widened too (load() never constrained it). 2. paramEffect never pinned. The schema advertised a closed paramEffect enum but the drift test jumped straight from diLifetime to flow ops, so it never bound. Extract the effect tuple in load() to a named authority `_PARAM_EFFECTS` and assert schema.paramEffect == it. 3. Flow-op bind was one-directional. The test only proved schema-ops lower; a handled op the schema forgot stayed green. Extract the lowerer's vocabulary to `_FLOW_OPS` (the _lower_flow `else` now distinguishes "declared-but-unhandled" from "unknown vocabulary") and assert schema.flowOp consts == _FLOW_OPS — both directions. The drive-test still lowers every declared op so a phantom set entry fails. Both _FLOW_OPS and _PARAM_EFFECTS now mirror _KNOWN_RESOURCE_KINDS: a named frozenset used by load()/_lower_flow AND bound to the schema by equality, so schema and validator cannot drift either way. 230/230 bridge checks; ruff + mypy --strict + full suite green.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@spec/ownir.schema.json`:
- Around line 85-108: Update the resourceRecord schema to include the missing
fact identifiers event, handler, and lambda alongside the existing
line/released/resource/type/source/source_type fields. Keep them additive and
optional like the other preserved fields so the generated own-ir Rust serde
types round-trip the full subscription/capture facts used in tests. Use
resourceRecord as the anchor in spec/ownir.schema.json so the schema remains the
source of truth for all core identifying fields.
🪄 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: 4e0f50d3-196e-4a1d-81e2-906158633435
📒 Files selected for processing (5)
docs/notes/tech-debt-register.mdownlang/ownir.pyspec/README.mdspec/ownir.schema.jsontests/test_ownir.py
Uh oh!
There was an error while loading. Please reload this page.
CodeRabbit (Major): the resourceRecord schema omitted the event, handler, and lambda fields that every subscription/timer/capture fact carries — event/handler are core identifying fields (finding messages, rendered output) read as strings via sub.get(), and lambda is the bool flag (ownir.py:2171) marking an un-detachable inline-lambda handler. Without them the schema-generated Rust own-ir serde types would drop the fields and lose round-trip fidelity for real facts, undermining the schema's single-source purpose. Added additive/optional, matching code semantics (event/handler string, lambda bool). 230/230 bridge checks; full suite green.
Uh oh!
There was an error while loading. Please reload this page.
Что и зачем
Добавляет машинную грамматику OwnIR —
spec/ownir.schema.json(JSON Schema draft 2020-12,ownir_versionкакconst:0) — рядом с прозаической спекойspec/OwnIR.md. Схема зеркалит контракт, который проверяет валидаторownlang/ownir.py::load(), и спроектирована как единый источник, из которого крейтown-ir(P-022, #170) генерирует serde-типы. Ядру нельзя тянутьjsonschema(zero-dependency), поэтому вместо валидации документов тестtests/test_ownir.pyпривязывает словарь схемы к авторитетным множествам в коде — так схема и валидатор не могут разъехаться без красной сборки, без новой зависимости.Тип изменения
Как проверено
python tests/run_tests.py— вся сборка зелёная (ownir: 230/230)ruff check .иmypy(mypy--strictнадownlang) — чистоpython3 -c "import json; json.load(open('spec/ownir.schema.json'))"— схема валидный JSONПривязка схема↔код в тесте:
resourceKind == _KNOWN_RESOURCE_KINDS,diLifetime == di.LIFETIMES,paramEffect == _PARAM_EFFECTS,flowOp consts == _FLOW_OPS(в обе стороны + drive-test лоуэрит каждый op),ownir_version const == OWNIR_VERSION.Связанные issue
Refs #170 (крейт
own-ir— второй набор type-ов, для которого схема станет источником генерации). Closes — none.Чеклист
tests/test_ownir.py)spec/README.md,docs/notes/tech-debt-register.mdп.3 → shipped)spec:,fix:,style:)