Skip to content

feat(rfc0024): green — P1/P2/P3 pipeline properties + canonical decode fix - #363

Merged
jensholdgaard merged 2 commits into
mainfrom
rfc0024-green-properties
Jul 5, 2026
Merged

feat(rfc0024): green — P1/P2/P3 pipeline properties + canonical decode fix#363
jensholdgaard merged 2 commits into
mainfrom
rfc0024-green-properties

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jul 5, 2026

Copy link
Copy Markdown
Owner

What

Third RFC 0024 green slice: the three pipeline properties, discharging RFC0024.3 (P1, ourios-parquet), RFC0024.4 (P2, ourios-miner), RFC0024.5 (P3, ourios-miner) — stub → live. Generated OTLP batches (adversarial + calibrated, per §3.2) run through the real pipeline: MinerCluster with a SharedRecordSink → RFC 0005 WriterReader.

  • P1 — round-trip fidelity. Per-partition write→read with full MinedRecord struct equality, plus OTLP-level body fidelity on the read-back rows (string bodies reconstruct bit-identically, structured bodies decode canonical-JSON equal). The writer's two documented loud rejections — §3.2 timestamp overflow on either column, and UnsupportedAbsentBody — are pinned as rejections, never silent drops.
  • P2 — no silent merge. Every emitted row must render back to its own record's body: clean attaches store no body, so a wrong template renders wrong bytes; diverted rows must retain the original verbatim. Byte-fidelity is the §3.1 invariant under arbitrary input.
  • P3 — RFC 0023 bounds. Tiny configured bounds (max_templates=3, max_node_children=2, max_line_tokens=8); leaf count checked after every ingest, over-long lines always divert, diverted rows keep their bodies. Per-node fan-out has no cluster-level observation surface — it stays pinned by the tree-level fan-out property and RFC0023.3 (noted in the test doc).

