Skip to content

test: Provider-Level Log-Stop Failure Test Coverage - #173

Merged
droid-ash merged 4 commits into
mainfrom
260731-cjx8-provider-log-stop-test-coverage
Jul 31, 2026
Merged

test: Provider-Level Log-Stop Failure Test Coverage#173
droid-ash merged 4 commits into
mainfrom
260731-cjx8-provider-log-stop-test-coverage

Conversation

@droid-ash

@droid-ash droid-ash commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Meta

Change ID Type Confidence Plan Review
cjx8 test 4.7/5.0 5/5 tasks, 11/11 acceptance ✓ ✓ 1 cycle
Impact +/− Net
true +456 / −1 +455
└ impl +390 / −1 +389
└ tests +66 / −0 +66

generated by fab-kit v2.16.8

Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr

Summary

PR #168 fixed a defect where stopLogCapture reported success over a log file that was never written, but no test ever drove a failing write stream through a provider's stopLogCapture — all prior tests either hit LogWriteStreamRegistry directly or used a good writable path. An adversarial mutation review proved this: swapping finalize for finalizeQuietly at the providers' success-path call sites restores the original defect and all 120 tests stay green. This change adds mutation-killing provider-level tests and documents two related behavior decisions without any source behavior change.

Changes

  • New provider-level failing-stream stop tests (Android + iOS), asserting success: false, an ENOENT-matching message, and zero live streams after stop — appended before the deliberately-last throwing-sink test, killing the finalize/finalizeQuietly mutation
  • Mutation-kill verification performed procedurally (mutation applied, confirmed new tests fail, reverted via git checkout, confirmed clean and green) — no committed artifact
  • Assessment item A: keep finalize's unconditional recorded-error rejection (no writableFinished guard) — documented via rationale comment; the contradicting state is unreachable in production because autoDestroy means every real error destroys the stream
  • Assessment item B: document the once-consumed recorded-error ordering invariant (quiet-then-loud) via code comment and memory update — no redesign, no test pinning the accepted hazard
  • docs/memory/device-node/log-capture.md updated with the new test surface and both Design Decisions

Summary by CodeRabbit

  • Bug Fixes

    • Log capture stops now report failures when the output stream cannot be opened.
    • Original stream errors, including ENOENT, are propagated even after a successful flush.
    • Failed stops clean up tracked capture entries reliably.
  • Tests

    • Added Android and iOS coverage for asynchronous log-stream opening failures.
    • Added verification for failure responses, error propagation, and cleanup behavior.
  • Documentation

    • Documented log finalization error handling and cleanup ordering.

Add mutation-verified provider-level tests pinning the finalize-vs-finalizeQuietly
stop contract from #168 (a failing write stream must report success: false, not
be swallowed) — the prior registry-level tests never exercised a failing stream
through a provider's stopLogCapture. Also documents two related behavior
decisions (keep-unconditional-rejection, once-consumed-recorded-error) in
logWriteStream.ts and docs/memory.
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@droid-ash, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 7 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b75f4652-b3f6-410f-9d72-16ac9b64df80

📥 Commits

Reviewing files that changed from the base of the PR and between 2a571a7 and 8e0cbcd.

📒 Files selected for processing (3)
  • fab/changes/260731-cjx8-provider-log-stop-test-coverage/.history.jsonl
  • fab/changes/260731-cjx8-provider-log-stop-test-coverage/.status.yaml
  • packages/device-node/src/device/logWriteStream.ts
📝 Walkthrough

Walkthrough

The change documents log-stream finalization error behavior and adds Android and iOS provider tests for asynchronous output-stream open failures. The tests verify ENOENT reporting, unsuccessful stop responses, error propagation, and registry cleanup.

Changes

Provider log-stop failure coverage

