Conversation
All Kani CI shards have been failing consistently (0/50 recent CI runs
passed). Root cause: CBMC solver processes consume 3-5 GB each, and at
--jobs 3-4 on 16 GB runners, peak memory exceeds available RAM causing:
- Runner preemption ("runner shutdown signal" after 2-3 minutes)
- OOM kills mid-verification
- Core shard timeout at 90 min (too tight for 145 proofs)
Changes:
- Reduce --jobs from 3/4 to 2 across all Kani shards (peak ~10 GB)
- Increase kani-core timeout: 90 → 120 min (145 proofs with unwind ≤100)
- Decrease kani-arrow timeout: 90 → 60 min (24 proofs, finishes in ~5 min)
- Update documentation comments with accurate proof counts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Looks ready to merge — no CI failures, open threads, or flagged issues. 👍 Well-structured Kani CI optimization: bounded proofs, gated slow proofs behind feature flag, reduced parallelism to prevent OOM — all intentional with documented trade-offs. Last activity: No activity yet. Configuration (5 of 12 enabled)Auto-title · Auto-body · Auto-review · Auto-labels · Hide external comments
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughCI Kani configuration updated: Possibly related PRs
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 2 warnings)
✅ Passed checks (4 passed)
Review rate limit: 0/10 reviews remaining, refill in 55 minutes and 52 seconds. Comment |
ApprovabilityVerdict: Approved CI-only changes that gate slow Kani verification proofs behind a feature flag and reduce parallelism to prevent OOM. No runtime code is affected - all modifications are in verification test modules and CI configuration. You can customize Macroscope's approvability policy. Learn more. |
There was a problem hiding this comment.
Pull request overview
Adjusts the GitHub Actions Kani verification shards to run within the memory limits of hosted runners, preventing consistent OOM/preemption failures and making the CI conclusion job attainable again.
Changes:
- Reduce Kani parallelism across all shards to
--jobs 2to avoid CBMC solver memory spikes on 16 GB runners. - Update timeouts: increase
kani-coreto 120 minutes; decreasekani-arrowto 60 minutes; keep other shards at 120 minutes. - Refresh the workflow’s Kani shard documentation/comments with current proof counts and rationale.
Five proofs were consuming 500-800s each (total ~2500s = 42 min on a single thread), causing Kani CI shards to timeout or get OOM-killed. Fixes: - verify_hex_decode_rejects_wrong_length (805s → ~5s): Replace Vec heap allocation with stack array slice - verify_parse_int_fast_no_panic_8bytes (538s → ~10s): Remove to_string() roundtrip (allocator modeling is expensive); oracle proof already covers correctness - verify_parse_int_fast_vs_oracle (534s → ~30s): Reduce input from 20 bytes to 10 (still covers all i32 + most i64) - verify_encode_bytes_field_content_compositional (502s → ~20s): Reduce data array from 8 to 4 bytes; reduce unwind 12 → 6 - verify_json_escape_bytes_vs_oracle (120s → ~15s): Reduce input from 16 to 8 bytes; reduce unwind 100 → 50 - verify_merge_child_send_result_tracks_pending_signals (556s → ~5s): Bound Duration millisecond values to ≤ 30_000 (full u64 solver space provides no extra branch coverage for a simple comparison) Total estimated savings: ~2400s → ~85s (28x faster on the critical path). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dismissing prior approval to re-evaluate c57b2f6
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c57b2f62fc
ℹ️ 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".
- Fix rustfmt formatting in sink.rs (if/else on single line) - Increase unwind(6) → unwind(12) on encode_bytes_field_content_compositional to cover encode_varint_stub's 10-iteration loop - Add verify_parse_int_fast_overflow_boundary proof targeting i64 overflow (19-20 digit inputs with constrained digit-only symbols to keep solver tractable while covering the overflow region the 10-byte oracle proof misses) - Update doc comments to cross-reference the overflow proof Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cracker research Document hard-won lessons on avoiding slow proofs: - Heap allocation avoidance (Vec/String → stack arrays) - Duration/u64 arithmetic bounding - Input constraining for targeted proofs - Input partitioning strategy - Function contracts pattern (Firecracker's key technique) - CI resource constraints (OOM thresholds) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5764b942a7
ℹ️ 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".
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@dev-docs/references/kani-verification.md`:
- Around line 210-215: The example uses an undefined variable `len` in the loop
over `for i in 0..len`; fix it by defining a bounded `len` or using a literal
bound so you never index past `bytes`. For example, declare `let len: usize = /*
choose or nondet value */` and constrain it with `kani::assume(len <=
bytes.len());` before the loop, or replace `for i in 0..len` with a literal like
`for i in 0..bytes.len()` to iterate safely over the `bytes` array.
- Line 179: The Vec example uses the repeat Vec syntax with kani::any(), which
fails because kani::any is not Clone; replace the vec![kani::any(); 16] usage by
constructing an iterator over the range 0..16, mapping each element to
kani::any::<u8>() (or kani::any() with an explicit Vec<u8> annotation to help
inference) and then collecting the results into a Vec<u8>, referencing the
existing symbols Vec<u8>, kani::any, map, collect and the 0..16 range.
🪄 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: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c99c22af-ba1f-424f-8ffb-709901703d60
📒 Files selected for processing (1)
dev-docs/references/kani-verification.md
…t PR CI Proofs taking >30s solver time are gated behind `#[cfg(feature = "kani-slow")]`: - structural.rs: 6 proofs (compute_real_quotes, prefix_xor, find_char_mask, structural_scalar — all with 65-unwind over symbolic u64/[u8;64]) - cri.rs: 3 proofs (process_cri 48-byte, write_json_line parametric, json_escape oracle — all with 50+ unwind) - otlp.rs: 3 proofs (parse_severity exhaustive, skip_field oracle + no-panic — 32-byte arrays) - ffwd-kani/bytes.rs: 3 proofs (oracle contracts with 65-unwind) - json_scanner.rs: 1 proof (next_quote 66-unwind) - structural_iter.rs: 1 proof (advance pipeline 66-unwind) - scan_config.rs: 1 proof (overflow boundary 20-byte) - framer.rs: 1 proof (ranges_valid 32-byte + kissat) CI behavior: - PR CI: runs ~130 fast proofs only (estimated ~5 min wall-clock) - Push-to-main / ci:full label: runs all ~149 proofs with --features kani-slow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dismissing prior approval to re-evaluate 0c77ab2
- Add verify_parse_int_fast_mid_range proof for 11-17 byte inputs, bridging the coverage gap between the main oracle (0-10) and overflow boundary (18-20) proofs - Fix undefined 'len' variable in digit-constraint doc example - Update input partitioning guidance to show three-range pattern Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Auto-dismissed because every review thread opened from this change request is now resolved. If additional changes are still required, please leave a new review.
|
Note Your trial team has used its Gitar budget, so automatic reviews are paused. Upgrade now to unlock full capacity. Comment "Gitar review" to trigger a review manually. Code Review ✅ ApprovedReduces CI memory pressure by lowering parallelism and gating expensive proofs behind a
OptionsDisplay: compact → Showing less information. Comment with these commands to change:
Important Your trial ends in 2 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more. Was this helpful? React with 👍 / 👎 | Gitar |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 381-401: PRs currently skip compiling code under cfg(feature =
"kani-slow") because --features kani-slow is only enabled on push-to-main or
when the ci:full label is present; update the CI to auto-enable the kani-slow
feature for PRs that touch any slow-proof files by detecting changed paths and
setting the feature flag for the relevant job(s). Concretely, add a step early
in the workflow to run git diff --name-only origin/main...HEAD (or use
github.event.pull_request.changed_files/path filters) to match the slow-proof
file patterns and, if matched, set an environment variable (e.g.,
ENABLE_KANI_SLOW=true) or append --features kani-slow to the cargo/kani
invocation for the build/test/proof steps referenced in the workflow so those
jobs compile and typecheck cfg(feature = "kani-slow") harnesses without
requiring the ci:full label.
In `@crates/ffwd-core/src/cri.rs`:
- Around line 1134-1139: Both slow JSON proofs need explicit solver pinning: add
the attribute #[kani::solver(kissat)] above the #[kani::proof] for both
verify_write_json_line_parametric() and verify_json_escape_bytes_vs_oracle(),
and include a short comment on the same line or just above explaining the solver
choice (e.g., "Pin solver to kissat because this ~30s proof exceeds the 10s
threshold and performs better with kissat"). Ensure you place the attribute in
the same cfg-gated blocks where the functions are defined so the proof
annotations remain contiguous.
In `@crates/ffwd-core/src/structural.rs`:
- Around line 714-717: The change removed the fast/oracle Kani proofs for
prefix_xor/compute_real_quotes; restore a reduced default (non-`kani-slow`)
oracle harness for `verify_prefix_xor` (and a small harness for
`compute_real_quotes`) that compares `prefix_xor` against the scalar reference
(`verify_prefix_xor_vs_oracle`) and uses kani::cover!() to assert both "some
bits set" and "zero bits" paths, while keeping the exhaustive 64-bit/65-unwind
variants gated by `#[cfg(feature = "kani-slow")]`; update the harnesses
referenced (`verify_prefix_xor`, `verify_prefix_xor_vs_oracle`,
`compute_real_quotes`, `verify_process_block_compositional`) so only the
expensive exhaustive tests remain behind `kani-slow` and the reduced oracle
proofs run in regular PR CI.
🪄 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: Repository YAML (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 8fa884d7-084b-42e6-9b27-a7f1deea50c4
📒 Files selected for processing (12)
.github/workflows/ci.ymlcrates/ffwd-core/Cargo.tomlcrates/ffwd-core/src/cri.rscrates/ffwd-core/src/framer.rscrates/ffwd-core/src/json_scanner.rscrates/ffwd-core/src/otlp.rscrates/ffwd-core/src/scan_config.rscrates/ffwd-core/src/structural.rscrates/ffwd-core/src/structural_iter.rscrates/ffwd-kani/Cargo.tomlcrates/ffwd-kani/src/bytes.rsdev-docs/references/kani-verification.md
| # Fast vs slow proofs: | ||
| # Proofs gated behind `kani-slow` feature (>30s solver time) run only | ||
| # on push-to-main and ci:full PRs. PR CI runs fast proofs only (~5 min | ||
| # wall-clock for core shard vs ~45+ min with slow proofs). | ||
| # | ||
| # Observed proof counts and timing constraints: | ||
| # kani-core: ~130 fast + ~15 slow proofs (ffwd-core + ffwd-kani) | ||
| # Slow: structural(unwind 65), cri(unwind 52), severity | ||
| # kani-arrow: 24 proofs (ffwd-arrow) — all fast | ||
| # kani-runtime-types: 63 proofs (ffwd-runtime + ffwd-types) — all fast | ||
| # kani-io-output: 59 proofs (ffwd-io + ffwd-output + | ||
| # ffwd-diagnostics + ffwd binary) — all fast | ||
| # | ||
| # All shards use --jobs 2 (not 3 or 4). CBMC solver processes consume | ||
| # 3-5 GB each; at --jobs 3+ on 16 GB runners, memory pressure causes | ||
| # OOM kills or runner preemption (manifests as "runner shutdown signal" | ||
| # after only minutes). --jobs 2 keeps peak memory under ~10 GB. | ||
| # | ||
| # The core shard gets 120 min (slow proofs need it on main). | ||
| # Arrow gets 60 min (finishes in ~5 min, but needs compilation time). | ||
| # Runtime and IO shards get 120 min for cold-cache variance. |
There was a problem hiding this comment.
Default PRs stop compiling the slow proof set.
With --features kani-slow only on push-to-main or ci:full, edits under the new #[cfg(feature = "kani-slow")] harnesses never typecheck on ordinary PRs. A helper rename or signature drift in those proofs now lands as a post-merge failure on main. Please auto-enable the feature when a PR touches one of the slow-proof files, even without the label.
Suggested workflow shape
jobs:
changes:
name: Detect changed paths
runs-on: ubuntu-latest
outputs:
kani_required: ${{ steps.filter.outputs.kani_required }}
+ kani_slow_required: ${{ steps.filter.outputs.kani_slow_required }}
tla: ${{ steps.filter.outputs.tla }}
frontend: ${{ steps.filter.outputs.frontend }}
miri: ${{ steps.filter.outputs.miri }}
rust: ${{ steps.filter.outputs.rust }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@f3ceefdc7ef57bc2d8560787d4b6c33e44044cec
id: filter
with:
filters: |
kani_required:
- 'crates/ffwd-kani/**'
- 'crates/ffwd-core/**'
- 'crates/ffwd-arrow/**'
- 'crates/ffwd-types/**'
- 'crates/ffwd-io/**'
- 'crates/ffwd-output/**'
- 'crates/ffwd-runtime/**'
- 'crates/ffwd-diagnostics/**'
- 'crates/ffwd/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'dev-docs/verification/kani-boundary-contract.toml'
- 'scripts/verify_kani_boundary_contract.py'
- '.github/workflows/ci.yml'
+ kani_slow_required:
+ - 'crates/ffwd-core/src/structural.rs'
+ - 'crates/ffwd-core/src/structural_iter.rs'
+ - 'crates/ffwd-core/src/json_scanner.rs'
+ - 'crates/ffwd-core/src/framer.rs'
+ - 'crates/ffwd-kani/src/bytes.rs'
kani-core:
...
with:
args: >-
--solver kissat
--jobs 2
--output-format terse
-Z function-contracts
-Z mem-predicates
-Z stubbing
-p ffwd-kani
-p ffwd-core
- ${{ (github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'ci:full')) && '--features kani-slow' || '' }}
+ ${{ (github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'ci:full') || needs.changes.outputs.kani_slow_required == 'true') && '--features kani-slow' || '' }}Also applies to: 420-432
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/ci.yml around lines 381 - 401, PRs currently skip
compiling code under cfg(feature = "kani-slow") because --features kani-slow is
only enabled on push-to-main or when the ci:full label is present; update the CI
to auto-enable the kani-slow feature for PRs that touch any slow-proof files by
detecting changed paths and setting the feature flag for the relevant job(s).
Concretely, add a step early in the workflow to run git diff --name-only
origin/main...HEAD (or use github.event.pull_request.changed_files/path filters)
to match the slow-proof file patterns and, if matched, set an environment
variable (e.g., ENABLE_KANI_SLOW=true) or append --features kani-slow to the
cargo/kani invocation for the build/test/proof steps referenced in the workflow
so those jobs compile and typecheck cfg(feature = "kani-slow") harnesses without
requiring the ci:full label.
| /// | ||
| /// Gated behind `kani-slow`: unwind 52 through JSON escaping takes >30s. | ||
| #[cfg(feature = "kani-slow")] | ||
| #[kani::proof] | ||
| #[kani::unwind(52)] | ||
| fn verify_write_json_line_parametric() { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
wc -l crates/ffwd-core/src/cri.rsRepository: strawgate/fastforward
Length of output: 98
🏁 Script executed:
sed -n '1130,1145p' crates/ffwd-core/src/cri.rsRepository: strawgate/fastforward
Length of output: 733
🏁 Script executed:
sed -n '1232,1255p' crates/ffwd-core/src/cri.rsRepository: strawgate/fastforward
Length of output: 1156
Add #[kani::solver(kissat)] to both slow JSON proofs.
Both verify_write_json_line_parametric() (line 1134) and verify_json_escape_bytes_vs_oracle() (line 1236) are documented as ~30s proofs, exceeding the 10s threshold that requires explicit solver pinning per the coding guidelines. Add #[kani::solver(kissat)] with a comment explaining the solver choice.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/ffwd-core/src/cri.rs` around lines 1134 - 1139, Both slow JSON proofs
need explicit solver pinning: add the attribute #[kani::solver(kissat)] above
the #[kani::proof] for both verify_write_json_line_parametric() and
verify_json_escape_bytes_vs_oracle(), and include a short comment on the same
line or just above explaining the solver choice (e.g., "Pin solver to kissat
because this ~30s proof exceeds the 10s threshold and performs better with
kissat"). Ensure you place the attribute in the same cfg-gated blocks where the
functions are defined so the proof annotations remain contiguous.
| /// | ||
| /// Gated behind `kani-slow`: 65-unwind loop over symbolic u64 takes >30s. | ||
| /// PR CI runs the fast `verify_prefix_xor_vs_oracle` instead. | ||
| #[cfg(feature = "kani-slow")] |
There was a problem hiding this comment.
Keep one fast oracle proof for compute_real_quotes/prefix_xor.
The comment above verify_prefix_xor now says PR CI still runs verify_prefix_xor_vs_oracle, but Lines 833-845 gate that harness too. After this change, ordinary PR Kani keeps only the submask contract for compute_real_quotes and no direct proof for prefix_xor; verify_process_block_compositional also stubs compute_real_quotes, so regressions in escape/string-mask handling will only surface on main/ci:full. Please leave a reduced default proof for these leaf primitives and reserve only the exhaustive 64-bit variants for kani-slow.
As per coding guidelines, "Bitmask operations (structural.rs, structural_iter.rs, chunk_classify.rs) must have oracle proofs against scalar reference with kani::cover!() confirming both 'some bits set' and 'zero bits' paths."
Also applies to: 750-805, 831-845
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/ffwd-core/src/structural.rs` around lines 714 - 717, The change
removed the fast/oracle Kani proofs for prefix_xor/compute_real_quotes; restore
a reduced default (non-`kani-slow`) oracle harness for `verify_prefix_xor` (and
a small harness for `compute_real_quotes`) that compares `prefix_xor` against
the scalar reference (`verify_prefix_xor_vs_oracle`) and uses kani::cover!() to
assert both "some bits set" and "zero bits" paths, while keeping the exhaustive
64-bit/65-unwind variants gated by `#[cfg(feature = "kani-slow")]`; update the
harnesses referenced (`verify_prefix_xor`, `verify_prefix_xor_vs_oracle`,
`compute_real_quotes`, `verify_process_block_compositional`) so only the
expensive exhaustive tests remain behind `kani-slow` and the reduced oracle
proofs run in regular PR CI.
Reduce Kani CI resource usage to prevent OOM on 16 GB runners by reducing parallel jobs, tightening proof bounds, and gating expensive proofs behind a
kani-slowfeature. Thekani-slowproofs (~15 proofs, >30s each) run only on push-to-main andci:fullPRs, keeping PR CI fast at ~5 min wall-clock for the core shard.--jobs 2(down from 3–4) since CBMC solver processes consume 3–5 GB each and--jobs 3+causes OOM/preemption on 16 GB runnerskani-slowfeature flag toffwd-coreandffwd-kanicrates, gating ~15 expensive proofs behind--features kani-slow; conditional in CI for push-to-main andci:fulllabelverify_json_escape_bytes_vs_oracle: Array bounded 16 → 8 bytes, unwind 100 → 50verify_hex_decode_rejects_wrong_length: Vec replaced with[b'a'; 34]stack array, unwind 36 (Vec caused 800s+ of CBMC allocator modeling)verify_encode_bytes_field_content_compositional: Data bounded 8 → 4 bytes, unwind 12verify_parse_int_fast_vs_oracle: Bounded 20 → 10 bytes, unwind 22 → 12; removed 500s+ roundtrip check that modeled allocator; split into twokani-slowproofs for mid-range (11-17 bytes) and overflow boundary (18-20 bytes, constrained to digits)merge_child_send_resultin sink.rs: Duration values bounded to ≤30,000 ms to avoid 500s+ of symbolic u64/Duration arithmeticdev-docs/references/kani-verification.mdsection on performance best practices (avoid Vec/String in proofs, bound arithmetic, constrain inputs for targeted proofs)Note
Add
kani-slowfeature gate and reduce CI parallelism to 2 jobs for Kani proofskani-slowfeature flag inffwd-coreandffwd-kanito gate expensive Kani proofs, which are now only run on push to main or PRs labeledci:full; default PRs run fast proofs only.cri.rs,framer.rs,json_scanner.rs,otlp.rs,scan_config.rs,structural.rs,structural_iter.rs, andbytes.rsbehind#[cfg(feature = "kani-slow")].--jobsfrom 3–4 to 2 across all Kani CI shards to reduce memory pressure, raiseskani-coretimeout from 90 to 120 minutes, and lowerskani-arrowtimeout from 90 to 60 minutes.verify_encode_bytes_field_content_compositionaldata length bounded to ≤4) to keep fast proofs tractable.Macroscope summarized c92fc41.