Skip to content

feat(miner): rfc 0023 green pt1 — bounded template memory (RFC0023.1–.5) - #354

Merged
jensholdgaard merged 4 commits into
mainfrom
rfc0023-green-pt1
Jul 4, 2026
Merged

feat(miner): rfc 0023 green pt1 — bounded template memory (RFC0023.1–.5)#354
jensholdgaard merged 4 commits into
mainfrom
rfc0023-green-pt1

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Implements RFC 0023 §3.1's three bounds and turns five of the seven §5 stubs green.

What

  • max_node_children (default 100)descend/descend_mut route unseen tokens through a <*> wildcard child once a prefix node's keyed children hit the cap. Read and write sides share the routing rule (children only grow, so a token's route can never diverge between them); attach below the wildcard child stays simSeq-gated — routing is not merging.
  • max_templates (default 20,000) — a per-tenant Drain-leaf ceiling on a new TenantState.leaf_count (incremented at the single leaf-push site, rebuilt from leaves.len() on snapshot restore). At the ceiling, both mint arms (no-candidate and §6.3 lossy-zone) divert to the parse-failure path: body retained bit-for-bit, counted, NO_TEMPLATE. Existing leaves keep widening — the ceiling stops growth, not matching.
  • max_line_tokens (default 512) — over-long lines fail parse before any tree work, subsuming the previous u16::MAX audit-width guard (the u16 config type keeps every accepted line inside the RFC 0001 §6.4 position width by construction).
  • Config: three validated MinerConfig fields (BoundZero rejection, with_* builders, doc-table rows). The RFC 0004 §3.3 tunables tripwire fired as designed and now classifies the knobs: tunables inside the invariants — overflow diverts, never merges, never drops.

Scenarios

  • RFC0023.1 — ceiling plateaus, overflow lines carry NO_TEMPLATE + retained bodies, and the capped template set equals the uncapped run truncated at the ceiling (no silent merge).
  • RFC0023.2 — an overflow line round-trips bit-identically through the Parquet body column (ingest-path integration).
  • RFC0023.3 — fan-out cap routes via the wildcard child; exact repeats attach cleanly through it; below-floor lines under it still fail parse rather than merge.
  • RFC0023.4 — over-cap lines fail parse with bodies retained; at-cap lines mine normally.
  • RFC0023.5 — the seed corpus mines to an identical template set under defaults vs type-maxima bounds; the corpus/C1/C2 suites (running under defaults in this very CI) stay the full-strength oracle.
  • .6 (telemetry) stays stubbed for the semconv slice; .7 is the scale-rerun bench criterion.

Invariants / hazards (CLAUDE.md §3/§4)

  • §3.1 no silent merges: load-bearing throughout — every overflow path emits NO_TEMPLATE with the body retained; RFC0023.1/.3 pin it.
  • §3.3 reconstruction: overflow lines are parse-failure class (body column is the reconstruction); RFC0023.2/.4 pin the round-trip.
  • Hazards docs: add verification process spec #1/docs: apply RFC maturity-model amendments #2: this is the fix for the 2026-07-04 scale-run OOM (docs/benchmarks.md §9.10) — worst-case tree memory becomes a computable product of the caps.
  • Tests are specifications: no existing test weakened; the tripwire update is the RFC 0004-designed maintenance path.

Verification

cargo fmt --all --check, cargo clippy --all-targets --all-features -- -D warnings, cargo test --all-features (117 suite blocks, 0 failures — including the corpus gates under the new defaults) — all green locally.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added per-tenant tunables to cap template growth, tree branching, and line token size, including explicit builder methods and default values.
  • Bug Fixes
    • Strengthened RFC 0023 enforcement so capped allocations route overflow to the failure path while retaining the original log body.
    • Improved recovery so restored tenant counters remain consistent and capacity ceilings apply correctly after restore.
  • Tests
    • Replaced stub/ignored RFC0023 cases with active end-to-end bounded-memory and overflow round-trip coverage.

max_node_children (100): full prefix nodes route unseen tokens
through a <*> wildcard child; attach below it stays simSeq-gated
(routing is not merging). max_templates (20k): a per-tenant leaf
ceiling tracked by a new leaf_count (rebuilt on snapshot restore);
at the ceiling both mint arms divert to the §6.3 parse-failure path
with the body retained — never force-merge (§3.1). max_line_tokens
(512): over-long lines fail parse pre-tree, subsuming the old
u16::MAX audit-width guard. RFC0023.1-.5 green; .6 stays stubbed for
the telemetry slice; the RFC 0004 tunables tripwire classifies the
new knobs as tunables inside the invariants.

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

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ce643cf-a087-4d76-999a-d461113f5f4a

