Hypothesis state-machine tests for pipeline completion, and fail-fast telemetry (#73, #285) - #243
Conversation
Reviewer's GuideExtracts pipeline completion decision logic into a pure Sequence diagram for pipeline task completion and fail-fast terminationsequenceDiagram
participant Task
participant _process_completed_task
participant _PipelineWaitState
participant _terminate_pipeline_remaining_stages
Task->>_process_completed_task: result()
_process_completed_task->>_PipelineWaitState: record_completion(idx, exit_code, ended_at)
alt [record_completion returns True]
_process_completed_task->>_terminate_pipeline_remaining_stages: _terminate_pipeline_remaining_stages(processes, wait_tasks, idx, cancel_grace)
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Summary
WalkthroughThe pipeline wait path now records deterministic completion metadata, latches the first failure, publishes a sanitised ChangesPipeline fail-fast observability
Sequence Diagram(s)sequenceDiagram
participant Stage as completed pipeline stage
participant Wait as _process_completed_task
participant State as _PipelineWaitState
participant Event as ExecEvent observer
participant Adapter as logging metrics tracing adapters
participant Teardown as pipeline teardown
Stage->>Wait: return exit code
Wait->>State: record completion and latch failure
State->>Event: publish pipeline_fail_fast
Event->>Adapter: project structured telemetry
Wait->>Teardown: terminate remaining stages
Teardown->>Stage: complete escalation and reaping
Suggested labels: Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 3 warnings)
✅ Passed checks (16 passed)
Full details: Linked Issues checkExplanation Mark the linked objectives as met. The changes provide deterministic completion handling and verification coverage for Full details: Out of Scope Changes checkExplanation The PR includes changes that are not clearly required by Full details: Docstring CoverageExplanation Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 165 functions across 29 files. (4 skipped: 4 unsupported.) Full details: Testing (Overall)Explanation PASS: Verify the changed behaviour is covered by substantive tests. Hypothesis state-machine, CrossHair contracts, pinned examples, and async-boundary tests check completion-slot writes, completion-order failure latching, timestamp handling, final/single-stage rules, batch ordering, and exactly-once termination. Direct event tests and real three-stage subprocess tests check fail-fast emission, ordering, correlation, sanitisation, tag shadowing, no-emission cases, and hook failures. Adapter tests check exact metric labels, tracing span lifecycle, warning level, configurable logging, and sensitive-data exclusion. Cancellation tests exercise SIGTERM-to-SIGKILL escalation, repeated cancellation, real subprocess reaping, and late-settling termination counts. The tests assert product state and published payloads, not only mock calls. Full details: User-Facing DocumentationExplanation Pass the user-facing documentation check. The PR changes Full details: Developer DocumentationExplanation Pass the developer documentation check. Full details: Module-Level DocumentationExplanation All changed and newly added Python modules have a module-level docstring. The docstrings state each module's purpose and utility. The relevant component relationships are also documented, including Full details: Testing (Unit And Behavioural)Explanation Accept the testing coverage. The unit tests exercise the extracted transition with pinned examples, randomized Hypothesis state-machine checks, CrossHair contracts, batch ordering, timing slots, first-failure latching, final and single-stage failures, success paths, hook failures, late-settlement outcomes, and cancellation teardown. The adapter tests cover metrics, tracing, logging, sanitisation, correlation, and error handling. The behavioural BDD tests call the public pipeline API with real stages, and the new wiring tests run real subprocess pipelines through Full details: Testing (Property / Proof)Explanation Pass this check. The PR introduces a Hypothesis Full details: Testing (Compile-Time / Ui)Explanation Record PASS. The PR changes Python only; no Rust or TypeScript files changed, so no trybuild-equivalent test applies. The structured adapter projections use focused Syrupy snapshots, including Full details: Unit ArchitectureExplanation FAIL — the new fail-fast event path hides a wall-clock dependency. The pull request adds Resolution Inject a narrow wall-clock callable at the observation boundary, for example Full details: Domain ArchitectureExplanation The PR introduces a core-to-logging representation leak. Resolution Remove the direct Full details: ObservabilityExplanation Mark Observability as PASS. The changed pipeline wait path logs first-failure, termination-start, and termination-outcome records with stage, exit, correlation, elapsed-time, and confirmed termination fields. It emits a sanitized Full details: Security And PrivacyExplanation Pass the Security and Privacy check. The PR adds no credentials, secrets, permissions, or unsafe deserialisation. Allowlist enforcement remains before pipeline spawning, and subprocess calls remain parameterized. The new fail-fast event removes argv, cwd, env, tags, output, and error text. Logging applies the same sanitisation and emits only bounded decision fields plus the intended execution correlation ID. Metrics use only program and project labels. Tracing records only typed stage, exit, and duration fields on the matching span. Added test markers such as Full details: Performance And Resource UseExplanation The logging adapter adds an avoidable per-event allocation on a hot path. Before the pull request, Resolution Remove the per-event dictionary construction. Build the phase-to-level mapping once in Full details: Concurrency And StateExplanation PASS — the pull request makes ownership, ordering, locking, task lifetime, and cancellation behaviour explicit, and adds focused interleaving tests. Full details: Architectural Complexity And MaintainabilityExplanation Keep the change. The new abstractions map to concrete seams: Full details: Rust Compiler Lint IntegrityExplanation Pass this check. The complete PR range from merge-base e6775b8 to HEAD contains no changes to Rust source, Cargo manifests, Cargo.lock, or Rust lint configuration. The patch adds no Rust lint suppressions or clone calls. Existing Rust expectations are outside the PR diff, so the custom Rust integrity failure conditions are not applicable. ✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Your free Security trial is over. An organization admin can activate billing to continue. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@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. (Treat documentation and validation coverage as in scope). #73 Introduce CrossHair-based verification for the refactored pure transition logic after the refactor. ❌ The PR only adds the |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
Completed issue #73's CrossHair criterion and both unresolved pre-merge warnings in 28ca2a7. No follow-up issue raised — this was in scope. CrossHair verification
The model is deliberately small: preconditions cap the pipeline at three stages, exit codes at I confirmed the contracts actually verify rather than rubber-stamp. Two mutations of the production code both produce
The import-time probe follows One thing I changed beyond the brief: that probe logic already existed in Observability
Neither fires for a successful exit, a later failure once latched, or a final-stage or single-stage failure. Logging stays in the async caller — moving it into Five log-capture tests pin those cases with a monkeypatched clock (so elapsed times are exact, not timing-dependent), and assert the termination-call count stays consistent with the records. Also mutation-checked: logging the first-failure record unconditionally, or dropping the termination record, each fail them. Documentation
uv run pytest -q cuprum/unittests/test_pipeline_wait_crosshair.py -m crosshair
uv run crosshair check cuprum/unittests/test_pipeline_wait_crosshair.py --analysis_kind=PEP316
Validation
Two issues surfaced during validation and were fixed: pylint counts |
Completes issue #75's CrossHair criterion. The Hypothesis module is unchanged; this adds bounded symbolic verification alongside it. Five PEP 316 contracts, executed through check_states and required to return MessageType.CONFIRMED: _resolve_timeout_payload — a carried _SubprocessTimeoutError returns its own timeout, stdout, stderr, and exit time verbatim (the fallback in that contract holds different values and a None configured timeout, so a resolver consulting it would return a wrong field or raise); a bare TimeoutError with a configured timeout returns the fallback's four fields exactly; a bare TimeoutError without one raises _SubprocessInvariantError. _stages_to_terminate — the selection is in range, unique, ordered, excludes the failure index, contains only stages whose done flag is False, and equals exactly the unfinished non-failed set; and cleanup is idempotent, since marking the selected stages done makes a second pass select nothing. The domains are bounded so CrossHair exhausts them rather than returning CANNOT_CONFIRM: at most three stages with failure_index constrained by precondition, done flags encoded as one bounded integer bitmask rather than a symbolic list of symbolic booleans, and three-value enumerations for times and text (including None) since the reducers only copy those values while keeping carried and fallback distinguishable. Verified genuine rather than assumed: making the carried branch read the fallback's stdout, and dropping the failed-stage exclusion from the selection, each yield POST_FAIL instead of CONFIRMED. The module matches PYTEST_TARGETS' cuprum/unittests/test_*.py glob, so make test collects and runs it — the checks are automated, not just documented. Availability uses the shared _crosshair_support.py probe (byte-identical to the copy on the #243 branch, so the two merge cleanly), which degrades to a skip only for a missing dependency or an untraceable interpreter; anything else, including CANNOT_CONFIRM, fails. Documents the verified invariants, both commands, and the deliberate bounds in the developers guide, and regenerates the wheel manifest for the two new files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. Excess Number of Function Argumentscuprum/unittests/test_pipeline_wait_crosshair.py: _latches_first_failure What lead to degradation?_latches_first_failure has 5 arguments, max arguments = 4 Why does this problem occur?Functions with many arguments indicate either a) low cohesion where the function has too many responsibilities, or b) a missing abstraction that encapsulates those arguments. How to fix it?Start by investigating the responsibilities of the function. Make sure it doesn't do too many things, in which case it should be split into smaller and more cohesive functions. Consider the refactoring INTRODUCE PARAMETER OBJECT to encapsulate arguments that refer to the same logical concept. |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. Excess Number of Function Argumentscuprum/unittests/test_pipeline_wait_crosshair.py: _first_failure_latch_contract What lead to degradation?_first_failure_latch_contract has 5 arguments, max arguments = 4 Why does this problem occur?Functions with many arguments indicate either a) low cohesion where the function has too many responsibilities, or b) a missing abstraction that encapsulates those arguments. How to fix it?Start by investigating the responsibilities of the function. Make sure it doesn't do too many things, in which case it should be split into smaller and more cohesive functions. Consider the refactoring INTRODUCE PARAMETER OBJECT to encapsulate arguments that refer to the same logical concept. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
CodeScene finding cleared in 5457037 — file health 9.68 → 10.0. One decision worth surfacingThe two specifications conflicted, so I checked the actual finding before choosing: CodeScene flags both functions. The second specification asked to refactor only So I refactored both, but used the second specification's tuple shape: one Both functions now take three arguments: The helper unpacks both tuples immediately; the state construction, the ordered The symbolic domain is preserved exactly, with the preconditions now bounding each tuple element: The refactor did not weaken the verificationSymbolic tuple parameters could in principle degrade CrossHair's exploration, so I checked rather than trusting four green ticks. Two mutations of
Commands and outcomes
|
Preserve the lost-wakeup fallback while passing immutable stage context through the updated wait API. Align the legacy and synthetic test doubles, stabilise timeout teardown startup, and regenerate the wheel manifest.
Preserve the rebased fail-fast and cancellation behaviour while applying the formatter and NumPy return documentation required by the new main branch lint policy.
Extract the independent logging, tracing, and metrics assertion groups so the Hypothesis property remains a concise coordinator without weakening its projection contracts.
Route pipeline-wait warnings through the structured logging adapter, keep the sanitised event's trusted project label, and serialise same-stage trace callbacks against exit. Cover record ordering, process-exit polling isolation, and the fail-fast tracing race while updating the user and design contracts.
Move the record-ordering contract out of the async-boundary suite so each pipeline-wait test module stays below the repository's size limit. Document the complete split suite and regenerate the wheel-manifest snapshot for the new test module.
Count one verified outcome for every selected teardown target, excluding stages that settle after selection before they can be terminated. Cover the race directly, split batch completion coverage into its own module, and clarify the completion-record and event channels.
Carry each record's action, message, and optional fields in one immutable report value so the adapter boundary no longer accepts an excessive argument surface. Keep the published fields unchanged and assert that teardown outcome fields remain exclusive to the termination-outcome record.
Match target-era pipeline tests to the current wait context and final-stage fail-fast policy. Restore formatter-required spacing and remove the replayed documentation blank line.
Keep legacy tracing imports as compatibility re-exports while making the public module the sole protocol definition. Document the separate direct pipeline-wait record contract and extract the verified-teardown race setup.
Preserve the direct pipeline-wait records while adding their execution correlation token to the structured fail-fast log projection. Clarify the associated telemetry and protocol boundaries, and improve failure diagnostics without changing teardown semantics.
Make lifecycle and fail-fast event timestamps deterministic at the observation boundary, and avoid rebuilding logging level maps for every event. Keep the reporter and structured-event channels distinct in the user documentation.
aa614eb to
60ca50c
Compare
Restore target-branch timeout observability documentation that was lost during the rebase, while retaining the pipeline fail-fast additions. Keep `TracingHook` below the module-size limit without weakening its documented attribute contract, and resolve the remaining Markdown and spelling gate findings.
|
@coderabbitai Please investigate the cause of the following issue using codegraph exploration and research, identify a fix and provide an AI coding agent prompt for the fix: https://github.com/leynos/cuprum/actions/runs/32840569935/job/97778914224?pr=243 |
This comment was marked as resolved.
This comment was marked as resolved.
|
@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. (Treat o11y, code safety, documentation and validation coverage as in scope). ❌ Failed checks (1 error, 2 warnings)
|
|
@coderabbitai Have the following now been resolved? cuprum/unittests/test_pipeline_fail_fast_tag_shadowing.py (1)
Keep phase filtering in the shared helper. duplication”. Proposed change- (event,) = [item for item in events if item.phase == _FAIL_FAST_PHASE]
+ (event,) = phase(events, _FAIL_FAST_PHASE)🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In Source: Coding guidelines docs/cuprum-design.md (1)
single-stage, or already-settled non-final failure emits that direct record even when no Proposed wording-`cuprum._pipeline_wait` consults the same reducer *before* it reports anything,
-so a completion that would select no stages is not announced as a fail-fast
-decision at all: no `pipeline_fail_fast` event is published.
+`cuprum._pipeline_wait` consults the same reducer before deciding whether to
+publish a fail-fast event. A completion that would select no stages is not
+announced as a `pipeline_fail_fast` decision, but its first-failure record is
+still published.🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In docs/users-guide.md (1)
records a fail-fast decision, not a completed teardown. Proposed wording-- `cuprum_pipeline_fail_fast_total`: Counter incremented once per pipeline torn
- down early because a non-final stage was the first to fail
+- `cuprum_pipeline_fail_fast_total`: Counter incremented once per fail-fast
+ decision when a non-final stage is the first to fail and another stage is
+ still running🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In |
|
@coderabbitai Have the following now been resolved? docs/users-guide.md (2)
📝 Proposed wording-`cuprum_exec_id`. Both fields carry the same existing execution token, which
-you can then use to find the individual stage spans behind the spike.
+`cuprum_exec_id`. Both fields carry the same existing execution token, which
+then identifies the individual stage spans behind the spike.Triage: 🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In Source: Path instructions 📝 Proposed wordingThe event carries the failing stage's index, pipeline width, exit code,
-duration, and execution token. It is sanitized: `argv` is empty, `cwd` and
-`env` are `None`, and `tags` is empty; only the program, trusted configured
-project, typed decision fields,
-and `ExecEvent.exec_id` remain.
+duration, and execution token. It is sanitized: the caller-controlled `argv`,
+`cwd`, `env`, and `tags` are removed, while the program, trusted configured
+project, typed decision fields, `pid`, `timestamp`, and `ExecEvent.exec_id`
+remain.Run the following script to confirm which fields the builder still populates: #!/bin/bash
set -eu
printf '%s\n' '--- fail-fast event construction ---'
rg -n -C 20 'pipeline_fail_fast' cuprum/_pipeline_types.py🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Current revision =='
git rev-parse --short HEAD
git show --no-patch --format='%H%n%s' HEAD
printf '%s\n' '== Changed target files =='
git diff --name-status origin/main...HEAD | rg \
'cuprum/(_pipeline_types|_pipeline_wait|_pipeline_wait_records)\.py|cuprum/adapters/logging_adapter\.py|test_.*(pipeline|adapter).*\.py|docs/' \
|| true
printf '%s\n' '== Pipeline types outline =='
ast-grep outline cuprum/_pipeline_types.py --items all \
--match 'StageObservation|PipelineWaitReporter|StageWaitContext' --view expanded
printf '%s\n' '== Pipeline event time source, reporter port, and constructors =='
rg -n -C 8 \
'time\.(time|monotonic)|datetime|def emit_fail_fast\b|def emit\b|class _PipelineWaitReporter\b|def report_pipeline_wait\b|class _StageObservation\b|_StageObservation\(' \
cuprum/_pipeline_types.py cuprum
printf '%s\n' '== Pipeline-wait reporting record boundary =='
ast-grep outline cuprum/_pipeline_wait_records.py cuprum/_pipeline_wait.py --items all --view expanded
rg -n -C 7 \
'report_pipeline_wait|_report_completion_event|_Completion(LogFields|Report)|pipeline_stage_first_failure|pipeline_fail_fast_(termination|terminated)|emit_fail_fast' \
cuprum/_pipeline_wait.py cuprum/_pipeline_wait_records.py cuprum/_pipeline_types.py
printf '%s\n' '== Logging hook level dispatch =='
ast-grep outline cuprum/adapters/logging_adapter.py --items all --match 'StructuredLoggingHook|structured_logging_hook|LogLevels' --view expanded
rg -n -C 8 \
'class _StructuredLoggingHook|def __call__|def structured_logging_hook|level_map|pipeline_fail_fast|LogLevels' \
cuprum/adapters/logging_adapter.py
printf '%s\n' '== Focused tests and docs =='
rg -n -C 5 \
'emit_fail_fast|wall_clock|time\.time|report_pipeline_wait|pipeline_stage_first_failure|pipeline_fail_fast_terminated|level_map|fail_fast_level' \
cuprum/unittests docs
printf '%s\n' '== Test and lint commands =='
rg -n -C 3 'pytest|ruff|pylint|typecheck|pyright|mypy' pyproject.toml Makefile tox.ini 2>/dev/null || trueLength of output: 107795 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Stage observation timestamp use =='
sed -n '76,178p' cuprum/_pipeline_types.py | cat -n
printf '%s\n' '== Production construction boundary =='
sed -n '88,126p' cuprum/_pipeline_internals.py | cat -n
sed -n '372,402p' cuprum/sh.py | cat -n
printf '%s\n' '== Deterministic observation support and fail-fast tests =='
sed -n '1,120p' cuprum/unittests/_pipeline_wait_support.py | cat -n
rg -n -C 10 \
'timestamp|12\.5|pipeline_fail_fast|emit_fail_fast|wall_clock' \
cuprum/unittests/test_pipeline_wait_fail_fast_event.py \
cuprum/unittests/test_pipeline_fail_fast_wiring.py \
cuprum/unittests/test_adapter_fail_fast.py \
cuprum/unittests/test_adapter_projection.py
printf '%s\n' '== Direct-record logger and adapter path =='
sed -n '1,150p' cuprum/_pipeline_wait_records.py | cat -n
sed -n '68,114p' cuprum/adapters/logging_adapter.py | cat -n
rg -n -C 6 \
'getLogger\("cuprum\._pipeline_wait"\)|report_pipeline_wait\(|pipeline_stage_first_failure|pipeline_fail_fast_termination|pipeline_fail_fast_terminated' \
cuprum/unittests docs CHANGELOG.md
printf '%s\n' '== Per-event allocation regression search =='
rg -n -C 4 \
'level_map\s*=\s*\{|_level_by_phase|structured_logging_hook\(' \
cuprum/adapters/logging_adapter.py cuprum/unittests/test_logging_adapter_properties.py
printf '%s\n' '== Current check status, if GitHub reports it =='
gh pr checks 243 --repo leynos/cuprum || trueLength of output: 84241
Use this suppression text for the Domain Architecture warning: Keep the direct pipeline-wait reporter path. It emits the documented
`pipeline_stage_first_failure`, `pipeline_fail_fast_termination`, and
`pipeline_fail_fast_terminated` standard-library records on the
`cuprum._pipeline_wait` logger at a fixed WARNING level. These records provide
ordered lifecycle diagnostics through the stable `cuprum_action` field.
Keep this path separate from the typed `pipeline_fail_fast` `ExecEvent`. The
event drives metrics, tracing, and opt-in structured logging at
`LogLevels.fail_fast_level`. A first-failure record is required even when no
fail-fast event is valid, including a final-stage failure and a completion batch
where no other stage remains running. Replacing the direct records with events
would change the documented logging, ordering, and privacy contracts.Do not create a new GitHub issue. No remaining code change is valid for these three checks. The current check status still shows a separate failure in Typecheck and test (Python 3.14). That failure is outside these three CodeScene findings. The earlier CI investigation identified the CrossHair warning-capture failure and the unclosed 🧠 Learnings usedYou are interacting with an AI system. |
|
@coderabbitai Have the following now been resolved? docs/cuprum-design.md (1)
defines projection. The current schema omits it, so it conflicts with the later fail-fast contract. must stay aligned with behaviour. 🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In Source: Path instructions docs/users-guide.md (1)
Proposed wording-The structured logging adapter renders these canonical wait records at WARNING.
+The optional pipeline-wait reporter emits these canonical wait records at a
+fixed WARNING level on `cuprum._pipeline_wait`. `structured_logging_hook()`
+separately renders the `pipeline_fail_fast` `ExecEvent` at
+`LogLevels.fail_fast_level`.Based on learnings, the fixed 🤖 Detailed instructionsUse a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results. In Source: Learnings |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Current revision =='
git rev-parse --short HEAD
git show --no-patch --format='%H%n%s' HEAD
printf '%s\n' '== Sanitized fail-fast event documentation =='
sed -n '260,292p' docs/users-guide.md | cat -n
printf '%s\n' '== Metrics/tracing token documentation =='
sed -n '980,1004p' docs/users-guide.md | cat -n
printf '%s\n' '== First/second-person pronouns in the relevant document ranges =='
rg -n -i -C 2 '\b(I|we|you|our|us)\b' docs/users-guide.md || true
printf '%s\n' '== Pipeline fail-fast event construction =='
ast-grep outline cuprum/_pipeline_types.py --items all \
--match 'StageObservation|emit_fail_fast' --view expanded
rg -n -C 20 'def emit_fail_fast\b|ExecEvent\(|pipeline_fail_fast|timestamp=|pid=|argv=|cwd=|env=|tags=' \
cuprum/_pipeline_types.pyLength of output: 10986
The documentation matches No further change or follow-up issue is required for these two findings. You are interacting with an AI system. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Current revision =='
git rev-parse --short HEAD
git show --no-patch --format='%H%n%s' HEAD
printf '%s\n' '== Documented ExecEvent schema =='
sed -n '790,835p' docs/cuprum-design.md | cat -n
printf '%s\n' '== Actual ExecEvent fields and fail-fast construction =='
ast-grep outline cuprum/events.py cuprum/_pipeline_types.py \
--items all --match 'ExecEvent|emit_fail_fast' --view expanded
rg -n -C 10 \
'class ExecEvent\b|project:|def emit_fail_fast\b|ExecEvent\(' \
cuprum/events.py cuprum/_pipeline_types.py
printf '%s\n' '== Pipeline-wait documentation =='
sed -n '245,285p' docs/users-guide.md | cat -n
printf '%s\n' '== Direct record and structured event logging contracts =='
rg -n -C 7 \
'report_pipeline_wait|pipeline_stage_first_failure|pipeline_fail_fast_termination|pipeline_fail_fast_terminated|getLogger\("cuprum\._pipeline_wait"\)|fail_fast_level|structured_logging_hook|pipeline_fail_fast' \
cuprum/_pipeline_wait_records.py cuprum/_pipeline_types.py \
cuprum/adapters/logging_adapter.py docs/users-guide.mdLength of output: 45604
The wording keeps the fixed pipeline-wait records separate from the configurable structured-event adapter. The inspection used the existing fail-fast observability contract learning. 🧠 Learnings usedYou are interacting with an AI system. |
Close handled `HTTPError` instances before retrying or propagating them, preventing deferred resource-cleanup warnings in CI. Make CrossHair fallback tests select their own warning so unrelated warnings cannot change their assertions.
Summary
Pipeline completion ordering — first-failure latching, timing-slot population,
and the fail-fast termination decision — used to live inline in
process_completed_task. It is now a deterministic state transition, which
addresses #73.
Seam
PipelineWaitState.record_completion(completed_idx, exit_code, *, ended_at):
stage.
The async wait layer supplies the clock, checks whether a stage remains to
terminate, publishes the event, and then performs termination.
Tests
A Hypothesis RuleBasedStateMachine exercises randomized completion orders
across 1–8 stages, plus pinned examples for completion order, final and
single-stage failures, all-success runs, and exactly-once fail-fast.
Review follow-up
observe event; metrics, tracing, and structured logging consume the same
domain-neutral output.
tags, with regression coverage across log, trace, metric, and snapshot-ready
payloads.
the event is observed, and guarantee cancellation-test PID cleanup in a
finally block.
Validation
Full gates green: make check-fmt, make lint (ruff, interrogate 100%, pylint
10.00/10), make typecheck, and make test (898 passed / 52 skipped; behavioural
suites 38 passed, 10 passed / 3 skipped, and 18 passed / 8 skipped; Rust
nextest 104/104).
Closes #73
This branch also carries the pipeline fail-fast telemetry — the
pipeline_fail_fast ExecPhase, the cuprum_pipeline_fail_fast_total counter, the
cuprum.pipeline_fail_fast span event on the failing stage's open span, the
LogLevels.fail_fast_level logging arm, and the adapter and tracing-protocol
changes that carry them. That work is required by
#285, which records its
acceptance criteria; it is not incidental scope.
Closes #285
🤖 Generated with Claude Code
Summary by Sourcery
Extract the pipeline completion decision logic into a pure state transition and
adapt the async handler to delegate to it while preserving behaviour.
Enhancements:
separate exit-code, timing, and fail-fast bookkeeping from async effects.
Tests:
completion ordering, first-failure semantics, and termination decisions.
References