Skip to content

Remove dead IPC-timeout constructors on CargoMetadataError (#98) - #113

Merged
leynos merged 5 commits into
mainfrom
issue-98-remove-dead-ipc-timeout-constructors
Jun 10, 2026
Merged

Remove dead IPC-timeout constructors on CargoMetadataError (#98)#113
leynos merged 5 commits into
mainfrom
issue-98-remove-dead-ipc-timeout-constructors

Conversation

@leynos

@leynos leynos commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #98

  • Delete CargoMetadataError.invalid_ipc_timeout() / non_positive_ipc_timeout() — dead code referenced only by their own test, duplicating cmd-mox messages on the wrong domain class.
  • Define the two messages once as module constants in lading/testing/cmd_mox_runner.py (INVALID_IPC_TIMEOUT_MESSAGE, NON_POSITIVE_IPC_TIMEOUT_MESSAGE); _resolve_cmd_mox_timeout references them.
  • Bug fix surfaced by the property test: NaN timeouts previously passed the timeout <= 0 guard and were returned as valid; they now raise CmdMoxError with the canonical non-positive message.

Testing

  • Hypothesis property test covers the timeout-resolution domain: None → default; finite positive → that value; everything else (non-numeric, zero, negative, NaN) → CmdMoxError with one of the two canonical messages.
  • syrupy snapshots pin both message strings so rewording is a deliberate, reviewed change.
  • Dead assertions removed from tests/unit/test_metadata_helpers.py.
  • make check-fmt, make lint, make typecheck, and make test (556 passed) all green.

🤖 Generated with Claude Code

Summary by Sourcery

Consolidate and canonicalize cmd-mox IPC-timeout error handling while tightening timeout validation and tests.

Bug Fixes:

  • Reject NaN cmd-mox IPC timeout values by treating them as invalid/non-positive and raising CmdMoxError with the canonical message.

Enhancements:

  • Define canonical IPC-timeout error message constants in cmd_mox_runner and use them as the single source of truth across the codebase.
  • Remove unused CargoMetadataError IPC-timeout convenience constructors that duplicated cmd-mox error messages.

Documentation:

  • Document the validation rules and canonical error messages for CMOX_IPC_TIMEOUT in the cmd-mox usage guide and developers guide.

Tests:

  • Add property-based and snapshot tests to cover the full CMOX_IPC_TIMEOUT resolution domain and pin the canonical error messages, while removing obsolete tests tied to deleted helpers.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e3dcad80-b7a6-4946-9636-905aa085e3d9

📥 Commits

Reviewing files that changed from the base of the PR and between 39e86f4 and 684179d.

📒 Files selected for processing (7)
  • docs/cmd-mox-usage-guide.md
  • docs/developers-guide.md
  • lading/testing/cmd_mox_runner.py
  • lading/workspace/metadata.py
  • tests/unit/__snapshots__/test_cmd_mox_integration.ambr
  • tests/unit/test_cmd_mox_integration.py
  • tests/unit/test_metadata_helpers.py
💤 Files with no reviewable changes (1)
  • tests/unit/test_metadata_helpers.py

Overview

This PR removes dead IPC-timeout constructors from the CargoMetadataError domain class and consolidates operator-facing timeout error messages as canonical constants in lading/testing/cmd_mox_runner.py. It hardens timeout validation to reject non-finite and non-positive values, and strengthens test coverage with property tests and snapshot assertions.

Changes

Code deletions

  • lading/workspace/metadata.py: Removed @classmethod helpers CargoMetadataError.invalid_ipc_timeout() and CargoMetadataError.non_positive_ipc_timeout() as unused, duplicative, and domain-misplaced methods that belonged in the cmd-mox runner instead.

Centralisation of error messages

  • lading/testing/cmd_mox_runner.py: Introduced two module-level constants as the canonical single source of truth for operator-facing messages:
    • INVALID_IPC_TIMEOUT_MESSAGE = "Invalid CMOX_IPC_TIMEOUT value" (for parse failures)
    • NON_POSITIVE_IPC_TIMEOUT_MESSAGE = "CMOX_IPC_TIMEOUT must be positive" (for invalid values: zero, negative, NaN, infinity, overflow)

Validation hardening

  • _resolve_cmd_mox_timeout() in lading/testing/cmd_mox_runner.py:
    • Added math.isfinite() check to reject NaN and infinite values (including overflow-to-infinity cases like 1e400), alongside the existing <= 0 guard for non-positive values.
    • Added logging via _LOGGER.warning() when validation fails, emitting the raw input value and the applicable validation rule.
    • Now raises CmdMoxError with canonical messages from the constants above, ensuring consistency and testability.

Test improvements

  • tests/unit/test_cmd_mox_integration.py:

    • Replaced single-purpose test with comprehensive suite covering the full timeout input domain.
    • Added parametrised tests for valid inputs (None → default; finite positive strings → float values) and invalid inputs (unparseable, zero, negative, NaN, infinity, overflow).
    • Added snapshot test (test_ipc_timeout_messages_are_stable) pinning the two canonical messages via Syrupy for stable, deliberate rewording.
    • Added Hypothesis property tests with a _TimeoutCase composite strategy generating inputs by class (default, finite positive, unparseable, out of range) with embedded expected outcomes; tests assert both correct resolution/exception and that the expected canonical message is used.
    • Added "totality" property asserting that any successful resolution is always finite and strictly positive (postcondition).
  • tests/unit/test_metadata_helpers.py: Removed obsolete test_error_convenience_constructors test validating the deleted CargoMetadataError helpers.

Documentation updates

  • docs/cmd-mox-usage-guide.md: Expanded the CMOX_IPC_TIMEOUT variable documentation to specify validation behaviour and failure modes, noting that the two canonical messages are pinned via snapshot and owned by lading/testing/cmd_mox_runner.py to ensure intentional, reviewed rewording.

  • docs/developers-guide.md: Added developer documentation explaining that _resolve_cmd_mox_timeout centralises timeout validation, with operator-facing messages as module constants pinned by Syrupy, and linked to the usage guide for operator-visible behaviour.

Snapshot capture

  • tests/unit/__snapshots__/test_cmd_mox_integration.ambr: New snapshot file capturing stable expected values for the two canonical messages.

Outcomes

  • 556 tests pass across the full CI suite (format check, lint, type check, unit tests).
  • Domain separation improved: timeout validation and messaging now live exclusively in the cmd-mox runner; CargoMetadataError focused on cargo-metadata-specific concerns.
  • Single source of truth: error messages for operators are centralised constants, snapshot-pinned, and documented in design guides; accidental duplication or silent message drift is prevented.
  • Validation strengthened: NaN, infinities, and non-positive values are consistently rejected; previously, NaN could pass the <= 0 guard if parsed.

Walkthrough

Centralise CMOX_IPC_TIMEOUT error messages as constants in lading/testing/cmd_mox_runner.py; make _resolve_cmd_mox_timeout reject non‑finite and non‑positive values; add snapshot and Hypothesis tests that pin messages and behaviours; remove duplicate constructors from CargoMetadataError; update docs to reference the canonical messages.

Changes

IPC Timeout Message Consolidation

Layer / File(s) Summary
Core timeout validation with canonical message constants
lading/testing/cmd_mox_runner.py
Import math; add INVALID_IPC_TIMEOUT_MESSAGE and NON_POSITIVE_IPC_TIMEOUT_MESSAGE; update _resolve_cmd_mox_timeout to warn and raise for non‑numeric inputs and to reject non‑finite (NaN/∞) and <= 0 values using math.isfinite and raise CmdMoxError with the canonical messages.
Snapshot and property-based timeout tests
tests/unit/test_cmd_mox_integration.py, tests/unit/__snapshots__/test_cmd_mox_integration.ambr
Add Hypothesis and snapshot imports; add parametrised tests for valid/invalid inputs; add Hypothesis strategies and property tests asserting exact resolution or canonical CmdMoxError messages; add snapshot pinning the two canonical messages.
Remove duplicate timeout message constructors
lading/workspace/metadata.py, tests/unit/test_metadata_helpers.py
Remove CargoMetadataError.invalid_ipc_timeout() and non_positive_ipc_timeout() classmethods; remove their assertions from metadata tests while preserving test_coerce_text_handles_bytes.
Documentation of canonical timeout message location
docs/cmd-mox-usage-guide.md, docs/developers-guide.md
Extend CMOX_IPC_TIMEOUT docs with validation rules and exact CmdMoxError messages; document that the messages are defined as constants in the cmd‑mox runner and are snapshot‑pinned.

Suggested labels

Issue

Consolidate the strings where they belong, pin them in tests and docs,
Reject NaN and infinite timeouts with a firm resolve,
Remove the duplicates; let the runner hold the canonical voice—
One source, tested and concise. 📌✨

Act as a test runner: run unit tests for `_resolve_cmd_mox_timeout` including Hypothesis cases and ensure snapshots match their pinned values. 
🚥 Pre-merge checks | ✅ 20
✅ Passed checks (20 passed)
Check name Status Explanation
Title check ✅ Passed The title directly aligns with the primary change: removing dead IPC-timeout constructors from CargoMetadataError, and properly references the linked issue (#98).
Description check ✅ Passed The description comprehensively relates to the changeset, detailing the removal of dead constructors, centralisation of error messages, bug fixes, and testing strategies.
Linked Issues check ✅ Passed All coding requirements from issue #98 are met: dead constructors removed [#98], messages centralised as constants [#98], property tests covering the timeout domain added [#98], snapshot assertions pinning messages implemented [#98], and obsolete tests removed [#98].
Out of Scope Changes check ✅ Passed All code changes directly support the stated objectives: removing dead code, centralising messages, hardening validation, expanding tests, and documenting the canonical message home—no extraneous modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Testing (Overall) ✅ Passed Parametrised tests pin messages with logging checks. Property tests cover diverse inputs. Snapshot tests lock message strings. Tests catch inverted logic and swapped error messages.
User-Facing Documentation ✅ Passed CMOX_IPC_TIMEOUT is test infrastructure, not end-user functionality. Documentation correctly targets developers (developers-guide.md, cmd-mox-usage-guide.md).
Developer Documentation ✅ Passed Developers-guide documents constants and canonical location; cmd-mox guide documents validation and errors with snapshot pinning; cross-references between guides present; single language only.
Module-Level Documentation ✅ Passed All modified Python modules carry comprehensive docstrings explaining purpose, utility, function, and inter-component relationships with appropriate detail levels for production and test modules.
Testing (Unit And Behavioural) ✅ Passed Tests cover meaningful behaviour, edge cases, and error paths; integration test exercises functional boundary via substituted adapters; Hypothesis strategies are independent with bundled outcomes.
Testing (Property / Proof) ✅ Passed Hypothesis property tests use composite strategies and independent postconditions to cover timeout-validation invariants, systematically exercising all input classes without restating implementation.
Testing (Compile-Time / Ui) ✅ Passed Snapshot test appropriately pins operator-facing error messages with focused assertions, stable serialisation, and clear semantic intent; complemented by parametrised tests.
Unit Architecture ✅ Passed Removed dead domain-crossing methods; centralised messages as module constants; made validation fallibility explicit; tests properly separate query, command, integration concerns.
Domain Architecture ✅ Passed IPC-timeout messages moved to adapter; dead domain methods removed; no cross-layer dependencies; domain uses protocol abstraction, maintaining clean separation.
Observability ✅ Passed Validation failures log raw value and rule violation at WARNING level before raising, providing sufficient context for operators to diagnose CMOX_IPC_TIMEOUT configuration errors.
Security And Privacy ✅ Passed No secrets, injection risks, or privacy exposures. Timeout validation improved with math.isfinite(). Error messages consolidated as constants, not exposed in logs/snapshots.
Performance And Resource Use ✅ Passed Deletes dead methods and adds validation with single O(1) math.isfinite() call on test setup; no unbounded growth, algorithmic regression, or hot-path blocking identified.
Concurrency And State ✅ Passed The PR introduces only immutable string constants and refactors validation logic; no shared mutable state, async code, locks, or concurrency patterns present.
Architectural Complexity And Maintainability ✅ Passed PR centralises error messages as module constants, removes dead code, and uses standard library tools; no unnecessary abstractions, layers, or circular dependencies introduced.
Rust Compiler Lint Integrity ✅ Passed The PR contains only Python code, documentation, and test snapshots—no Rust source files (.rs) exist in the repository, making the Rust compiler lint integrity check not applicable to this PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

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

View plan used: #98

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-98-remove-dead-ipc-timeout-constructors

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

@sourcery-ai

sourcery-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

Centralizes canonical cmd-mox IPC-timeout error messages in the cmd_mox_runner, tightens timeout validation (including explicit NaN rejection), adds property-based and snapshot tests around timeout resolution, removes dead CargoMetadataError IPC-timeout helpers and their tests, and updates docs to describe the new behavior and single source of truth for the messages.

File-Level Changes

Change Details Files
Centralize canonical IPC-timeout error messages and harden timeout validation logic, including NaN handling.
  • Introduce INVALID_IPC_TIMEOUT_MESSAGE and NON_POSITIVE_IPC_TIMEOUT_MESSAGE module-level constants as the single source of truth for operator-facing IPC-timeout messages.
  • Update _resolve_cmd_mox_timeout to use the new constants instead of inline strings.
  • Extend timeout validation to explicitly reject NaN values in addition to zero and negative timeouts, raising CmdMoxError with the canonical non-positive message.
lading/testing/cmd_mox_runner.py
Expand and stabilize cmd-mox integration tests around IPC-timeout behavior.
  • Import hypothesis and syrupy utilities to support property-based and snapshot testing for cmd-mox timeout resolution.
  • Add a syrupy snapshot test that pins the canonical IPC-timeout error messages so message changes are intentional and reviewed.
  • Add a Hypothesis property test that exercises the IPC-timeout input domain (None, floats, and short strings), asserting that None uses the default, finite positive floats round-trip, and all other cases raise CmdMoxError with one of the canonical messages.
tests/unit/test_cmd_mox_integration.py
tests/unit/__snapshots__/test_cmd_mox_integration.ambr
Remove dead CargoMetadataError IPC-timeout convenience constructors and their tests.
  • Delete invalid_ipc_timeout and non_positive_ipc_timeout classmethods from CargoMetadataError, since they were unused outside their own tests and carried cmd-mox-specific messages on the wrong domain type.
  • Remove unit tests that asserted behavior of the deleted CargoMetadataError IPC-timeout constructors.
lading/workspace/metadata.py
tests/unit/test_metadata_helpers.py
Document canonical IPC-timeout behavior and message ownership for cmd-mox.
  • Update the cmd-mox usage guide to describe validation of CMOX_IPC_TIMEOUT, including behavior for non-numeric, zero, negative, and NaN values, and to point to the canonical message constants in cmd_mox_runner.
  • Update the developers guide to document that IPC-timeout messages live only in cmd_mox_runner constants, are pinned via snapshot tests, and to cross-link to the cmd-mox usage guide section on environment variables.
docs/cmd-mox-usage-guide.md
docs/developers-guide.md

Assessment against linked issues

Issue Objective Addressed Explanation
#98 Remove CargoMetadataError.invalid_ipc_timeout / non_positive_ipc_timeout and any tests that reference them.
#98 Centralize IPC-timeout error messages as constants in the cmd-mox runner module and use them from _resolve_cmd_mox_timeout, documenting this canonical home in the docs.
#98 Add property-based tests and snapshot assertions for _resolve_cmd_mox_timeout, and update/remove obsolete tests accordingly.

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.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
leynos marked this pull request as ready for review June 9, 2026 22:17
sourcery-ai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot added the Issue label Jun 9, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 23111f2468

ℹ️ 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".

Comment thread lading/testing/cmd_mox_runner.py Outdated
@leynos

leynos commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

Annul any requirements that violate the en-GB-oxendict spelling (-ize / -yse / -our) conventions (for example a request to replace "normalize" with "normalise" or "artefact" with "artifact"), or where the requirement unnecessarily increases cyclomatic complexity.

## Overall Comments
- In `_resolve_cmd_mox_timeout` and its property-based test, positive infinities are currently treated as valid timeouts even though the test docstring explicitly talks about finite values; consider either rejecting `math.isinf(timeout)` alongside `math.isnan(timeout)` or tightening the Hypothesis strategy/docstring to match the intended domain.
- The property test `test_resolve_cmd_mox_timeout_domain` re-derives the parsing logic with `repr(value)` and `float(raw)`; you might simplify and harden this by expressing expectations directly in terms of the public behavior (e.g., via composite strategies that generate the three classes of inputs: default, valid positive, and invalid) rather than mirroring the implementation’s parsing logic.

## Individual Comments

### Comment 1
<location path="tests/unit/test_cmd_mox_integration.py" line_range="44-53" />
<code_context>
+@given(value=st.one_of(st.none(), st.floats(), st.text(max_size=12)))
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen property-based assertions to pin which canonical message is used for which class of invalid input

Right now the property test only checks that any `CmdMoxError` message is one of the two canonical strings. That would still pass if the messages were accidentally swapped between parse errors and non‑positive/NaN inputs. To lock in the intended mapping, either add a couple of example-based tests for representative categories (e.g. unparseable string → `INVALID_IPC_TIMEOUT_MESSAGE`, "0"/"-1"/"nan" → `NON_POSITIVE_IPC_TIMEOUT_MESSAGE`), or extend this property test to assert the specific expected message per input category when it’s unambiguous.

Suggested implementation:

```python
@given(value=st.one_of(st.none(), st.floats(), st.text(max_size=12)))
def test_resolve_cmd_mox_timeout_domain(value: float | str | None) -> None:
    """Resolution is total and uses the correct canonical message per input class.

    ``None`` yields the default, finite positive floats round-trip, unparseable
    strings raise :class:`CmdMoxError` with ``INVALID_IPC_TIMEOUT_MESSAGE``,
    and non-positive / NaN / infinite values raise
    :class:`CmdMoxError` with ``NON_POSITIVE_IPC_TIMEOUT_MESSAGE``.
    """
    raw = value if value is None or isinstance(value, str) else repr(value)

    # None → default timeout
    if raw is None:
        resolved = cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        # Assumes a canonical default timeout constant; adjust if named differently.
        assert resolved == cmd_mox_runner.DEFAULT_IPC_TIMEOUT
        return

    # Non-None: first, determine if it's parseable as a float
    try:
        parsed = float(raw)
    except (TypeError, ValueError):
        # Unparseable input → INVALID_IPC_TIMEOUT_MESSAGE
        with pytest.raises(Exception) as excinfo:
            cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        assert str(excinfo.value) == cmd_mox_runner.INVALID_IPC_TIMEOUT_MESSAGE
        return

    # Parseable float: decide between valid timeout vs NON_POSITIVE_IPC_TIMEOUT_MESSAGE
    if parsed > 0 and math.isfinite(parsed):
        resolved = cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        # Positive finite values should round-trip
        assert resolved == parsed
    else:
        # Non-positive, NaN, or infinite values → NON_POSITIVE_IPC_TIMEOUT_MESSAGE
        with pytest.raises(Exception) as excinfo:
            cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        assert str(excinfo.value) == cmd_mox_runner.NON_POSITIVE_IPC_TIMEOUT_MESSAGE

```

1. Ensure `pytest` and `math` are imported at the top of `tests/unit/test_cmd_mox_integration.py`, for example:
   ```python
   import math
   import pytest
   ```
   If they are already imported, no changes are needed.

2. The search block above only covers the beginning of `test_resolve_cmd_mox_timeout_domain`. You should extend the `<<<<<<< SEARCH` section to include the *entire* original body of that test function (down to its final line) before applying this replacement, so that the old implementation is fully replaced rather than partially overlapped.

3. Replace `cmd_mox_runner.DEFAULT_IPC_TIMEOUT` with the actual constant or helper your codebase uses for the default timeout, if it has a different name (e.g. `cmd_mox_runner.DEFAULT_CMD_MOX_TIMEOUT` or similar).

4. If `cmd_mox_runner._resolve_cmd_mox_timeout` raises a specific exception type (e.g. `CmdMoxError`) and you prefer type-precise assertions, change:
   ```python
   with pytest.raises(Exception) as excinfo:
   ```
   to:
   ```python
   with pytest.raises(cmd_mox_runner.CmdMoxError) as excinfo:
   ```
   (or the appropriate import/qualified name).
</issue_to_address>

### Comment 2
<location path="tests/unit/test_cmd_mox_integration.py" line_range="63-64" />
<code_context>
+            cmd_mox_runner._resolve_cmd_mox_timeout(raw)
+            == cmd_mox_runner._CMD_MOX_TIMEOUT_DEFAULT
+        )
+    elif parsed is not None and parsed > 0:
+        assert cmd_mox_runner._resolve_cmd_mox_timeout(raw) == parsed
+    else:
+        with pytest.raises(cmd_mox_runner.CmdMoxError) as excinfo:
</code_context>
<issue_to_address>
**question (testing):** The property test’s oracle currently treats positive infinity as valid, which conflicts with the docstring’s focus on finite positives

The oracle currently accepts `float('inf')` via `parsed > 0`, which contradicts the documented "finite" domain and could hide a later change to reject infinities. Either tighten the condition to something like `elif parsed is not None and math.isfinite(parsed) and parsed > 0:` (and adjust the assertions accordingly), or update the docstring to explicitly include positive infinity so the test and docs align.
</issue_to_address>

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== lading/testing/cmd_mox_runner.py ==="
cat lading/testing/cmd_mox_runner.py

echo ""
echo "=== tests/unit/test_cmd_mox_integration.py ==="
cat tests/unit/test_cmd_mox_integration.py

Length of output: 16765



@leynos Here is the status of each item.


✅ Overall Comment 1 — infinities treated as valid timeouts

Resolved. _resolve_cmd_mox_timeout now uses:

if not math.isfinite(timeout) or timeout <= 0:
    raise CmdMoxError(NON_POSITIVE_IPC_TIMEOUT_MESSAGE)

NaN, ±∞, and overflow-to-infinity values (e.g. "1e400") are all rejected. The property-test oracle mirrors this with if math.isfinite(parsed) and parsed > 0:.


✅ Comment 2 — oracle accepted positive infinity

Resolved. The oracle condition is now math.isfinite(parsed) and parsed > 0, so float('inf') is no longer treated as a valid timeout.


✅ Comment 1 — property test only checked membership, not per-class mapping

Resolved. The property test now asserts the specific canonical message per input class:

  • Unparseable string → INVALID_IPC_TIMEOUT_MESSAGE
  • Parseable but non-finite or non-positive → NON_POSITIVE_IPC_TIMEOUT_MESSAGE

The dedicated parametrised test test_resolve_cmd_mox_timeout_rejects_with_canonical_message additionally covers "inf", "Infinity", "nan", "1e400", "0", "-1" and pins each to the correct constant. The mapping cannot be silently swapped.


⚠️ Overall Comment 2 — property test re-derives parsing logic

Not yet addressed. The test still mirrors the implementation with repr(value) / try: float(raw). The original suggestion was to use composite Hypothesis strategies to express input classes directly. This would reduce cyclomatic complexity, so it cannot be annulled on complexity grounds. That said, it was phrased as a "might simplify" observation rather than a firm requirement — it is the only remaining open item. Raise a follow-up issue if you would like it tracked separately.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

Annul any requirements that violate the en-GB-oxendict spelling (-ize / -yse / -our) conventions (for example a request to replace "normalize" with "normalise" or "artefact" with "artifact"), or where the requirement unnecessarily increases cyclomatic complexity.

## Overall Comments
- In `_resolve_cmd_mox_timeout` and its property-based test, positive infinities are currently treated as valid timeouts even though the test docstring explicitly talks about finite values; consider either rejecting `math.isinf(timeout)` alongside `math.isnan(timeout)` or tightening the Hypothesis strategy/docstring to match the intended domain.
- The property test `test_resolve_cmd_mox_timeout_domain` re-derives the parsing logic with `repr(value)` and `float(raw)`; you might simplify and harden this by expressing expectations directly in terms of the public behavior (e.g., via composite strategies that generate the three classes of inputs: default, valid positive, and invalid) rather than mirroring the implementation’s parsing logic.

## Individual Comments

### Comment 1
<location path="tests/unit/test_cmd_mox_integration.py" line_range="44-53" />
<code_context>
+@given(value=st.one_of(st.none(), st.floats(), st.text(max_size=12)))
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen property-based assertions to pin which canonical message is used for which class of invalid input

Right now the property test only checks that any `CmdMoxError` message is one of the two canonical strings. That would still pass if the messages were accidentally swapped between parse errors and non‑positive/NaN inputs. To lock in the intended mapping, either add a couple of example-based tests for representative categories (e.g. unparseable string → `INVALID_IPC_TIMEOUT_MESSAGE`, "0"/"-1"/"nan" → `NON_POSITIVE_IPC_TIMEOUT_MESSAGE`), or extend this property test to assert the specific expected message per input category when it’s unambiguous.

Suggested implementation:

```python
@given(value=st.one_of(st.none(), st.floats(), st.text(max_size=12)))
def test_resolve_cmd_mox_timeout_domain(value: float | str | None) -> None:
    """Resolution is total and uses the correct canonical message per input class.

    ``None`` yields the default, finite positive floats round-trip, unparseable
    strings raise :class:`CmdMoxError` with ``INVALID_IPC_TIMEOUT_MESSAGE``,
    and non-positive / NaN / infinite values raise
    :class:`CmdMoxError` with ``NON_POSITIVE_IPC_TIMEOUT_MESSAGE``.
    """
    raw = value if value is None or isinstance(value, str) else repr(value)

    # None → default timeout
    if raw is None:
        resolved = cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        # Assumes a canonical default timeout constant; adjust if named differently.
        assert resolved == cmd_mox_runner.DEFAULT_IPC_TIMEOUT
        return

    # Non-None: first, determine if it's parseable as a float
    try:
        parsed = float(raw)
    except (TypeError, ValueError):
        # Unparseable input → INVALID_IPC_TIMEOUT_MESSAGE
        with pytest.raises(Exception) as excinfo:
            cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        assert str(excinfo.value) == cmd_mox_runner.INVALID_IPC_TIMEOUT_MESSAGE
        return

    # Parseable float: decide between valid timeout vs NON_POSITIVE_IPC_TIMEOUT_MESSAGE
    if parsed > 0 and math.isfinite(parsed):
        resolved = cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        # Positive finite values should round-trip
        assert resolved == parsed
    else:
        # Non-positive, NaN, or infinite values → NON_POSITIVE_IPC_TIMEOUT_MESSAGE
        with pytest.raises(Exception) as excinfo:
            cmd_mox_runner._resolve_cmd_mox_timeout(raw)
        assert str(excinfo.value) == cmd_mox_runner.NON_POSITIVE_IPC_TIMEOUT_MESSAGE

```

1. Ensure `pytest` and `math` are imported at the top of `tests/unit/test_cmd_mox_integration.py`, for example:
   ```python
   import math
   import pytest
   ```
   If they are already imported, no changes are needed.

2. The search block above only covers the beginning of `test_resolve_cmd_mox_timeout_domain`. You should extend the `<<<<<<< SEARCH` section to include the *entire* original body of that test function (down to its final line) before applying this replacement, so that the old implementation is fully replaced rather than partially overlapped.

3. Replace `cmd_mox_runner.DEFAULT_IPC_TIMEOUT` with the actual constant or helper your codebase uses for the default timeout, if it has a different name (e.g. `cmd_mox_runner.DEFAULT_CMD_MOX_TIMEOUT` or similar).

4. If `cmd_mox_runner._resolve_cmd_mox_timeout` raises a specific exception type (e.g. `CmdMoxError`) and you prefer type-precise assertions, change:
   ```python
   with pytest.raises(Exception) as excinfo:
   ```
   to:
   ```python
   with pytest.raises(cmd_mox_runner.CmdMoxError) as excinfo:
   ```
   (or the appropriate import/qualified name).
</issue_to_address>

### Comment 2
<location path="tests/unit/test_cmd_mox_integration.py" line_range="63-64" />
<code_context>
+            cmd_mox_runner._resolve_cmd_mox_timeout(raw)
+            == cmd_mox_runner._CMD_MOX_TIMEOUT_DEFAULT
+        )
+    elif parsed is not None and parsed > 0:
+        assert cmd_mox_runner._resolve_cmd_mox_timeout(raw) == parsed
+    else:
+        with pytest.raises(cmd_mox_runner.CmdMoxError) as excinfo:
</code_context>
<issue_to_address>
**question (testing):** The property test’s oracle currently treats positive infinity as valid, which conflicts with the docstring’s focus on finite positives

The oracle currently accepts `float('inf')` via `parsed > 0`, which contradicts the documented "finite" domain and could hide a later change to reject infinities. Either tighten the condition to something like `elif parsed is not None and math.isfinite(parsed) and parsed > 0:` (and adjust the assertions accordingly), or update the docstring to explicitly include positive infinity so the test and docs align.
</issue_to_address>

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== tests/unit/test_cmd_mox_integration.py ==="
cat tests/unit/test_cmd_mox_integration.py

echo ""
echo "=== lading/testing/cmd_mox_runner.py ==="
cat lading/testing/cmd_mox_runner.py

Length of output: 18693



@leynos All four items are now resolved.


✅ Overall Comment 1 — infinities treated as valid

Resolved. _resolve_cmd_mox_timeout uses if not math.isfinite(timeout) or timeout <= 0:, which rejects NaN, ±∞, and overflow-to-infinity values.


✅ Individual Comment 2 — oracle accepted positive infinity

Resolved. test_resolve_cmd_mox_timeout_is_total asserts math.isfinite(resolved) and resolved > 0, so positive infinity is no longer a passing outcome.


✅ Individual Comment 1 — property test only checked membership, not per-class mapping

Resolved. test_resolve_cmd_mox_timeout_rejects_with_canonical_message pins the exact message per representative input, and test_resolve_cmd_mox_timeout_classes asserts the specific raises_message or resolves_to value attached to each generated case.


✅ Overall Comment 2 — property test re-derived parsing logic

Resolved. _timeout_cases() builds four input classes directly via composite Hypothesis strategies (default, finite_positive, unparseable, out_of_range), with each _TimeoutCase carrying its expected outcome. test_resolve_cmd_mox_timeout_classes asserts against that embedded expectation without re-deriving anything from float(raw). The remaining test_resolve_cmd_mox_timeout_is_total uses repr(value) only as a postcondition guard (finite positive or raises), not as a parsing oracle.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following failed checks now been resolved?

If further work is required, please provide an AI agent prompt for the remaining work to be done to address these failures.

Do not treat warnings as optional or aspirational. Where a change is out of scope for this PR, propose a GitHub issue unless one exists already.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Module-Level Documentation ❌ Error Modules lading/testing/cmd_mox_runner.py and lading/workspace/metadata.py lack adequate module docstrings explaining their relationship to other components, as required by the custom check. Expand module docstrings to explicitly document each module's purpose, utility, function, and relationship to other system components. Avoid one-sentence summaries alone.
Observability ⚠️ Warning Timeout validation errors lack logging. Invalid CMOX_IPC_TIMEOUT values raise CmdMoxError without logging, preventing maintainers from diagnosing failures without reading source code. Add logging to _resolve_cmd_mox_timeout() to emit diagnostic messages when validation fails, including raw value and failed validation rule.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== lading/testing/cmd_mox_runner.py ==="
cat lading/testing/cmd_mox_runner.py

echo ""
echo "=== lading/workspace/metadata.py ==="
cat lading/workspace/metadata.py

Length of output: 17862



@leynos Both checks are now resolved.


✅ Module-Level Documentation — resolved

Both modules now carry comprehensive multi-paragraph docstrings.

lading/testing/cmd_mox_runner.py explains: the adapter's role bridging cmd-mox's IPC server to the CommandRunner protocol; the entry point cmd_mox_runner; the validation, normalisation, and passthrough steps; its test-time counterpart relationship to lading.runtime.subprocess_runner; accepted command modules (lading.commands.publish_execution, lading.workspace.metadata); how to install the runner via use_command_runner; and the canonical home of the IPC-timeout message constants.

lading/workspace/metadata.py explains: its role as the workspace layer's gateway to cargo metadata; ownership of the CargoMetadataError hierarchy; delegation to the CommandRunner protocol; the default subprocess_runner adapter; and the context-local override mechanism via use_command_runner.


✅ Observability — resolved

_resolve_cmd_mox_timeout now emits a _LOGGER.warning on both validation failure paths, including the raw value and the specific rule that failed:

_LOGGER.warning(
    "Rejecting CMOX_IPC_TIMEOUT=%r: value is not a number", raw_timeout
)
_LOGGER.warning(
    "Rejecting CMOX_IPC_TIMEOUT=%r: %s is not a finite positive number",
    raw_timeout,
    timeout,
)

@leynos

leynos commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

leynos and others added 5 commits June 10, 2026 14:34
CargoMetadataError.invalid_ipc_timeout() and
non_positive_ipc_timeout() were referenced only by their own unit
test, duplicated the cmd-mox timeout messages verbatim, and placed an
IPC concern on a cargo-metadata error class.

Delete the two classmethods and define the messages once as constants
in lading.testing.cmd_mox_runner, the module that owns IPC-timeout
validation. While here, reject NaN timeouts explicitly: NaN compares
false against everything, so the previous `timeout <= 0` guard let it
slip through.

Add a Hypothesis property test driving _resolve_cmd_mox_timeout across
None, floats, and arbitrary strings, plus syrupy snapshots pinning the
two canonical messages.

Closes #98
Record where the IPC-timeout error messages live and how they behave, as
requested in review. The cmd-mox usage guide now describes CMOX_IPC_TIMEOUT
validation and names INVALID_IPC_TIMEOUT_MESSAGE and
NON_POSITIVE_IPC_TIMEOUT_MESSAGE as the single source of truth in
lading/testing/cmd_mox_runner.py, noting the syrupy snapshot that pins them.
The developers guide cross-references this from the command-runners section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Treat infinite CMOX_IPC_TIMEOUT values as invalid. float() returns
positive infinity for "inf", "Infinity", and overflowing literals such as
"1e400"; the old `math.isnan(timeout) or timeout <= 0` guard let infinity
through because it is positive, so the socket layer later crashed with
OverflowError instead of the documented CmdMoxError. Resolution now
requires a finite value via `not math.isfinite(timeout)`, routing NaN and
both infinities through the non-positive message.

Strengthen the tests so the canonical messages are tied to the
implementation rather than merely snapshotted:

- Add parametrised example tests pinning each input class to its specific
  message (unparseable -> INVALID_IPC_TIMEOUT_MESSAGE; zero/negative/NaN/
  infinite -> NON_POSITIVE_IPC_TIMEOUT_MESSAGE), including "inf",
  "Infinity", and "1e400". This locks the mapping so the two strings
  cannot be silently swapped, and makes the snapshot test non-vacuous by
  asserting the runner actually raises with those constants.
- Fix the property-test oracle to reject infinity with
  `math.isfinite(parsed)` and assert the specific expected message per
  input class instead of accepting either.

Document infinity (and overflowing literals) among the rejected values in
the cmd-mox usage guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The domain property test previously re-derived its expectations by calling
float() and math.isfinite() on each generated value, mirroring the resolver's
own parsing. Replace it with composite Hypothesis strategies that construct
each input class directly and attach the expected outcome to the input:

- finite positive floats (rendered via repr) that resolve to a timeout,
- consonant-only strings drawn from an alphabet that excludes every letter
  in "inf"/"infinity"/"nan" and the exponent marker, so they are guaranteed
  unparseable and map to INVALID_IPC_TIMEOUT_MESSAGE,
- zero, negative, NaN, and infinite values that map to
  NON_POSITIVE_IPC_TIMEOUT_MESSAGE,
- None mapping to the default.

The new class-based test asserts the contract directly with a flat
two-branch body, lowering cyclomatic complexity. A separate totality
property over arbitrary input asserts the postcondition (a finite positive
result or a CmdMoxError) without restating the parsing rules, guarding
against a regression that returns an unusable timeout for some unforeseen
value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address the module-documentation and observability review checks.

Expand the module docstrings for the cmd-mox runner and the cargo-metadata
gateway so each explains its purpose, the helpers it owns, and its
relationship to the shared CommandRunner protocol and the sibling adapters,
rather than a one-line summary. Note that cmd_mox_runner is the test-time
counterpart of subprocess_runner and the canonical home of the IPC-timeout
messages, and that metadata routes cargo metadata through the protocol so
use_command_runner can swap in the cmd-mox adapter.

Add diagnostic logging to _resolve_cmd_mox_timeout: each rejection now emits
a warning naming the rejected raw CMOX_IPC_TIMEOUT value and the rule it
failed (not a number, or not a finite positive number), so a misconfigured
timeout can be traced without reading the source. Extend the rejection test
to assert the warning is emitted with the raw value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lodyai
lodyai Bot force-pushed the issue-98-remove-dead-ipc-timeout-constructors branch from 6c3f5c4 to 684179d Compare June 10, 2026 12:37
@leynos
leynos merged commit 0ce5a3e into main Jun 10, 2026
5 checks passed
@leynos
leynos deleted the issue-98-remove-dead-ipc-timeout-constructors branch June 10, 2026 12:58
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.

Remove dead, misplaced IPC-timeout constructors on CargoMetadataError

1 participant