📥 Commits

Reviewing files that changed from the base of the PR and between 3905f7b and 6c6f9ea.

📒 Files selected for processing (3)
  • crates/ourios-miner/src/cluster.rs
  • crates/ourios-miner/src/tree.rs
  • crates/ourios-miner/tests/rfc0023_bounded_memory.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/ourios-miner/tests/rfc0023_bounded_memory.rs
  • crates/ourios-miner/src/tree.rs
  • crates/ourios-miner/src/cluster.rs

📝 Walkthrough

Walkthrough

This PR adds three RFC 0023 bounded-memory tunables to MinerConfig, routes tree descent through a bounded wildcard child path, enforces tenant template and line-token caps during ingestion and restore, and implements RFC 0023 coverage tests plus an overflow Parquet round-trip test.

Changes

RFC 0023 bounded memory caps

Layer / File(s) Summary
MinerConfig cap fields, error variant, and builders
crates/ourios-core/src/config.rs
Adds max_node_children, max_templates, and max_line_tokens, plus a BoundZero error variant, defaults, and validating builder methods.
Tree descent bound and wildcard child routing
crates/ourios-miner/src/tree.rs
Adds max_node_children to descend/descend_mut, routes saturated keyed children through WILDCARD_CHILD, and updates tree tests to use the new bound.
Tenant leaf_count and template ceiling enforcement
crates/ourios-miner/src/cluster.rs
Tracks leaf-only template counts, enforces max_line_tokens and max_templates, reuses shared parse-failure emission, and rebuilds bounded state during restore.
RFC0023 and RFC0004 test scenarios
crates/ourios-ingester/tests/rfc0023_overflow_roundtrip.rs, crates/ourios-miner/tests/rfc0023_bounded_memory.rs, crates/ourios-miner/tests/rfc0004_configuration_policy.rs
Implements the previously stubbed RFC0023 scenarios, adds startup validation for zero bounds, and checks Parquet overflow body round-tripping.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant MinerCluster
  participant Tree
  participant TenantState
  participant Parquet

  Client->>MinerCluster: ingest log records
  MinerCluster->>Tree: descend / descend_mut with max_node_children
  Tree-->>MinerCluster: routed template or wildcard path
  MinerCluster->>TenantState: check leaf_count and max_templates
  alt overflow or ceiling reached
    MinerCluster->>MinerCluster: emit parse-failure record with NO_TEMPLATE
  else accepted
    MinerCluster->>TenantState: increment leaf_count and template_count
  end
  Client->>Parquet: encode mined records
  Parquet-->>Client: read back overflow body bytes
Loading

Possibly related PRs

  • jensholdgaard/ourios#160: Both PRs modify the miner parse-failure emission flow in crates/ourios-miner/src/cluster.rs.
  • jensholdgaard/ourios#187: Both PRs touch restore_tenant and snapshot/restore traversal behavior in crates/ourios-miner/src/cluster.rs.
🚥 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 0023 bounded-memory changes.
Description check ✅ Passed The description covers the main changes, scenarios, and verification, though it doesn't follow the repo's exact template headings.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rfc0023-green-pt1

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

Implements RFC 0023 bounded-template-memory controls in the miner by adding three configurable bounds (tree fan-out, per-tenant template ceiling, and per-line token-width) and turning the corresponding RFC §5 scenarios green via new/updated tests.

Changes:

  • Add MinerConfig bounds (max_node_children, max_templates, max_line_tokens) with validation and builders.
  • Enforce the bounds in the miner: wildcard routing once a prefix node hits the child cap, template mint diversion at the per-tenant leaf ceiling, and early parse-failure for over-tokenized lines.
  • Add/upgrade RFC 0023 scenario tests, including an ingester-path Parquet body round-trip for overflow lines.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/ourios-core/src/config.rs Introduces and validates the three new RFC 0023 bound fields on MinerConfig.
