Skip to content

invariant: add proptest properties for source_complexity.rs 🔬#2606

Draft
EffortlessSteven wants to merge 1 commit into
mainfrom
invariant-model-analysis-proptest-7696108606194472207
Draft

invariant: add proptest properties for source_complexity.rs 🔬#2606
EffortlessSteven wants to merge 1 commit into
mainfrom
invariant-model-analysis-proptest-7696108606194472207

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

💡 Summary

Added missing property-based invariant tests around source_complexity.rs. These invariants explicitly verify that the heuristic rust code parsing and metric aggregations are independent of structural shifts like function re-ordering.

🎯 Why

The lightweight heuristic parser in source_complexity.rs drives cockpit review gates without pulling in a full AST. It relies on a custom token mask and a state machine tracking bracket depth and function spans. To ensure stable tracking of total_complexity and max_complexity, we needed property-based verification confirming the aggregation math works commutatively and monotonically regardless of input structure.

🔎 Evidence

Minimal proof:

  • crates/tokmd-analysis/src/source_complexity/properties.rs
  • Observed behavior: source_complexity.rs was not previously covered by proptest. Adding invariants discovered a minor issue with bad generated regexes that we fixed. Both invariants now pass deterministically over randomized input subsets.
  • Tests demonstrate: Function order is commutative, and total >= max always holds.

🧭 Options considered

Option A (recommended)

  • Add property-based invariants directly testing source_complexity.rs heuristic aggregations.
  • Fits the analysis-stack shard, improves property coverage.
  • Trade-offs: Increases CI property-testing time slightly, but locks in the core logic.

Option B

  • Try to property-test internal configuration boundaries within tokmd-gate (e.g. ratchet definitions).
  • Fits the shard, but doesn't find as many structural bugs as generating programmatic inputs against custom parsers.
  • Trade-offs: Focuses on JSON serialization edges instead of programmatic metrics logic.

✅ Decision

Option A. Adding property-based invariants directly against the analyze_rust_function_complexity parser is an honest and high-value proof improvement within the analysis-stack that locks in true mathematical properties of the implementation.

🧱 Changes made (SRP)

  • Added crates/tokmd-analysis/src/source_complexity/properties.rs.
  • Registered properties.rs within crates/tokmd-analysis/src/source_complexity.rs.

🧪 Verification receipts

> cargo test -p tokmd-analysis properties
...
test source_complexity::properties::tests::property_function_order_independence ... ok
test source_complexity::properties::tests::property_total_gte_max ... ok
...
test result: ok. 103 passed; 0 failed; 0 ignored; 0 measured; 1470 filtered out; finished in 6.47s

🧭 Telemetry

  • Change shape: Add proptest module
  • Blast radius: Only test code and metrics behavior tracking
  • Risk class: Low
  • Rollback: Revert source_complexity.rs and delete properties.rs
  • Gates run: cargo test, cargo fmt -- --check, cargo clippy -- -D warnings, cargo build --verbose

🗂️ .jules artifacts

  • .jules/runs/invariant_model_analysis/envelope.json
  • .jules/runs/invariant_model_analysis/decision.md
  • .jules/runs/invariant_model_analysis/receipts.jsonl
  • .jules/runs/invariant_model_analysis/result.json
  • .jules/runs/invariant_model_analysis/pr_body.md

🔜 Follow-ups

None


PR created automatically by Jules for task 7696108606194472207 started by @EffortlessSteven

Added missing property-based invariants around `source_complexity.rs` to lock in aggregation logic.

- Registered `properties.rs` within `crates/tokmd-analysis/src/source_complexity.rs`.
- Added two invariants testing function order independence and that total complexity >= max complexity, verifying both pass with `cargo test -p tokmd-analysis properties`.
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@EffortlessSteven, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 21 minutes and 53 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6457104e-3e30-43ea-b78b-a2937f909f55

📥 Commits

Reviewing files that changed from the base of the PR and between a6b9118 and 2b4812b.

📒 Files selected for processing (7)
  • .jules/runs/invariant_model_analysis/decision.md
  • .jules/runs/invariant_model_analysis/envelope.json
  • .jules/runs/invariant_model_analysis/pr_body.md
  • .jules/runs/invariant_model_analysis/receipts.jsonl
  • .jules/runs/invariant_model_analysis/result.json
  • crates/tokmd-analysis/src/source_complexity.rs
  • crates/tokmd-analysis/src/source_complexity/properties.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch invariant-model-analysis-proptest-7696108606194472207

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 and usage tips.

@factory-droid

factory-droid Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Droid finished @EffortlessSteven's task —— View job


Droid validation complete.

The P1 finding that property_total_gte_max is vacuous is incorrect: the regex character class does allow minimal valid Rust functions (e.g. fn a { }), and the PR's own receipts show the test originally failed for the analyzer, proving the invariant is meaningfully exercised. The P2 finding about breaking the crate's tests.rs indirection pattern is approved: properties.rs is dropped next to mask.rs and registered from the production file with #[path = ...] mod properties; and no #[cfg(test)] gate, unlike every sibling module. The second P2 finding on the same line is rejected as a strict subset of the first.

@github-actions

Copy link
Copy Markdown
Contributor

Glass Cockpit

Base: origin/main
Head: HEAD

Change Surface:

  • Files: 7
  • Insertions: 130
  • Deletions: 52

Composition:

  • Code: 33.3%
  • Test: 0.0%
  • Docs: 33.3%
  • Config: 33.3%

Contracts:

  • API: No
  • CLI: No
  • Schema: No

Health: 100/100 (A)
Risk: low (0/100)

Review Plan

  • crates/tokmd-analysis/src/source_complexity/properties.rs (priority: 2)
  • .jules/runs/invariant_model_analysis/decision.md (priority: 3)
  • .jules/runs/invariant_model_analysis/envelope.json (priority: 3)
  • .jules/runs/invariant_model_analysis/pr_body.md (priority: 3)
  • .jules/runs/invariant_model_analysis/receipts.jsonl (priority: 3)
  • .jules/runs/invariant_model_analysis/result.json (priority: 3)
  • crates/tokmd-analysis/src/source_complexity.rs (priority: 3)

Receipts

Full receipt data available in JSON format.

}
}
#[path = "source_complexity/properties.rs"]
mod properties;

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.

[P2] Property-test file breaks the established tests.rs registration pattern used elsewhere in this crate

Siblings such as crates/tokmd-analysis/src/complexity/tests.rs, crates/tokmd-analysis/src/derived/tests.rs, crates/tokmd-analysis/src/git/tests.rs, and crates/tokmd-analysis/src/halstead/tests.rs all follow the same pattern: the production module file ends with a #[cfg(test)]-gated mod tests; (or mod moved_tests; with #[path = "tests.rs"]) and the tests.rs file pulls in a properties submodule from a tests/ subdirectory. This PR instead drops properties.rs directly next to mask.rs in source_complexity/ and registers it from the production file with #[path = "source_complexity/properties.rs"] mod properties;, skipping the #[cfg(test)] gate and the tests.rs indirection. Move the file to source_complexity/tests/properties.rs, introduce a source_complexity/tests.rs that contains mod properties; (or #[path = "tests/properties.rs"] mod properties; to match the rest of the crate), and replace this registration with #[cfg(test)] mod tests; to match the sibling-file pattern.

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.

1 participant