The suite paid for itself on its first run — two real findings

  1. Canonical decode gap (fixed here, ourios-core). The canonical codec rejected its own encoder's output for two legal spellings: an empty AnyValue nested in arrays/kvlists ({}, proto3 oneof-unset — opentelemetry-proto's deserializer errors "no known keys found") and explicit "value": null kvlist entries in the hand-built fallback path. Stored bytes containing either were unreadable on the query path. The fallback decoder now accepts both, pinned by empty_any_value_round_trips_at_every_nesting and attributes_with_absent_and_empty_values_round_trip. Encoder bytes are unchanged (the exact-bytes pin still passes), so no stored data is affected — this widens what the reader accepts.
  2. Absent-body poison pill (filed as Absent-body OTLP records permanently wedge their partition buffer (UnsupportedAbsentBody) #362, not fixed here). A legal wire-absent body flows receiver → miner (BodyKind::Absent) → encode, which rejects it permanently — and the ingest sink retains the buffer on flush error, wedging that partition forever. The schema-level fix is an RFC 0005 amendment (§3.5 migration plan), so this PR pins the current rejection loudly and defers the representation change to the RFC process.

Both findings are exactly RFC 0024 §2's thesis: "an input shape we didn't anticipate" as a generated, repeatable test class.

Invariants / hazards

  • §3.3 (bit-identical reconstruction) / hazard 7: P1/P2 extend the reconstruction property to arbitrary generated input, through storage.
  • Hazard 1 (miner correctness) / §3.1: P2 is the no-silent-merge invariant under generation; P3 pins the RFC 0023 bounds mid-stream.
  • §3.5 (schema): no schema change; the absent-body gap is deliberately routed through the RFC process (Absent-body OTLP records permanently wedge their partition buffer (UnsupportedAbsentBody) #362) instead of an improvised ordinal.
  • The ourios-core decode fix touches a production path: it is strictly widening (decode-only, encoder bytes unchanged), covered by new unit tests plus the existing exact-bytes pin.
  • .proptest-regressions files are committed per RFC 0024 §6 (counterexamples become permanent regression cases).

Verification

  • cargo fmt --all --check clean
  • cargo clippy --all-targets --all-features -- -D warnings clean (workspace)
  • cargo test --all-features — 123 suites, 912 tests, 0 failures

Remaining for the RFC: slice (d) — the P4 query oracle (RFC0024.6) + the adversarial umbrella (RFC0024.7).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added broader support for empty and missing structured values, improving OTLP JSON decoding in edge cases.
    • Expanded property-based coverage for log ingestion and storage, including end-to-end round-trip checks.
  • Bug Fixes

    • Correctly preserves empty nested values, absent fields, and explicit nulls instead of misreading them.
    • Improves handling of rejected records so unsupported cases are surfaced consistently rather than silently altered.

…e fix

Discharges RFC0024.3/.4/.5: generated OTLP batches (both modes)
through MinerCluster → RFC 0005 writer → reader. P2 found a real
decode gap on its first run — the canonical codec rejected its own
encoder's output for empty AnyValues ({}, proto3 oneof-unset) and
explicit "value":null kvlist entries; the fallback decoder now
accepts both spellings, pinned by two new unit tests. P1 also
surfaced #362 (absent-body records wedge their partition buffer) —
pinned as a documented loud rejection until the RFC 0005 amendment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jensholdgaard
jensholdgaard requested a review from Copilot July 5, 2026 05:32
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jensholdgaard, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 53a6bb44-972e-4b4c-90d1-0c1e83bd1bd8

📥 Commits

Reviewing files that changed from the base of the PR and between 74867ae and 30e71f6.

📒 Files selected for processing (1)
  • crates/ourios-miner/tests/rfc0024_properties.rs
📝 Walkthrough

Walkthrough

Modifies canonical JSON decoding in ourios-core to treat null and empty objects as absent AnyValue/KeyValue values, with new codec tests. Adds ourios-testgen (and ourios-miner) dev-dependencies to ourios-miner and ourios-parquet, replacing ignored RFC0024 test stubs with active property-based tests and a proptest regression seed file.

Changes

OTLP Absent-Value Decoding

Layer / File(s) Summary
Absent-value decoding logic
crates/ourios-core/src/otlp.rs
json_to_av now accepts JSON null and {} as an unset AnyValue; json_to_kv maps missing or explicit null "value" fields to KeyValue.value = None.
Round-trip codec tests
crates/ourios-core/src/otlp.rs
New tests verify empty AnyValue round-trips nested in arrays/kvlists and attribute lists containing absent or None-valued KeyValues.

RFC0024 Property Tests (Miner & Parquet)

Layer / File(s) Summary
Miner dev-dependency and regression seed
crates/ourios-miner/Cargo.toml, crates/ourios-miner/tests/rfc0024_properties.proptest-regressions
Adds ourios-testgen as a dev-dependency and a proptest regression seed file for RFC0024 tests.
Miner no-silent-merge and bounds tests
crates/ourios-miner/tests/rfc0024_properties.rs
Replaces ignored stubs with synthetic_manifest, template_map, assert_no_silent_merge, and active tests rfc0024_4_no_silent_merge_over_generated_batches and rfc0024_5_bounds_hold_over_generated_streams.
Parquet dev-dependency wiring
crates/ourios-parquet/Cargo.toml
Adds ourios-testgen and ourios-miner path dependencies under dev-dependencies.
Parquet storage round-trip test
crates/ourios-parquet/tests/rfc0024_properties.rs
Replaces the ignored RFC0024.3 stub with synthetic_manifest, assert_round_trip, and a proptest! harness validating writer rejection, Parquet write/read equality, and OTLP body fidelity.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • jensholdgaard/ourios#62: Both PRs modify the OTLP canonical JSON encode/decode logic in crates/ourios-core/src/otlp.rs.
  • jensholdgaard/ourios#176: Both PRs adjust canonical JSON decoding of AnyValue/KeyValue around null/absent value shapes in the same file.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main RFC 0024 pipeline property work plus the canonical decode fix.
Description check ✅ Passed The description is detailed and on-topic, covering summary, verification, and RFC context, though it uses custom headings instead of the template.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rfc0024-green-properties

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR implements RFC 0024’s third “green slice” by turning the P1/P2/P3 pipeline property tests from stubs into live proptest suites, and fixes a production canonical JSON decode gap in ourios-core so the decoder accepts legal “empty” OTLP AnyValue spellings that can appear on the wire.

Changes:

  • Implemented RFC0024 property tests: P1 (parquet write→read round-trip fidelity), P2 (no silent merge), and P3 (RFC0023 bounds under tiny caps) using ourios-testgen adversarial + calibrated generators.
  • Widened ourios_core::otlp::canonical decoding to accept {} and null as legal “no value” spellings for AnyValue, with new unit tests to pin the behavior.
  • Added dev-dependencies (ourios-testgen, ourios-miner) and committed .proptest-regressions seeds per RFC 0024 guidance.

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
crates/ourios-parquet/tests/rfc0024_properties.rs Implements P1 round-trip fidelity through miner → writer → reader with OTLP-level body fidelity assertions.
crates/ourios-parquet/Cargo.toml Adds dev-deps needed to run the parquet-side RFC0024 property suite.
crates/ourios-miner/tests/rfc0024_properties.rs Implements P2 (no silent merge) and P3 (bounds) property tests using generated OTLP batches.
crates/ourios-miner/tests/rfc0024_properties.proptest-regressions Adds saved proptest counterexample seeds for deterministic regression coverage.
crates/ourios-miner/Cargo.toml Adds ourios-testgen dev-dependency for the miner-side property tests.
crates/ourios-core/src/otlp.rs Fixes canonical decode to accept legal empty/unset AnyValue spellings and adds unit tests.
Cargo.lock Updates lockfile for newly added workspace/dev dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ourios-miner/tests/rfc0024_properties.rs

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
crates/ourios-core/src/otlp.rs (1)

825-887: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage; consider pinning the decoder's byte-level contract directly.

The round-trip tests exercise the new null/{} acceptance indirectly, via whatever bytes the fast (opentelemetry-proto) serializer happens to emit. Adding a direct test that feeds literal bytes (b"null", b"{}", and [{"key":"k","value":null}]) into decode_any_value/decode_attributes would pin the decoder's accepted wire contract independently of any future change to the fast-path encoder.

♻️ Example additional test
#[test]
fn decode_any_value_accepts_literal_null_and_empty_object() {
    for bytes in [b"null".as_slice(), b"{}".as_slice()] {
        let back = decode_any_value(bytes).expect("decode");
        assert_eq!(back, AnyValue { value: None });
    }
}

#[test]
fn decode_attributes_accepts_literal_null_value() {
    let bytes = br#"[{"key":"k","value":null}]"#;
    let back = decode_attributes(bytes).expect("decode");
    assert_eq!(
        back,
        vec![KeyValue { key: "k".to_string(), value: None, ..Default::default() }]
    );
}
🤖 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 `@crates/ourios-core/src/otlp.rs` around lines 825 - 887, Add direct decoder
contract tests in the otlp round-trip test module so acceptance of literal wire
forms is pinned independently of the serializer. Update the test area around
decode_any_value and decode_attributes to feed raw bytes for null, {}, and a
JSON attribute entry with value:null, then assert the decoded AnyValue and
KeyValue results match the expected empty/absent values. Keep the existing
round-trip tests, but add these byte-level cases to explicitly verify the
decoder behavior.
crates/ourios-miner/tests/rfc0024_properties.rs (1)

96-136: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Asymmetric divert/lossy assertions across body kinds.

The Some(Body::String(s)) arm asserts lossy_flag and verbatim mined.body retention when diverted to NO_TEMPLATE (lines 107-115), but the Structured and None arms have no equivalent check. Reconstruction equality partially covers the merge invariant for these kinds, but explicitly asserting the divert/lossy contract for structured/absent bodies too would tighten P2 coverage and catch regressions in ingest_structured/absent-body handling that reconstruction alone might miss (e.g. a wrongly-cleared lossy_flag on a correctly-reconstructing row).

🤖 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 `@crates/ourios-miner/tests/rfc0024_properties.rs` around lines 96 - 136, The
divert/lossy contract is only asserted for Body::String, leaving
Body::Structured and None under-tested. In the property test loop in
rfc0024_properties.rs, extend the existing NO_TEMPLATE checks in the match over
original.body so structured and absent bodies also verify the expected
lossy_flag and retained payload behavior via mined.template_id,
mined.lossy_flag, and mined.body. Use the same reconstruct/mined assertions
pattern already present in the Some(Body::String) arm to tighten coverage for
ingest_structured and absent-body handling.
🤖 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.

Nitpick comments:
In `@crates/ourios-core/src/otlp.rs`:
- Around line 825-887: Add direct decoder contract tests in the otlp round-trip
test module so acceptance of literal wire forms is pinned independently of the
serializer. Update the test area around decode_any_value and decode_attributes
to feed raw bytes for null, {}, and a JSON attribute entry with value:null, then
assert the decoded AnyValue and KeyValue results match the expected empty/absent
values. Keep the existing round-trip tests, but add these byte-level cases to
explicitly verify the decoder behavior.

In `@crates/ourios-miner/tests/rfc0024_properties.rs`:
- Around line 96-136: The divert/lossy contract is only asserted for
Body::String, leaving Body::Structured and None under-tested. In the property
test loop in rfc0024_properties.rs, extend the existing NO_TEMPLATE checks in
the match over original.body so structured and absent bodies also verify the
expected lossy_flag and retained payload behavior via mined.template_id,
mined.lossy_flag, and mined.body. Use the same reconstruct/mined assertions
pattern already present in the Some(Body::String) arm to tighten coverage for
ingest_structured and absent-body handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2a5ff590-e304-4966-b58f-70f2d9377455

📥 Commits

Reviewing files that changed from the base of the PR and between 6b696e4 and 74867ae.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • crates/ourios-core/src/otlp.rs
  • crates/ourios-miner/Cargo.toml
  • crates/ourios-miner/tests/rfc0024_properties.proptest-regressions
  • crates/ourios-miner/tests/rfc0024_properties.rs
  • crates/ourios-parquet/Cargo.toml
  • crates/ourios-parquet/tests/rfc0024_properties.proptest-regressions
  • crates/ourios-parquet/tests/rfc0024_properties.rs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 8 changed files in this pull request and generated no new comments.

@jensholdgaard
jensholdgaard merged commit 563f540 into main Jul 5, 2026
22 checks passed
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