crates/ourios-miner/src/tree.rs Adds wildcard-child routing to cap per-node keyed fan-out on both read and write paths.
crates/ourios-miner/src/cluster.rs Enforces max_templates (leaf ceiling) and max_line_tokens, and threads max_node_children into tree traversal.
crates/ourios-miner/tests/rfc0023_bounded_memory.rs Turns RFC0023.1/.3/.4/.5 green with miner-level scenario tests.
crates/ourios-ingester/tests/rfc0023_overflow_roundtrip.rs Implements RFC0023.2 integration test: overflow body round-trips through Parquet.
crates/ourios-miner/tests/rfc0004_configuration_policy.rs Updates the RFC 0004 config-policy compile-time tripwire to include the new tunables.

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

Comment thread crates/ourios-miner/src/tree.rs
Comment thread crates/ourios-miner/src/cluster.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.

Actionable comments posted: 3

🧹 Nitpick comments (2)
crates/ourios-miner/src/tree.rs (1)

185-204: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the max_node_children contract in the public doc comments.

The descend_mut/descend rustdoc blocks above these signatures weren't updated to explain the new parameter — its wildcard-routing behavior and the invariant that read and write sides must be called with the same value (or the "children only grow" reasoning in descend_immutable's inline comment breaks) is currently only documented on the private helpers, not on these pub fn signatures.

Also applies to: 221-239

🤖 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/src/tree.rs` around lines 185 - 204, Update the public
rustdoc for descend_mut and descend to document max_node_children, including
that it controls wildcard-routing behavior and must be kept identical between
read and write calls so the PrefixNode/descend_immutable invariants remain
valid. Add the contract directly on the public signatures rather than only on
descend_recursively or other private helpers, and make sure the docs reference
the same behavior described by descend_mut, descend, and descend_immutable.
crates/ourios-miner/tests/rfc0023_bounded_memory.rs (1)

45-100: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider a property test for the max_templates ceiling invariant.

RFC0023.1 verifies the ceiling with one fixed 6-line, 3-ceiling example. The invariant itself (leaf_count never exceeds max_templates, and once at ceiling every would-mint line diverts to parse-failure with body retained) generalizes cleanly to arbitrary ceilings and arbitrary distinct-shaped line counts, and is a good proptest candidate per the crate's testing guideline.

As per coding guidelines, "Use property tests (proptest) for anything with an invariant."

🤖 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/rfc0023_bounded_memory.rs` around lines 45 - 100,
The RFC0023.1 test only checks one fixed example, but the `max_templates`
ceiling is an invariant and should be covered with a property test. Refactor
`rfc0023_1_template_ceiling_holds_and_never_merges` in
`crates/ourios-miner/tests/rfc0023_bounded_memory.rs` into a `proptest`-based
test that varies the ceiling and the number of distinct-shaped input lines,
while asserting `templates_for(...).len()` never exceeds
`MinerConfig::with_max_templates(...)` and that any would-mint overflow line is
routed to parse-failure with `NO_TEMPLATE`, `lossy_flag`, and retained body. Use
the existing `MinerCluster`, `SharedRecordSink`, and `template_set` helpers to
keep the same behavior checks.

Source: Coding guidelines

🤖 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 `@crates/ourios-core/src/config.rs`:
- Around line 331-375: Add tests covering the zero-bound validation in
MinerConfig’s builder methods so the guard clauses don’t regress. In the config
tests for `MinerConfig::with_max_node_children`,
`MinerConfig::with_max_templates`, and `MinerConfig::with_max_line_tokens`,
assert that passing `0` returns `MinerConfigError::BoundZero` with the expected
field name string for each method. Keep the tests focused on these three methods
and their zero-input rejection behavior.

In `@crates/ourios-miner/src/cluster.rs`:
- Around line 1276-1290: The ceiling-divert handling is duplicated in
cluster.rs, so extract the repeated record-envelope construction, overflow
retention, emit, record_parse_failure, and early return logic into a shared
helper in the Cluster implementation. Reuse that helper from both
at_template_ceiling call sites so the behavior stays identical and future
changes only need to be made in one place; keep the helper centered around the
existing record_envelope, apply_overflow_retention, emit_record, and
record_parse_failure flow.

In `@crates/ourios-miner/src/tree.rs`:
- Around line 265-303: Add a proptest-based property test for the bounded-fanout
invariant around `descend_recursively`/`descend_immutable` and `keyed_children`.
Generate arbitrary token sequences and `max_node_children` values, build the
tree through `Tree::descend_mut`, then walk the visited nodes and assert the
keyed child count never exceeds the cap. Cover the wildcard-reuse path too, so
the test exercises the same routing logic that can trigger an off-by-one in
`keyed_children` or `WILDCARD_CHILD` handling.

---

Nitpick comments:
In `@crates/ourios-miner/src/tree.rs`:
- Around line 185-204: Update the public rustdoc for descend_mut and descend to
document max_node_children, including that it controls wildcard-routing behavior
and must be kept identical between read and write calls so the
PrefixNode/descend_immutable invariants remain valid. Add the contract directly
on the public signatures rather than only on descend_recursively or other
private helpers, and make sure the docs reference the same behavior described by
descend_mut, descend, and descend_immutable.

In `@crates/ourios-miner/tests/rfc0023_bounded_memory.rs`:
- Around line 45-100: The RFC0023.1 test only checks one fixed example, but the
`max_templates` ceiling is an invariant and should be covered with a property
test. Refactor `rfc0023_1_template_ceiling_holds_and_never_merges` in
`crates/ourios-miner/tests/rfc0023_bounded_memory.rs` into a `proptest`-based
test that varies the ceiling and the number of distinct-shaped input lines,
while asserting `templates_for(...).len()` never exceeds
`MinerConfig::with_max_templates(...)` and that any would-mint overflow line is
routed to parse-failure with `NO_TEMPLATE`, `lossy_flag`, and retained body. Use
the existing `MinerCluster`, `SharedRecordSink`, and `template_set` helpers to
keep the same behavior checks.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2890cee8-eee3-48e0-9100-0b3547fd0166

📥 Commits

Reviewing files that changed from the base of the PR and between 2eb892d and 3905f7b.

📒 Files selected for processing (6)
  • crates/ourios-core/src/config.rs
  • crates/ourios-ingester/tests/rfc0023_overflow_roundtrip.rs
  • crates/ourios-miner/src/cluster.rs
  • crates/ourios-miner/src/tree.rs
  • crates/ourios-miner/tests/rfc0004_configuration_policy.rs
  • crates/ourios-miner/tests/rfc0023_bounded_memory.rs

Comment thread crates/ourios-core/src/config.rs
Comment thread crates/ourios-miner/src/cluster.rs
Comment thread crates/ourios-miner/src/tree.rs
…overflow exit

Five duplicated emit blocks (below-floor zone, degenerate-widening
rejection, long-line guard, both ceiling diverts) collapse onto one
helper — the overflow contract now has a single implementation, and
attach_and_maybe_widen drops back under the clippy line budget.

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 6 changed files in this pull request and generated 3 comments.

Comment thread crates/ourios-miner/tests/rfc0023_bounded_memory.rs Outdated
Comment thread crates/ourios-miner/tests/rfc0023_bounded_memory.rs Outdated
Comment thread crates/ourios-miner/src/cluster.rs Outdated
…t, zero-bound test

Plus canonical format_template rendering in the RFC 0023 oracle
helper (Debug output is not a stable form), a drain-length assertion
in the long-line scenario, and the §6.4 call site named in the shared
parse-failure helper's doc.

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 6 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

crates/ourios-miner/src/tree.rs:195

  • Tree::descend_mut now takes max_node_children, but it doesn't validate that the cap is non-zero. Passing 0 makes every node appear “full” and forces wildcard routing, which would collapse routing unexpectedly. Since this is a public API, add a precondition assert (mirroring the config-level BoundZero guarantee) so misuse fails fast.
        assert!(
            !masked.is_empty(),
            "descend_mut precondition: masked must be non-empty",
        );

crates/ourios-miner/src/tree.rs:231

  • Tree::descend takes max_node_children but doesn’t validate it. A 0 cap causes the read-side routing rule to degenerate (everything treated as overflow), which can make candidate selection diverge from intent. Add a non-zero precondition assert to fail fast on invalid input.
        assert!(
            !masked.is_empty(),
            "descend precondition: masked must be non-empty",
        );

Comment thread crates/ourios-miner/tests/rfc0023_bounded_memory.rs Outdated
…ms to test

The previous input missed the second-level prefix and minted via
no-candidate, making the no-merge assertion vacuous. It now shares
gamma's exact bucket (wildcard route + worker prefix, 1/4 similarity
< the 0.4 floor) and pins NO_TEMPLATE + an unchanged template count.

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 6 changed files in this pull request and generated no new comments.

@jensholdgaard
jensholdgaard merged commit d171457 into main Jul 4, 2026
23 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