Layer / File(s) Summary
Test contract and acceptance criteria
fab/changes/260731-cjx8-provider-log-stop-test-coverage/*
Defines provider failure scenarios, deterministic synchronization, acceptance criteria, verification steps, and workflow status.
Finalization error semantics
packages/device-node/src/device/logWriteStream.ts, docs/memory/device-node/log-capture.md
Documents recorded-error propagation through finalize, error consumption during cleanup, and the required finalize before finalizeQuietly ordering.
Cross-platform provider failure tests
packages/device-node/src/device/test/logCaptureProviders.test.ts, docs/memory/device-node/log-capture.md
Adds Android and iOS tests for failed stream opens. The tests verify success: false, ENOENT, error propagation, and registry removal.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: arnoldlaishram

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the provider-level log-stop failure test coverage added by the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 260731-cjx8-provider-log-stop-test-coverage

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

@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: 2

🧹 Nitpick comments (1)
packages/device-node/src/device/test/logCaptureProviders.test.ts (1)

241-251: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share the provider factory between platform loops.

The new loop duplicates the createProvider factory from Lines 121-130. Extract one helper that accepts platform and FakeChildProcess, then use it in both loops. This prevents Android and iOS test setup from diverging.

🤖 Prompt for 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.

In `@packages/device-node/src/device/test/logCaptureProviders.test.ts` around
lines 241 - 251, Extract the duplicated createProvider factory into a shared
helper that accepts a platform and FakeChildProcess and returns the
corresponding AndroidLogcatProvider or IOSLogProvider. Replace the local factory
definitions in both platform loops with this helper, preserving the existing
execFileStub and spawnFn setup.
🤖 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 `@packages/device-node/src/device/logWriteStream.ts`:
- Around line 191-202: Serialize concurrent stop operations in LogCaptureManager
before awaiting either provider, using a per-capture single-flight guard or
claiming the capture in _stoppedTestCases before the provider call so only one
stop can reach finalization. Preserve the required loud-before-quiet behavior
and update the comments in packages/device-node/src/device/logWriteStream.ts
(lines 191-202) and docs/memory/device-node/log-capture.md (lines 331-350) to
describe the enforced serialization and resulting ownership semantics.
- Around line 136-140: The finalize flow in logWriteStream.ts can report success
before asynchronous close-time errors are recorded. Update the writableFinished
path in finalize to await the stream’s terminal close/error state before
evaluating entry.error, add a regression test covering an error emitted during
auto-destroy after writableFinished, and update
docs/memory/device-node/log-capture.md lines 303-321 to document that successful
stop waits for close-time errors.

---

Nitpick comments:
In `@packages/device-node/src/device/test/logCaptureProviders.test.ts`:
- Around line 241-251: Extract the duplicated createProvider factory into a
shared helper that accepts a platform and FakeChildProcess and returns the
corresponding AndroidLogcatProvider or IOSLogProvider. Replace the local factory
definitions in both platform loops with this helper, preserving the existing
execFileStub and spawnFn setup.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 01208b2a-49dc-4f21-8563-12e56bb5c55d

📥 Commits

Reviewing files that changed from the base of the PR and between 7fdebd0 and 2a571a7.

📒 Files selected for processing (7)
  • docs/memory/device-node/log-capture.md
  • fab/changes/260731-cjx8-provider-log-stop-test-coverage/.history.jsonl
  • fab/changes/260731-cjx8-provider-log-stop-test-coverage/.status.yaml
  • fab/changes/260731-cjx8-provider-log-stop-test-coverage/intake.md
  • fab/changes/260731-cjx8-provider-log-stop-test-coverage/plan.md
  • packages/device-node/src/device/logWriteStream.ts
  • packages/device-node/src/device/test/logCaptureProviders.test.ts

Comment thread packages/device-node/src/device/logWriteStream.ts Outdated
Comment thread packages/device-node/src/device/logWriteStream.ts Outdated
droid-ash and others added 2 commits July 31, 2026 11:27
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review should-fixes from the cjx8 pipeline: the finalize doc claimed the
flush-succeeded-with-recorded-error state is unreachable with real errors,
which holds only error-then-flush — auto-destroy's close(2) after finish
can record an EIO with writableFinished already true, exactly what a
writableFinished guard would drop. And finalizeQuietly's ordering note
overstated _stoppedTestCases: it prevents only a sequential second stop;
overlapping stop/abort is a check-then-act race (accepted hazard, recorded
in docs/memory/device-node/log-capture.md).

Comment-only; 122/122 device-node tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@droid-ash
droid-ash marked this pull request as ready for review July 31, 2026 11:59
@droid-ash
droid-ash merged commit e8f9060 into main Jul 31, 2026
2 checks passed
droid-ash added a commit that referenced this pull request Aug 1, 2026
* fix: Log Finalize Awaits Terminal Stream State

LogWriteStreamRegistry.finalize decided success/failure by reading
entry.error at whatever moment its finally completed, instead of after
the stream's terminal close state. That produced two wrong outcomes: a
fully-flushed log with a stale non-destroying recorded error rejected
(contradicting the file's own contract), and a close-time error
arriving after the check silently missed. finalize now awaits the
stream's terminal 'close' state before deciding, and the success
predicate is state-based: resolve iff writableFinished &&
stream.errored === null (warn-and-resolve over a stale recorded
error), else reject with entry.error ?? stream.errored.

Supersedes the PR #173 decision to document rather than fix the
unconditional recorded-error rejection, reopened on two independent
reviewers converging (operator-side should-fix; CodeRabbit MAJOR /
data integrity).

* Update ship status and record PR URL

* fix: address review feedback from @coderabbitai[bot]

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Update review-pr status

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: droid-ash <droid-ash@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant