Skip to content

Add selector concurrency property tests (#57) - #62

Merged
leynos merged 11 commits into
mainfrom
issue-57-add-property-based-and-model-checking-concurrency-tests-for-envbackendselector
Jun 10, 2026
Merged

Add selector concurrency property tests (#57)#62
leynos merged 11 commits into
mainfrom
issue-57-add-property-based-and-model-checking-concurrency-tests-for-envbackendselector

Conversation

@leynos

@leynos leynos commented May 20, 2026

Copy link
Copy Markdown
Owner

Summary

This branch adds property-based and checkpointed concurrency coverage for issue #57. It generates backend selector reentrancy cases, exercises concurrent worker completion across generated backend sequences and thread counts, and documents the _EnvBackendSelector state-machine invariants that the tests exercise.

Closes #57.

Review walkthrough

Validation

  • uv run pytest cuprum/unittests/test_tee_profile_worker.py: 20 passed.
  • make check-fmt: passed.
  • make lint: passed.
  • make typecheck: passed.
  • make test: 474 passed, 43 skipped.

Notes

  • coderabbit review --agent was attempted twice after the implementation milestone. The CLI returned a recoverable service-side rate limit both times, so there were no CodeRabbit concerns to clear locally.

Summary by Sourcery

Add property-based and checkpointed concurrency coverage for the _EnvBackendSelector used by tee_profile_worker, and reorganize its test suite into focused core, CLI, and concurrency modules.

Enhancements:

  • Document _EnvBackendSelector concurrency invariants and model-checking considerations in the concurrency test module.
  • Refactor tee_profile_worker tests into separate core execution, CLI/config validation, and concurrency-focused files for clearer coverage boundaries.

Tests:

  • Introduce Hypothesis-based generation of nested backend selector pairs and concurrent backend sequences to validate selector reentrancy and race-freedom across backends and thread counts.
  • Add checkpointed interleaving tests that assert environment mutation and observation are correctly serialized by the backend selector lock.
  • Preserve and relocate existing worker core-behavior, CLI, and configuration-validation tests into dedicated modules, updating associated snapshots.

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Splits test_tee_profile_worker.py into three focused test modules with separate concerns: CLI validation, core worker execution, and concurrency/reentrancy behaviour. Concurrency tests are strengthened with Hypothesis-driven property tests, lock-instrumentation helpers, and checkpoint-based interleaving assertions covering arbitrary backend sequences.

Changes

Test suite refactoring and reorganisation

Layer / File(s) Summary
Snapshot index update
cuprum/unittests/__snapshots__/test_maturin_build.ambr
Replaces monolithic test_tee_profile_worker.ambr entry with separate snapshots for test_tee_profile_worker_concurrency.ambr and test_tee_profile_worker_core.ambr; updates listed test modules from single test_tee_profile_worker.py to test_tee_profile_worker_cli.py, test_tee_profile_worker_concurrency.py, and test_tee_profile_worker_core.py.
CLI validation test module
cuprum/unittests/test_tee_profile_worker_cli.py
New module with three tests: test_worker_cli_reports_config_errors patches sys.argv with invalid fixture path and asserts exit code 2 with validation error in stderr; test_worker_config_rejects_invalid_fields parametrises TeeProfileWorkerConfig construction with invalid field values and asserts ValueError fragments; test_worker_cli_runs_successfully_via_subprocess runs worker via subprocess with temporary fixture and asserts JSON output contains status == "ok" and exit_code == 0.
Core worker test module
cuprum/unittests/test_tee_profile_worker_core.py
New module with three tests: test_worker_exercises_parent_side_consume_path parametrises echo/capture/tee modes with optional callbacks and asserts worker status, exit code, scenario naming, output length, and callback counts; test_run_tee_profile_worker_snapshot runs worker in tee mode with callbacks enabled and validates redacted result against snapshot; test_worker_accumulates_repeat_counters runs worker with repeat_count=3 and asserts output and callback counts scale correctly.
Concurrency and reentrancy test refactoring
cuprum/unittests/test_tee_profile_worker_concurrency.py
Refactors module to focus on _EnvBackendSelector lock serialisation and reentrancy invariants. Introduces lock-instrumentation protocol _RLockLike and class _SignallingRLock to coordinate thread interleaving. Adds dynamic backend availability computation (_available_backend_names()), Hypothesis-driven backend sequence generation (_backend_lists()), and centralised thread joining assertion (_join_and_assert_finished()). Replaces fixed _BACKEND_PAIRS constant with computed _backend_pairs() function. Adds property-based tests: test_nested_selector_rejects_generated_backend_pairs generates backend pairs and asserts reentrancy raises before environment mutation; test_generated_concurrent_workers_complete generates arbitrary backend concurrency and asserts worker completion with correct status. Adds checkpoint-based interleaving test test_selector_interleaving_blocks_environment_observation_until_unlock that monkeypatches _BACKEND_LOCK with _SignallingRLock to coordinate two threads and verify lock-serialised environment mutation ordering.
Snapshot reorganisation for refactored tests
cuprum/unittests/__snapshots__/test_tee_profile_worker_concurrency.ambr, cuprum/unittests/__snapshots__/test_tee_profile_worker_core.ambr
Moves "Rejected re-entrant backend selector activation" snapshot from monolithic structure to concurrency snapshot. Core snapshot contains only test_run_tee_profile_worker_snapshot entry. Updates snapshot metadata and test references to match refactored module structure.
Docs and Rust UI-test update
docs/developers-guide.md, rust/cuprum-rust/tests/ui/fail/invalid_pymodule_return.stderr
Add developer-guide section documenting worker test layout and concurrency invariants; update expected Rust UI test stderr to match updated compiler diagnostic formatting.

Sequence Diagram(s)

sequenceDiagram
  participant T1 as Thread 1
  participant Checkpoint as _CheckpointBackendSelector
  participant Lock as _BACKEND_LOCK/_SignallingRLock
  participant T2 as Thread 2
  participant Env as backend_env
  T1->>Checkpoint: enter_context(backend A)
  Checkpoint->>Lock: acquire
  T1->>Env: mutate backend env
  T2->>Checkpoint: enter_context(backend B)
  Checkpoint->>Lock: wait_for_release
  T1->>Lock: release on context exit
  T2->>Lock: acquire
  T2->>Env: observe serialised env state
Loading
  • Possibly related PRs:
    • leynos/cuprum#55: Shares earlier _EnvBackendSelector guard and reentrancy work that this PR refines with Hypothesis and interleaving tests.

"From monolith to focused tests we go,
Split CLI, core, and concurrency flow.
Property-based assertions now explore,
Lock choreography, like never before!
🧵✨"

Run the concurrency test file alone with the documented pytest command to validate timing heuristics and Hypothesis strategies in your environment.

Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 3 warnings)

Check name Status Explanation Resolution
Unit Architecture ❌ Error Docs use en-GB-oxendict -ise spelling (serialisation, serialises, serialised) instead of required -ize forms; test architecture is sound. Replace 'serialisation', 'serialises', 'serialised' with 'serialization', 'serializes', 'serialized' in docs/developers-guide.md (lines ~307–318, 371).
Developer Documentation ⚠️ Warning Documentation covers test architecture and concurrency approach. Three violations of en-GB-oxendict spelling policy: "serialisation" (307), "serialises" (318), "serialised" (371). Replace British "-isation"/"-ised" with American "-ization"/"-ized" forms: serialisation→serialization, serialises→serializes, serialised→serialized.
Testing (Unit And Behavioural) ⚠️ Warning Tests properly verify meaningful behaviour, edge cases, error paths, and invariants. Documentation violates spelling standards: uses British "-isation" forms instead of required "-ize" forms. Replace "serialisation", "serialises", "serialised" with "-ization", "-izes", "-ized" in docs/developers-guide.md per repository en-GB-oxendict standards.
Architectural Complexity And Maintainability ⚠️ Warning Review comment for docs/developers-guide.md requested en-GB-oxendict (-ize) spelling replacements at lines 307, 318, 371, but British forms (serialisation, serialises, serialised) remain unaddressed. Replace British spelling forms with American equivalents: serialisation→serialization, serialises→serializes, serialised→serialized in docs/developers-guide.md at lines 307, 318, 371 to match repository documentation standards.
✅ Passed checks (16 passed)
Check name Status Explanation
Title check ✅ Passed The title directly references the linked issue (#57) and accurately summarizes the main change: adding selector concurrency property tests.
Description check ✅ Passed The description is related to the changeset, explaining property-based testing, concurrency coverage, test reorganisation, and documenting the changes made.
Linked Issues check ✅ Passed The PR fully addresses all acceptance criteria from #57: Hypothesis tests for reentrancy behaviour [test_nested_selector_rejects_generated_backend_pairs], tests covering arbitrary thread counts [test_selector_interleaving_blocks_environment_observation_until_unlock], parameterised backend sequences via _backend_lists(), and no test regressions.
Out of Scope Changes check ✅ Passed All changes are scoped to concurrency testing infrastructure: new test modules (CLI, core, concurrency), snapshot updates, documentation, and Rust compiler-output fixture updates. No unrelated changes detected.
Docstring Coverage ✅ Passed Docstring coverage is 85.29% which is sufficient. The required threshold is 80.00%.
Testing (Overall) ✅ Passed Tests substantively exercise implementation: Hypothesis tests verify reentrancy rejection, concurrency tests verify lock and environment isolation, CLI tests verify validation and integration.
User-Facing Documentation ✅ Passed This PR introduces no new user-facing functionality. All changes are test additions, test reorganisation, and developer documentation only.
Module-Level Documentation ✅ Passed All three new test modules carry comprehensive module-level docstrings explaining purpose, utility, and relationships to other components.
Testing (Property / Proof) ✅ Passed Hypothesis property tests cover selector invariants over arbitrary backend pairs and thread counts 2–8. Checkpointed interleaving tests implement model-checking for lock serialisation.
Testing (Compile-Time / Ui) ✅ Passed Trybuild configured for Rust UI tests. Python snapshots redact volatile keys, explicitly mask nondeterministic fields via regex, and include focused assertions alongside snapshots.
Domain Architecture ✅ Passed Domain and test infrastructure are properly segregated. Production code has no test dependencies; test helpers are confined to test modules and injected via BackendSelector/Clock protocols.
Observability ✅ Passed PR introduces only test code, snapshots, and documentation—no operational code changes. The underlying _EnvBackendSelector logging was added in prior PR #55, not this PR.
Security And Privacy ✅ Passed Test fixtures use harmless data, subprocess calls are safe, environment variables properly isolated, sensitive data redacted in snapshots, and no credentials or injection vectors.
Performance And Resource Use ✅ Passed Hypothesis strategies bound thread counts to 2–8; max_examples≤30; all waits have timeouts; fixture sizes fixed; subprocess timeout 30s; no unbounded growth, recursion, or cloning.
Concurrency And State ✅ Passed Concurrency model explicit with checkpoint tests; shared state properly locked; Hypothesis tests cover thread counts 2–8 and backend sequences; interleaving tests verify lock serialization.
Rust Compiler Lint Integrity ✅ Passed Only Rust change is a UI test stderr snapshot update for compiler diagnostics. No source code modifications. Zero lint suppressions and zero cloning found in Rust source files verified.
📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plan used: #57

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-57-add-property-based-and-model-checking-concurrency-tests-for-envbackendselector

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai

sourcery-ai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds property-based and checkpointed concurrency tests around _EnvBackendSelector, refactors existing worker tests into focused core/CLI/concurrency modules, and introduces a snapshot file aligned with the new test layout.

File-Level Changes

Change Details Files
Introduce Hypothesis-based concurrency and reentrancy coverage for _EnvBackendSelector.
  • Document _EnvBackendSelector invariants and model-checking considerations in the concurrency test module docstring.
  • Add Hypothesis strategies for generating backend names and concurrent backend sequences based on runtime backend availability.
  • Add property-based test that asserts nested _EnvBackendSelector usage in a single thread always raises a reentrancy error before mutating the environment.
  • Add property-based test that concurrently runs workers across generated backend sequences and asserts all complete successfully.
cuprum/unittests/test_tee_profile_worker_concurrency.py
Add checkpointed interleaving harness to assert lock-serialised environment mutation.
  • Implement _CheckpointBackendSelector wrapper to expose selector state transitions via events, observation lists, and a lock.
  • Introduce _run_selector_context helper to run selector contexts in threads while capturing errors.
  • Add an interleaving test that coordinates two selector calls via events to prove the second thread blocks on the lock and only observes the environment after the first releases it.
  • Reuse existing _BackendEnvironmentRace-style helpers to assert concurrent workers preserve backend environment state and finish without errors.
cuprum/unittests/test_tee_profile_worker_concurrency.py
Refactor tests into separate core, CLI, and concurrency-focused modules with updated snapshots.
  • Rename the original test_tee_profile_worker.py to test_tee_profile_worker_concurrency.py and trim non-concurrency tests from it.
  • Create test_tee_profile_worker_core.py to hold core worker execution tests (echo/capture/tee behavior, snapshot, and repeat-counter accumulation).
  • Create test_tee_profile_worker_cli.py to hold CLI and configuration-validation tests, moving the relevant tests out of the original module.
  • Rename the corresponding snapshot file to test_tee_profile_worker_core.ambr to align with the new core test module and add a concurrency-specific snapshot file stub.
cuprum/unittests/test_tee_profile_worker_concurrency.py
cuprum/unittests/test_tee_profile_worker_core.py
cuprum/unittests/test_tee_profile_worker_cli.py
cuprum/unittests/__snapshots__/test_tee_profile_worker_core.ambr
cuprum/unittests/__snapshots__/test_tee_profile_worker_concurrency.ambr

Assessment against linked issues

Issue Objective Addressed Explanation
#57 Add Hypothesis-driven property tests for _EnvBackendSelector reentrancy, parameterised over backend names and execution orderings, asserting that nested same-thread entry raises RuntimeError before environment mutation.
#57 Parameterise concurrency tests over thread count (around 2–8 threads) and backend combinations, with a Hypothesis test that generates arbitrary thread counts and asserts all workers complete with status == 'ok' and exit_code == 0.
#57 Introduce model-checking-style coverage for the _EnvBackendSelector lock-acquisition and environment-mutation state machine (e.g. explicit interleaving / checkpoint tests) and document the invariants being exercised.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented May 22, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai please create new GitHub issues for the following:

High-Value Candidates

CrossHair is only a good fit where the target can be made pure and bounded. For async subprocess, file descriptor, or OS-environment code, Hypothesis with fakes is the better immediate tool; CrossHair becomes useful after extracting pure state-transition helpers.

Area Tool Justification Benefit Cost Trade-Off Verifiability Improvements
_emit_completed_lines / _strip_line_ending Hypothesis + CrossHair Pure line-splitting logic currently covered mostly through stream behaviour. Proves no dropped text, stable newline handling, correct final partial-line behaviour. Low. Fast, pure, good shrinking. Extract _split_complete_lines(text) -> (lines, remainder) with explicit contract.
CuprumContext.narrow and _validate_timeout Hypothesis, CrossHair for pure helpers Allowlist intersection, hook ordering, and timeout inheritance have many small combinations. Prevents subtle permission broadening and hook-order regressions. Low. Mostly dataclass/pure logic. Split allowlist merge, hook merge, and timeout normalisation into named helpers.
_build_final_results CrossHair + Hypothesis Fail-fast compaction maps partial results to new failure indices. Proves failure indices are valid, sorted, and point to failed results after cancellation. Very low. Pure reducer. Keep it pure; add simple postconditions/docstring invariants.
ProgramCatalogue indexing Hypothesis Duplicate project/program ownership cases are example-based. Exercises random ownership graphs and lookup/is_allowed consistency. Low. Pure data construction. Return structured duplicate diagnostics from private validators.
_coerce_argv / make and Pipeline.concat Hypothesis CLI argv construction and pipeline composition are algebraic and example-heavy today. Proves ordering, keyword normalisation, None rejection, associativity, and no stage loss. Low to moderate. Need generated SafeCmds. Add pure build_argv helper and lightweight command factories for tests.
safe_path / git_ref Hypothesis String validators are classic fuzz targets; current tests cover curated samples. Finds edge cases around empty strings, whitespace, NULs, traversal, suffixes, and Unicode. Low. Some oracle design needed. Factor validators into “classify reason” helpers so properties can assert rejection category.
tar_create / rsync_sync Hypothesis Command construction has flag-combination and ordering risk. Proves exactly-one compression flag, required argv shape, deterministic path conversion. Low. Pure command vectors. Extract immutable argv-builder helpers before wrapping in sh.make.
_read_backend_env / get_stream_backend Hypothesis Env parsing and cached backend resolution combine normalisation, availability, and failure paths. Proves AUTO never leaks from resolver, invalid values fail, forced Rust availability is respected. Medium due cache/global env resets. Split pure resolve_backend(requested, rust_available) from cached/env wrapper.
_PipelineWaitState / _process_completed_task Hypothesis state machine; CrossHair after refactor Pipeline completion ordering is a bounded state machine hidden inside async process waits. Proves first-failure semantics, timing slot population, and termination decisions. High. Needs fake processes/tasks. Move completion handling to a pure transition method taking (state, completed_idx, exit_code).
_pipeline_streams dispatch/fd lifecycle Hypothesis with fault injection Rust dispatch, FD blocking restore, and pipe-error suppression have many partial-failure paths. Catches leaked blocking state, missing resume calls, wrong fallback, and swallowed unexpected errors. Medium-high. Mock-heavy async/FD work. Introduce small FD-state object and context manager for pause/blocking lifecycle.
_handle_subprocess_timeout and _terminate_pipeline_remaining_stages Hypothesis; CrossHair on extracted transition data Timeout and cleanup paths are temporal and branch-heavy. Proves timeout payload consistency, idempotent cleanup, and no double-termination scheduling. Medium-high. Needs fakes around process state. Represent process lifecycle as explicit enum/state records, then verify reducers.
benchmark comparison / ratchet reducers Hypothesis JSON plan/result matching has ordering, duplicate, missing-pair, and numeric edge cases. Proves grouping, sorted output, duplicate rejection, matching Rust scenario sets, and regression ratios. Low to medium. Requires compact payload strategies. Build typed scenario/result factories; keep validation separate from report rendering.
folded stack summarisation Hypothesis + CrossHair Parser and counter aggregation already have property tests, but ranking/duplicate-frame invariants can go deeper. Proves inclusive counts dedupe repeated frames, leaf counts sum correctly, ranking is deterministic. Low. Mostly pure. Extract parse/add/rank contracts as standalone helpers with explicit invariants.
metrics/tracing/logging hooks Hypothesis stateful Event streams can arrive in varied phase/order/pid combinations. Proves counters/spans/log records are created exactly when intended and active maps drain. Medium. Needs synthetic event generators. Extract event-to-operation reducers from side-effecting collector/span calls.

Recommended Order

  1. Start with pure, low-cost properties: _emit_completed_lines, _build_final_results, CuprumContext.narrow, catalogue indexing, and argv/pipeline composition.
  2. Next cover validators/builders and benchmark reducers.
  3. Treat pipeline wait, FD lifecycle, subprocess timeout, and adapters as state-machine work after small refactors isolate pure transitions.

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

I'll create all 14 GitHub issues now.


🏁 Script executed:

#!/bin/bash
set -e

REPO="leynos/cuprum"
ASSIGNEE="leynos"
PR_URL="https://github.com/leynos/cuprum/pull/62"

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for _emit_completed_lines / _strip_line_ending (cuprum/_streams.py)" \
  --body "## Overview

Add Hypothesis and CrossHair property-based tests for the pure line-splitting logic in \`_emit_completed_lines\` and \`_strip_line_ending\` (\`cuprum/_streams.py\`, around line 202).

## Justification

These functions contain pure line-splitting logic currently covered mostly through stream behaviour. Property-based tests will prove no text is dropped, newline handling is stable, and the final partial-line behaviour is correct.

## Benefit

- Proves no dropped text
- Stable newline handling
- Correct final partial-line behaviour

## Cost Trade-Off

Low. Fast, pure, good shrinking.

## Verifiability Improvements

Extract \`_split_complete_lines(text) -> (lines, remainder)\` with an explicit contract so properties can be stated directly.

## Recommended Order

Phase 1 — start with pure, low-cost properties.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for CuprumContext.narrow and _validate_timeout (cuprum/context.py)" \
  --body "## Overview

Add Hypothesis (and CrossHair for pure helpers) property-based tests for \`CuprumContext.narrow\` (line 159) and \`_validate_timeout\` (line 42) in \`cuprum/context.py\`.

## Justification

Allowlist intersection, hook ordering, and timeout inheritance have many small combinations currently covered by example-based tests only.

## Benefit

- Prevents subtle permission broadening
- Prevents hook-order regressions

## Cost Trade-Off

Low. Mostly dataclass/pure logic.

## Verifiability Improvements

Split allowlist merge, hook merge, and timeout normalisation into named helpers that can be verified independently.

## Recommended Order

Phase 1 — start with pure, low-cost properties.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for _build_final_results (cuprum/concurrent.py)" \
  --body "## Overview

Add CrossHair and Hypothesis property-based tests for \`_build_final_results\` (\`cuprum/concurrent.py\`, around line 166).

## Justification

Fail-fast compaction maps partial results to new failure indices. This is a pure reducer with no I/O dependencies.

## Benefit

- Proves failure indices are valid, sorted, and point to failed results after cancellation

## Cost Trade-Off

Very low. Pure reducer.

## Verifiability Improvements

Keep it pure; add simple postconditions and docstring invariants.

## Recommended Order

Phase 1 — start with pure, low-cost properties.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for ProgramCatalogue indexing (cuprum/catalogue.py)" \
  --body "## Overview

Add Hypothesis property-based tests for \`ProgramCatalogue\` indexing (\`cuprum/catalogue.py\`, around line 97).

## Justification

Duplicate project/program ownership cases are currently example-based only.

## Benefit

- Exercises random ownership graphs
- Verifies lookup and \`is_allowed\` consistency

## Cost Trade-Off

Low. Pure data construction.

## Verifiability Improvements

Return structured duplicate diagnostics from private validators so properties can assert on rejection category.

## Recommended Order

Phase 1 — start with pure, low-cost properties.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for _coerce_argv / make and Pipeline.concat (cuprum/sh.py)" \
  --body "## Overview

Add Hypothesis property-based tests for \`_coerce_argv\`/\`make\` (line 79) and \`Pipeline.concat\` (line 424) in \`cuprum/sh.py\`.

## Justification

CLI argv construction and pipeline composition are algebraic and currently example-heavy.

## Benefit

- Proves ordering and keyword normalisation
- Proves \`None\` rejection
- Proves associativity and no stage loss

## Cost Trade-Off

Low to moderate. Requires generated \`SafeCmd\` instances.

## Verifiability Improvements

Add a pure \`build_argv\` helper and lightweight command factories for tests.

## Recommended Order

Phase 1 — start with pure, low-cost properties.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based fuzz tests for safe_path / git_ref validators (cuprum/builders/args.py)" \
  --body "## Overview

Add Hypothesis property-based fuzz tests for \`safe_path\` and \`git_ref\` string validators in \`cuprum/builders/args.py\` (around line 52).

## Justification

String validators are classic fuzz targets; current tests cover only curated samples.

## Benefit

- Finds edge cases around empty strings, whitespace, NULs, path traversal, suffixes, and Unicode

## Cost Trade-Off

Low. Some oracle design needed.

## Verifiability Improvements

Factor validators into \"classify reason\" helpers so properties can assert on the rejection category rather than just pass/fail.

## Recommended Order

Phase 2 — validators and builders.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for tar_create / rsync_sync command construction (cuprum/builders/tar.py)" \
  --body "## Overview

Add Hypothesis property-based tests for \`tar_create\` and \`rsync_sync\` in \`cuprum/builders/tar.py\` (around line 51).

## Justification

Command construction has flag-combination and ordering risk currently only covered by examples.

## Benefit

- Proves exactly-one compression flag
- Proves required argv shape
- Proves deterministic path conversion

## Cost Trade-Off

Low. Pure command vectors.

## Verifiability Improvements

Extract immutable argv-builder helpers before wrapping in \`sh.make\`.

## Recommended Order

Phase 2 — validators and builders.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for _read_backend_env / get_stream_backend (cuprum/_backend.py)" \
  --body "## Overview

Add Hypothesis property-based tests for \`_read_backend_env\` and \`get_stream_backend\` in \`cuprum/_backend.py\` (around line 46).

## Justification

Env parsing and cached backend resolution combine normalisation, availability, and failure paths in ways difficult to cover with examples alone.

## Benefit

- Proves \`AUTO\` never leaks from the resolver
- Proves invalid values fail
- Proves forced Rust availability is respected

## Cost Trade-Off

Medium, due to cache and global environment resets.

## Verifiability Improvements

Split a pure \`resolve_backend(requested, rust_available)\` helper from the cached/env wrapper.

## Recommended Order

Phase 2 — validators and builders.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Hypothesis state-machine tests for _PipelineWaitState / _process_completed_task (cuprum/_pipeline_wait.py)" \
  --body "## Overview

Add Hypothesis state-machine tests (and CrossHair after refactor) for \`_PipelineWaitState\` and \`_process_completed_task\` in \`cuprum/_pipeline_wait.py\` (around line 29).

## Justification

Pipeline completion ordering is a bounded state machine hidden inside async process waits, currently untested at the state-transition level.

## Benefit

- Proves first-failure semantics
- Proves timing slot population
- Proves correct termination decisions

## Cost Trade-Off

High. Requires fake processes and tasks.

## Verifiability Improvements

Move completion handling to a pure transition method taking \`(state, completed_idx, exit_code)\`.

## Recommended Order

Phase 3 — state-machine work after refactors isolate pure transitions.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Hypothesis fault-injection tests for _pipeline_streams dispatch/fd lifecycle (cuprum/_pipeline_streams.py)" \
  --body "## Overview

Add Hypothesis tests with fault injection for the Rust dispatch, FD blocking restore, and pipe-error suppression logic in \`cuprum/_pipeline_streams.py\` (around line 136).

## Justification

Many partial-failure paths exist across Rust dispatch, FD blocking restore, and pipe-error suppression.

## Benefit

- Catches leaked blocking state
- Catches missing resume calls
- Catches wrong fallback behaviour
- Catches swallowed unexpected errors

## Cost Trade-Off

Medium-high. Mock-heavy async/FD work.

## Verifiability Improvements

Introduce a small FD-state object and context manager for the pause/blocking lifecycle.

## Recommended Order

Phase 3 — state-machine work after refactors isolate pure transitions.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for _handle_subprocess_timeout and _terminate_pipeline_remaining_stages" \
  --body "## Overview

Add Hypothesis tests (and CrossHair on extracted transition data) for \`_handle_subprocess_timeout\` (\`cuprum/_subprocess_execution.py\`, line 263) and \`_terminate_pipeline_remaining_stages\` (\`cuprum/_process_lifecycle.py\`, line 235).

## Justification

Timeout and cleanup paths are temporal and branch-heavy, with risk of inconsistent payloads, non-idempotent cleanup, and double-termination scheduling.

## Benefit

- Proves timeout payload consistency
- Proves idempotent cleanup
- Proves no double-termination scheduling

## Cost Trade-Off

Medium-high. Requires fakes around process state.

## Verifiability Improvements

Represent the process lifecycle as explicit enum/state records, then verify reducers independently.

## Recommended Order

Phase 3 — state-machine work after refactors isolate pure transitions.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Property-based tests for benchmark comparison / ratchet reducers (benchmarks/comparison_analysis.py)" \
  --body "## Overview

Add Hypothesis property-based tests for the benchmark comparison and ratchet reducer logic in \`benchmarks/comparison_analysis.py\` (around line 229).

## Justification

JSON plan/result matching has ordering, duplicate, missing-pair, and numeric edge cases currently only covered by examples.

## Benefit

- Proves grouping and sorted output
- Proves duplicate rejection
- Proves matching Rust scenario sets
- Proves regression ratios

## Cost Trade-Off

Low to medium. Requires compact payload strategies.

## Verifiability Improvements

Build typed scenario/result factories; keep validation separate from report rendering.

## Recommended Order

Phase 2 — validators and benchmark reducers.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Deeper property-based tests for folded stack summarisation (benchmarks/summarize_folded.py)" \
  --body "## Overview

Extend Hypothesis and CrossHair coverage for the folded stack summarisation logic in \`benchmarks/summarize_folded.py\` (around line 20), going deeper than existing property tests.

## Justification

Parser and counter aggregation already have property tests, but ranking and duplicate-frame invariants can be verified more thoroughly.

## Benefit

- Proves inclusive counts deduplicate repeated frames
- Proves leaf counts sum correctly
- Proves ranking is deterministic

## Cost Trade-Off

Low. Mostly pure.

## Verifiability Improvements

Extract parse/add/rank contracts as standalone helpers with explicit invariants.

## Recommended Order

Phase 2 — validators and benchmark reducers.

---
Raised from PR $PR_URL by @$ASSIGNEE."

gh issue create --repo "$REPO" --assignee "$ASSIGNEE" \
  --title "Hypothesis stateful tests for metrics/tracing/logging hooks (cuprum/adapters/metrics_adapter.py)" \
  --body "## Overview

Add Hypothesis stateful tests for the metrics, tracing, and logging hooks in \`cuprum/adapters/metrics_adapter.py\` (around line 206).

## Justification

Event streams can arrive in varied phase/order/pid combinations, and current tests do not exercise these combinations systematically.

## Benefit

- Proves counters, spans, and log records are created exactly when intended
- Proves active maps drain correctly

## Cost Trade-Off

Medium. Requires synthetic event generators.

## Verifiability Improvements

Extract event-to-operation reducers from side-effecting collector/span calls.

## Recommended Order

Phase 3 — state-machine work after refactors isolate pure transitions.

---
Raised from PR $PR_URL by @$ASSIGNEE."

echo "All issues created."

Length of output: 622


@leynos All 14 issues have been created and assigned to you:

Issue Area Phase
#65 _emit_completed_lines / _strip_line_ending (_streams.py) 1
#66 CuprumContext.narrow / _validate_timeout (context.py) 1
#67 _build_final_results (concurrent.py) 1
#68 ProgramCatalogue indexing (catalogue.py) 1
#69 _coerce_argv / make / Pipeline.concat (sh.py) 1
#70 safe_path / git_ref (builders/args.py) 2
#71 tar_create / rsync_sync (builders/tar.py) 2
#72 _read_backend_env / get_stream_backend (_backend.py) 2
#73 _PipelineWaitState / _process_completed_task (_pipeline_wait.py) 3
#74 _pipeline_streams dispatch/FD lifecycle (_pipeline_streams.py) 3
#75 _handle_subprocess_timeout / _terminate_pipeline_remaining_stages 3
#76 Benchmark comparison / ratchet reducers (comparison_analysis.py) 2
#77 Folded stack summarisation (summarize_folded.py) 2
#78 Metrics/tracing/logging hooks (metrics_adapter.py) 3

@leynos

leynos commented May 22, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai please create new GitHub issues for the following:

Ranked Candidates

Baseline: I found no Rust-level #[test], proptest, kani, or verus coverage under rust/cuprum-rust. Current coverage is Python integration/scenario coverage around the extension.

Target Tool Justification Benefit Cost Verifiability Improvement
decode_utf8_replace proptest, some Kani Correctness depends on arbitrary byte streams and chunk boundaries. Fixed tests cover only a few invalid/incomplete UTF-8 examples. Proves Rust decoding matches String::from_utf8_lossy across arbitrary payloads and partitions. Low-medium. Pure logic, good shrinkability. Add decode_chunks(chunks) -> (String, pending) or a pure decode_step helper.
handle_utf8_error / handle_incomplete_sequence Kani Indexing and drain(..valid_up_to + error_len) are safe only under Utf8Error-derived bounds. Exhaustively checks bounded malformed byte layouts for no panic and correct pending/output transitions. Medium. Needs small harness or transition extraction. Replace implicit mutation with an enum action like ReplaceAndDrain(n) / KeepTail(n).
append_valid_prefix Kani Contains unsafe from_utf8_unchecked; invariant is external to the type system. Confirms checked and unchecked prefix decoding are equivalent for bounded valid prefixes. Low-medium. Keep unsafe block tiny; add debug assertion or a checked helper for verification builds.
validate_buffer_size proptest Current tests hit 0 and normal values, not platform boundary values. Proves all non-positive values reject and accepted values fit usize. Low. Extract checked_buffer_size(i64) -> Result<usize, ErrorKind> and add an explicit upper memory cap.
convert_fd proptest FD/handle conversion is platform-gated; Windows branch is not exercised here. Catches negative, truncation, and range boundary errors before I/O starts. Low, except CI needs platform coverage. Use shared pure range-check helper before platform conversion. Explicitly reject negative Windows handles.
pump_stream_files_readwrite proptest, Kani after refactor Writer-open state latches after non-fatal write errors; fixed tests cover only broad cases. Proves total bytes are monotonic, writes stop after broken pipe, reader drain continues, fatal errors propagate. Medium-high without seams. Extract a pure pump state machine over ReadEvent and WriteEvent.
handle_write_result / is_nonfatal_write_error proptest Error taxonomy and saturating total updates are policy-sensitive. Proves only BrokenPipe and ConnectionReset are suppressed and success updates totals correctly. Low. Return a typed enum: WriteAction::Continue(bytes), Stop, Fail(err).
try_splice_pump Kani, proptest with fake syscalls Linux splice branch has several rare error policies: EINVAL, broken pipe, fatal errors, EOF. Exhaustively checks dispatch policy and fallback decision boundaries. Medium-high. Real syscalls are unsuitable for Kani. Introduce a SpliceOps trait or scripted syscall seam.
splice_loop Kani Accumulation and termination depend on syscall result sequences. Proves total equals initial plus successful splice bytes until EOF/error, with drain on non-fatal write error. Medium after syscall seam. Extract pure transition over bounded SpliceResult traces.
drain_reader Kani It currently exits on any read <= 0; EINTR/EAGAIN policy is not modelled. Clarifies whether interrupted/nonblocking reads should retry or terminate. Medium. Return io::Result<()> and inject read operation for scripted verification.
file_from_raw / pump_stream / consume_stream Verus only after refactor; Kani for bounded paths FD ownership invariant is manual: reader is borrowed and forgotten, writer is consumed. Proves no accidental reader close / double-close in the model and writer closes intentionally. High. Verus needs an ownership model, not raw File effects. Replace mem::forget(reader) with ManuallyDrop<File> or typed BorrowedFd/OwnedFd wrappers.
rust_pump_stream / rust_consume_stream proptest at Python/Rust boundary Error mapping and default argument equivalence are currently scenario-tested. Proves invalid conversion returns ValueError, I/O failures map to OSError, defaults match explicit values. Medium. Cross-language tests are slower. Add internal RustStreamError enum and convert to PyO3 errors in one place.

Tool Fit

  • proptest first: UTF-8 chunking, buffer/FD conversion, consume output equivalence, write-error taxonomy.
  • Kani next: bounded state machines after seams are added: UTF-8 error transitions, write latch, splice policy, syscall traces.
  • Verus sparingly: only FD ownership/lifetime modelling is plausibly worth it. Most current code is I/O-bound and not a natural Verus target until pure ownership/state abstractions exist.

Highest-ROI First Step

Add Rust unit/property test support and start with decode_utf8_replace. It is pure, central to correctness, and likely to find real boundary issues fastest. Then extract event/state seams for pump_stream_files_readwrite and splice_loop; those are the best Kani candidates.

@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: 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 `@docs/developers-guide.md`:
- Line 307: The doc uses British "-ise" forms; update all occurrences of the
tokens "serialisation", "serialises", and "serialised" in
docs/developers-guide.md to the en-GB-oxendict "-ize" forms "serialization",
"serializes", and "serialized" respectively (including the other occurrences
noted in the review), by performing a targeted find-and-replace so the
documentation conforms to repository spelling standards.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7d3229e5-de2e-452e-8341-660e3035f3d2

📥 Commits

Reviewing files that changed from the base of the PR and between 1a4c47b and af8468c.

📒 Files selected for processing (2)
  • docs/developers-guide.md
  • rust/cuprum-rust/tests/ui/fail/invalid_pymodule_return.stderr
💤 Files with no reviewable changes (1)
  • rust/cuprum-rust/tests/ui/fail/invalid_pymodule_return.stderr

Comment thread docs/developers-guide.md Outdated
leynos and others added 11 commits June 10, 2026 20:57
Add Hypothesis coverage for generated backend selector reentrancy and
concurrent worker completion inputs. Document the selector state-machine
invariants and add checkpointed interleaving coverage for lock-serialised
environment mutation.
Separate core worker execution, selector concurrency, and CLI validation
coverage into focused test modules. Move the Syrupy snapshots to the
matching module snapshot files so the existing snapshot assertions keep
using the same keys after collection.
Use the availability-aware backend strategy for generated reentrancy
cases and centralize concurrency wait/join timeouts so slow CI tuning

only changes one place.
Leave the remaining two-thread orchestration cases separate because
their event sequencing differs and the shared multi-worker path already uses `_assert_backend_pair_completes`.
Refresh the maturin wheel contents snapshot so it expects the split tee
profile worker test modules and their renamed snapshot files.
Instrument the test-only backend lock wrapper so the interleaving test
sets `second_waiting_for_lock` only after a blocking acquire observes the
lock is already held.

Keep production selector code unchanged and preserve the existing
serialised environment observation assertion.
Move backend availability decisions out of module-level constants and
into small factory helpers so the concurrency tests avoid import-time
conditional work.

Use a deferred Hypothesis strategy for generated backend names while
preserving the existing test settings and assertions.
Share the timeout join and alive-thread assertion used by the selector
interleaving tests so both scenarios report unfinished worker threads in
one consistent form.
- Add `timeout`, `capture_output`, and `text` options to the worker CLI
  subprocess test so hanging or non-zero exits surface immediate diagnostics.
- Centralise worker-thread completion checks in
  `_assert_backend_pair_completes` using `_join_and_assert_finished`.
- Assert that the interleaving selector test waits for the release signal before
  the second thread observes environment state.
Address the Sourcery "Developer Documentation" warning for #57. Add a
developers' guide section describing the three-way split of the
tee_profile_worker test suite (core, CLI, concurrency) and the
Hypothesis-based and checkpointed concurrency approach used to verify the
`_EnvBackendSelector` invariants: lock hold duration, environment restoration,
cache clearing, and same-thread reentrancy rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The repository follows en-GB Oxford spelling (-ize), as in the existing
"serialized"/"serializes" usage in docs/cuprum-design.md and the prevalent
"normalized", "synchronized", and "optimization" forms across the docs. Align
the newly added selector concurrency section by replacing "serialisation",
"serialises", and "serialised" with their -ize forms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebasing the worker test-suite documentation onto main's new "Rust property
testing and verification" section left two double blank lines around the
inserted headings, tripping markdownlint MD012. Collapse them to single blank
lines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lodyai
lodyai Bot force-pushed the issue-57-add-property-based-and-model-checking-concurrency-tests-for-envbackendselector branch from af8468c to ef488d2 Compare June 10, 2026 19:07
@leynos
leynos merged commit f6bfd19 into main Jun 10, 2026
17 of 18 checks passed
@leynos
leynos deleted the issue-57-add-property-based-and-model-checking-concurrency-tests-for-envbackendselector branch June 10, 2026 19:51
lodyai Bot pushed a commit that referenced this pull request Jun 10, 2026
Rebase #58 (EnvBackendSelector lock-contention and reentrant-rejection
metrics) onto origin/main. Main's #57/#62 reorganised the tee-profile worker
tests into core/concurrency/cli modules, while this branch had split the same
original file into result/selector_guard/selector_metrics. The two refactors
were structurally incompatible, so this re-integrates the branch's net value
onto main's now-canonical layout rather than replaying the old structural
commits:

- Keep the observability-metrics implementation in
  ``benchmarks/tee_profile_worker.py`` (``_MetricsState``, the selector
  ``metrics_state`` property, lock-wait/rejection accounting) plus the two new
  ``TeeProfileWorkerResult`` fields.
- Expose ``metrics_state`` on main's ``_CoordinatedBackendSelector`` and
  ``_CheckpointBackendSelector`` so they satisfy the ``BackendSelector``
  protocol that ``run_tee_profile_worker`` now relies on.
- Add ``test_tee_profile_worker_selector_metrics.py`` with the metrics tests,
  including the two reentrant-rejection cases that previously lived in the
  branch's selector_guard module; drop the branch's result/selector_guard/
  helpers modules as main's core/concurrency modules supersede them.
- Regenerate the worker-core and maturin-build snapshots for the new metrics
  fields and the updated test-file inventory.
- Re-apply the benchmark validator split, docstrings, docs links, selector
  metrics doc section, CrossHair confirmation-budget fix, and other #58 work
  that main did not touch.

Cargo and uv lockfiles are taken from main unchanged; no dependency changes
were introduced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lodyai Bot pushed a commit that referenced this pull request Jun 10, 2026
The rebase onto main brings the interrogate 100% docstring gate (#131)
together with the selector concurrency test helpers (#57/#62), whose
`_RLockLike` protocol methods and `_SignallingRLock` dunder/`release`
methods lacked docstrings. Add minimal NumPy-style docstrings so
`make lint` passes after the rebase.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lodyai Bot pushed a commit that referenced this pull request Jun 11, 2026
Rebase #58 (EnvBackendSelector lock-contention and reentrant-rejection
metrics) onto origin/main. Main's #57/#62 reorganised the tee-profile worker
tests into core/concurrency/cli modules, while this branch had split the same
original file into result/selector_guard/selector_metrics. The two refactors
were structurally incompatible, so this re-integrates the branch's net value
onto main's now-canonical layout rather than replaying the old structural
commits:

- Keep the observability-metrics implementation in
  ``benchmarks/tee_profile_worker.py`` (``_MetricsState``, the selector
  ``metrics_state`` property, lock-wait/rejection accounting) plus the two new
  ``TeeProfileWorkerResult`` fields.
- Expose ``metrics_state`` on main's ``_CoordinatedBackendSelector`` and
  ``_CheckpointBackendSelector`` so they satisfy the ``BackendSelector``
  protocol that ``run_tee_profile_worker`` now relies on.
- Add ``test_tee_profile_worker_selector_metrics.py`` with the metrics tests,
  including the two reentrant-rejection cases that previously lived in the
  branch's selector_guard module; drop the branch's result/selector_guard/
  helpers modules as main's core/concurrency modules supersede them.
- Regenerate the worker-core and maturin-build snapshots for the new metrics
  fields and the updated test-file inventory.
- Re-apply the benchmark validator split, docstrings, docs links, selector
  metrics doc section, CrossHair confirmation-budget fix, and other #58 work
  that main did not touch.

Cargo and uv lockfiles are taken from main unchanged; no dependency changes
were introduced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lodyai Bot pushed a commit that referenced this pull request Jun 12, 2026
Rebase #58 (EnvBackendSelector lock-contention and reentrant-rejection
metrics) onto origin/main. Main's #57/#62 reorganised the tee-profile worker
tests into core/concurrency/cli modules, while this branch had split the same
original file into result/selector_guard/selector_metrics. The two refactors
were structurally incompatible, so this re-integrates the branch's net value
onto main's now-canonical layout rather than replaying the old structural
commits:

- Keep the observability-metrics implementation in
  ``benchmarks/tee_profile_worker.py`` (``_MetricsState``, the selector
  ``metrics_state`` property, lock-wait/rejection accounting) plus the two new
  ``TeeProfileWorkerResult`` fields.
- Expose ``metrics_state`` on main's ``_CoordinatedBackendSelector`` and
  ``_CheckpointBackendSelector`` so they satisfy the ``BackendSelector``
  protocol that ``run_tee_profile_worker`` now relies on.
- Add ``test_tee_profile_worker_selector_metrics.py`` with the metrics tests,
  including the two reentrant-rejection cases that previously lived in the
  branch's selector_guard module; drop the branch's result/selector_guard/
  helpers modules as main's core/concurrency modules supersede them.
- Regenerate the worker-core and maturin-build snapshots for the new metrics
  fields and the updated test-file inventory.
- Re-apply the benchmark validator split, docstrings, docs links, selector
  metrics doc section, CrossHair confirmation-budget fix, and other #58 work
  that main did not touch.

Cargo and uv lockfiles are taken from main unchanged; no dependency changes
were introduced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
leynos added a commit that referenced this pull request Jun 14, 2026
* Integrate selector observability metrics onto restructured worker tests

Rebase #58 (EnvBackendSelector lock-contention and reentrant-rejection
metrics) onto origin/main. Main's #57/#62 reorganised the tee-profile worker
tests into core/concurrency/cli modules, while this branch had split the same
original file into result/selector_guard/selector_metrics. The two refactors
were structurally incompatible, so this re-integrates the branch's net value
onto main's now-canonical layout rather than replaying the old structural
commits:

- Keep the observability-metrics implementation in
  ``benchmarks/tee_profile_worker.py`` (``_MetricsState``, the selector
  ``metrics_state`` property, lock-wait/rejection accounting) plus the two new
  ``TeeProfileWorkerResult`` fields.
- Expose ``metrics_state`` on main's ``_CoordinatedBackendSelector`` and
  ``_CheckpointBackendSelector`` so they satisfy the ``BackendSelector``
  protocol that ``run_tee_profile_worker`` now relies on.
- Add ``test_tee_profile_worker_selector_metrics.py`` with the metrics tests,
  including the two reentrant-rejection cases that previously lived in the
  branch's selector_guard module; drop the branch's result/selector_guard/
  helpers modules as main's core/concurrency modules supersede them.
- Regenerate the worker-core and maturin-build snapshots for the new metrics
  fields and the updated test-file inventory.
- Re-apply the benchmark validator split, docstrings, docs links, selector
  metrics doc section, CrossHair confirmation-budget fix, and other #58 work
  that main did not touch.

Cargo and uv lockfiles are taken from main unchanged; no dependency changes
were introduced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix runtime Path annotations and per-selector metrics isolation

Two review fixes in the benchmark worker surface:

- benchmarks/_benchmark_types.py: import ``pathlib as pth`` at module runtime
  rather than only under ``TYPE_CHECKING``. ``PipelineBenchmarkConfig`` and
  ``PipelineBenchmarkRunResult`` annotate fields as ``pth.Path``, so under
  ``from __future__ import annotations`` a ``typing.get_type_hints(...)`` call
  raised ``NameError: name 'pth' is not defined``. The import carries a
  ``# noqa: TC003`` with a comment because the alias is needed at runtime;
  the repo-wide ``runtime-evaluated-decorators`` alternative would have forced
  25 unrelated TC004 import moves across the codebase.

- benchmarks/tee_profile_worker.py: ``_EnvBackendSelector`` now creates its own
  ``_MetricsState(threading.local())`` when no ``metrics_state`` is injected,
  instead of falling back to a module-global singleton. Two selectors on the
  same thread no longer share or reset each other's counters. The module-global
  ``_metrics_state`` is removed; ``run_tee_profile_worker`` already reads
  ``selector.metrics_state``, so worker and selector still agree.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address review: timing, docstring, int validation, metrics test

- tee_profile_worker._build_worker_result: capture wall_time_seconds before
  _manifest_hash and _scenario_label run, so manifest I/O no longer inflates
  the measured worker-run duration.
- _benchmark_type_validators: correct the module docstring's exception
  contract. It claimed all wrong-type inputs raise TypeError, but several
  helpers (_validate_backend, _validate_non_empty_string, _validate_payload_
  bytes) raise ValueError; state that each helper raises TypeError or
  ValueError per its own contract.
- tee_profile_scenarios._check_int_bound: validate the int type up front via
  the shared _validate_int (rejecting non-int and bool deterministically with
  TypeError, consistent with the other benchmark validators) before the range
  comparisons. The local helper is retained rather than replaced wholesale
  because perf-frequency needs an unbounded maximum that the centralised
  _validate_iteration_count (fixed 1000 cap) cannot express.
- test_tee_profile_worker_cli: assert the exported metrics fields
  (reentrant_rejection_count, lock_wait_seconds) in the subprocess JSON output.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix rebased selector test helpers

Forward metrics_state from the coordinated selector test helper so it satisfies the BackendSelector protocol after rebasing onto main's split worker-test layout.

Add the missing test-helper docstrings and adjust a comment that Ruff parsed as an invalid noqa directive, keeping the lint gate clean.

* Address selector observability review (#58)

Signal test lock contention only immediately before the blocking acquire,
so contention tests observe the real blocking path rather than the probe.

Route tee-profile driver bounds through the shared benchmark validators and
make alternate-backend test setup fail explicitly when Rust is unavailable
instead of falling back to `auto`.

Clarify that selector observability metrics are per worker invocation and
update the documented Windows wheel platforms.

* Sort concurrent worker type imports (#58)

Order the type-only imports in the concurrent worker tests so Ruff's import
sorting gate passes after the `ParameterSet` annotation change.

* Collapse duplicate blank lines in the developers' guide

Rebasing onto the merged toolchain-pin docs left double blank lines at
the seams between the existing tail sections and the sections this
branch appends, failing markdownlint MD012.

* Test worker metrics reset on selector reuse (#58)

Add an integration test that pre-populates an injected selector's metrics
state before running `run_tee_profile_worker`. This proves the worker resets
selector metrics at the run boundary, rather than relying only on isolated
`_MetricsState.reset()` coverage.

* Document selector metrics architecture (#58)

Add the design-level description for tee profile selector metrics, including
per-run reset scope, the `BackendSelector.metrics_state` protocol property,
and deterministic clock injection for lock-wait timing.

* Cover worker repeat upper bound in CLI tests (#58)

Add the missing invalid `repeat_count=1001` parametrized case so the CLI
configuration tests cover both lower and upper repeat-count validation.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add property-based and model-checking concurrency tests for _EnvBackendSelector

1 participant