Repository navigation
ci: CI Cost Guards and Carried-Forward Defects - #168
Merged
Merged
Conversation
📝 WalkthroughWalkthroughThe PR adds path-filtered, timeout-bounded, concurrency-controlled native driver workflows and updates their CI documentation. It also records write-stream errors for later finalization failure, hardens quiet logging, expands regression tests, and adds Fab planning and execution records. ChangesCI and device reliability
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant GitHubEvents
participant DriversWorkflow
participant AndroidJob
participant IOSJob
GitHubEvents->>DriversWorkflow: Trigger on configured driver paths
DriversWorkflow->>AndroidJob: Run with 15-minute timeout
DriversWorkflow->>IOSJob: Run with 25-minute timeout
sequenceDiagram
participant TestOrCaller
participant LogWriteStreamRegistry
participant WriteStream
TestOrCaller->>LogWriteStreamRegistry: open(outputFilePath)
LogWriteStreamRegistry->>WriteStream: Attach error listener
WriteStream-->>LogWriteStreamRegistry: Record first error
TestOrCaller->>LogWriteStreamRegistry: finalize()
LogWriteStreamRegistry-->>TestOrCaller: Reject after cleanup
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@fab/changes/260730-eyvt-ci-cost-guards-carried-defects/plan.md`:
- Around line 142-157: Expand the registry regression-test scope from four to
six cases, including the two supplemental first-error cases, and keep all cases
in the existing logCaptureProviders.test.ts suite. Update
fab/changes/260730-eyvt-ci-cost-guards-carried-defects/plan.md lines 142-157 to
enumerate all six, line 224 to make the NICE-TO-HAVE status consistent with
required first-error coverage, and lines 245-254 to reflect the complete scope
in A-006/A-010. Update
fab/changes/260730-eyvt-ci-cost-guards-carried-defects/intake.md lines 336-346
to list all six cases and lines 431-434 to change the impact summary from four
cases to six.
🪄 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: f13c4ba0-aaf8-4327-b4f3-9c55c7378794
📒 Files selected for processing (14)
.github/workflows/drivers.ymldocs/memory/ci/index.mddocs/memory/ci/pr-quality-gate.mddocs/memory/cli/session-runner.mddocs/memory/device-node/index.mddocs/memory/device-node/log-capture.mddocs/memory/drivers/grpc-contract.mddocs/memory/index.mdfab/changes/260730-eyvt-ci-cost-guards-carried-defects/.history.jsonlfab/changes/260730-eyvt-ci-cost-guards-carried-defects/.status.yamlfab/changes/260730-eyvt-ci-cost-guards-carried-defects/intake.mdfab/changes/260730-eyvt-ci-cost-guards-carried-defects/plan.mdpackages/device-node/src/device/logWriteStream.tspackages/device-node/src/device/test/logCaptureProviders.test.ts
droid-ash
marked this pull request as ready for review
July 31, 2026 01:48
This was referenced Jul 31, 2026
droid-ash
added a commit
that referenced
this pull request
Jul 31, 2026
* test: Provider-Level Log-Stop Failure Test Coverage 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. * Update ship status and record PR URL * Update review-pr status Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: hedge two comment-accuracy overclaims in logWriteStream 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> --------- Co-authored-by: droid-ash <droid-ash@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
droid-ash
added a commit
that referenced
this pull request
Jul 31, 2026
* ci: Harden Drivers CI Workflow and Correct False Claims Add workflow_dispatch and a weekly schedule to drivers.yml for toolchain-rotation detection, add an SPM global-cache step to the ios job, and correct three rationale-comment claims falsified or made ambiguous by PRs #168-#172: the stale ios worst-case timing, the ambiguous native-file count, and the proto/** filter justification (now scoped to Android only, since a green ios job does not prove committed Swift bindings are in sync with proto). * Update ship status and record PR URL * 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>
droid-ash
added a commit
that referenced
this pull request
Jul 31, 2026
* docs: Correct False and Stale Claims Found in PR #168-175 Review Truth pass fixing fabricated ratios, rotted line-number citations, and false used-by attributions across comments and memory docs. No runtime changes — only comment/doc lines touched in .ts/.kt files. * Update ship status and record PR URL * fix: address review feedback from @coderabbitai[bot] Correct the fps-clamp rationale in grpc-contract.md: below 1 the failure is an invalid divisor (integer division-by-zero / negative-to-UInt64 traps in GrpcDriverServer.swift, unbounded or negative intervals on the floating-point paths), and the 60 upper bound is a chosen load cap, not a measured ceiling. 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Meta
eyvtgenerated by fab-kit v2.16.8
Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Summary
The
iosdriver-CI job is the most expensive thing in this repo's CI:macos-latestbills at 10× the Linux rate,drivers.ymlruns on every PR regardless of relevance, and superseded pushes are paid for in full (PR #167's three pushes cost ~200 billable minutes for one informative verdict). This change adds two cost guards to.github/workflows/drivers.yml— job-leveltimeout-minutesand apathsfilter plus PR-scopedconcurrencyblock — and separately fixes a carried-forward defect inpackages/device-node's log write-stream registry, where a missing persistenterrorlistener could either crash the CLI mid-run or silently report a successful stop over a log file that was never written.Changes
timeout-minuteson bothdrivers.ymljobs —15(android) /25(ios), set at job level (not step level, so checkout and toolchain setup are inside the bound). No workflow in the repo previously set one, so every job sat on GitHub's 360-minute default; at the 10×macos-latestrate a wedgedxcodebuildcould bill ~3,600 minutes. Both values are ≥2× the worst of five observed runs (android 2m36s, ios 9m20s worst-case), withiosdeliberately the tighter relative bound because its minutes cost 10×. Worst-caseiosexposure drops 3,600 → 250 billable minutes.A
paths:filter on both triggers, and a PR-scopedconcurrencyblock. The filter —drivers/**,proto/**, bothscripts/build-drivers-*.sh, and the workflow file itself — is byte-identical acrosspull_requestandpush.proto/**is load-bearing:drivers/android/app/build.gradle.kts:104adds the repo-rootprotodir as a protobuf source dir, so a proto-only edit can break the Android Kotlin compile with no file underdrivers/changing. The concurrency group isdrivers-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}withcancel-in-progressgated topull_request: superseded PR pushes cancel in flight, whilemainruns stay run-id-scoped so one is never queued behind or evicted by another — a baregroup: ${{ github.ref }}would reintroduce the pending-eviction footgun this repo already documents forci.yml. This is safe here specifically because ruleset14531661requires onlyci.yml'stestcontext, so no merge gate consultsdrivers.yml.ci.ymlitself is deliberately untouched — its no-concurrencyrule stays correct for the required check.logWriteStream.ts: a persistenterrorlistener inLogWriteStreamRegistry.open().open()previously returned a barefs.createWriteStream, andpipe()does not forward destination errors to the source, so the firstEACCES/ENOSPCsurfaced as an unhandled'error'event — which Node throws, killing the CLI mid-run. The defect had a second face:_endAndFlushearly-returns on an already-destroyed stream, and an errored stream auto-destroys, so an error arriving afterfinalizeran meant the stop resolved as success over a log file that was never actually written.open()now attaches a persistent listener that records the first error on a per-path entry, andfinalizere-throws that recorded error after its existingtry/finally(so an in-flight drain or flush rejection keeps precedence and is never masked). Both that listener'sLogger.ecall andfinalizeQuietly's are wrapped intry/catch, becauseLogger._emit's sink loop is itself unguarded and the CLI's runner-log sink is a barefs.appendFileSync— a listener of last resort must not throw. Six new registry test cases were added, all verified to fail against the pre-fix code.Scope note. A fourth item from the original request — adding
.github/to the/git-prskill's expected write areas — was deliberately dropped and is tracked separately as backlogax7i, to be fixed upstream in fab-kit..claude/skills/git-pr/SKILL.mdis gitignored and kit-deployed, so any edit here would be outside version control, invisible in this diff, and lost on the next fab-kit upgrade. Nothing under.claude/or~/.fab-kit/is touched by this PR.Verification.
npm run build,npm run typecheck,npm run lintall clean (lint has 42 pre-existing warnings, none in touched files).packages/device-node120/120.drivers.ymlparses; bothpathslists are byte-identical; bothconcurrencyexpressions verified forpull_requestandpush.pathsfilter's exclusion behavior is not proven by this PR — this PR edits.github/workflows/drivers.yml, which is itself in the filter, so thedriversworkflow will fire on it. That is the filter working, not a failure. Theconcurrencyblock is only exercised by two pushes in quick succession, so it ships source-verified unless this PR happens to receive them.Summary by CodeRabbit
Bug Fixes
CI Improvements
Documentation