Skip to content

ci: park perf-nightly to dispatch and stop the coverage-gate cascade double-red (#1781 A3, A5) - #1822

Merged
thymikee merged 1 commit into
mainfrom
ci/1781-a3-park-perf-nightly-a5-cascade
Aug 18, 2026
Merged

ci: park perf-nightly to dispatch and stop the coverage-gate cascade double-red (#1781 A3, A5)#1822
thymikee merged 1 commit into
mainfrom
ci/1781-a3-park-perf-nightly-a5-cascade

Conversation

@thymikee

@thymikee thymikee commented Aug 18, 2026

Copy link
Copy Markdown
Member

What / why

Two small, decided CI changes from #1781.

A3 — park perf-nightly.yml to dispatch-only

perf-nightly.yml writes a JSON/markdown perf report and compares nothing (scripts/perf/report.ts just serializes the run; grepping scripts/perf + the workflow for baseline|threshold|regress|compare|delta finds zero implementation, only a comment stating the intent). It therefore structurally cannot report a regression — a run only turns red on a harness crash.

Evidence (60-day run history + artifact diff):

  • 38/38 green since 2026-07-12; "success" only ever meant "didn't crash."
  • iOS wall-clock medians swing wildly night-to-night at n=5, warmup=1 on a shared macOS runner: type +122%, snapshot (deep) +74%, open (relaunch→root) +60%, boot device +39%. A fixed-threshold comparator would mostly print noise without multi-night smoothing.
  • No doc, README, or issue consumes the report (grep -rniE "perf-nightly|scripts/perf" docs/ CONTEXT.md AGENTS.md README.md → no hits; gh issue list --search "perf-nightly" → only Prune the test lanes that don't pay for themselves, and add the checks we're missing #1781 itself).
  • Cost: iOS job ~22min median on a macOS runner + Android ~9min, nightly. This is a public repo, so Actions minutes are free; the defensible cost is runner occupancy, not billing — ~22 min/night of a macOS runner held for a report nobody reads.

Implemented exactly the #1781 A1 parking pattern (replays-manual.yml): dropped the schedule: trigger, kept workflow_dispatch, added a short header comment naming the parking reason and the un-park condition. pnpm perf and scripts/perf are untouched — still runnable on demand.

scripts/gate/declarations.ts unchanged. perf-nightly declares no pnpm gate <name> check of its own — pnpm perf isn't a registered gate, and the only gate: reference in the file (swift-runner-ios, used to build the shared XCTest runner) is already declared and owned by other lanes (ios.yml, xctest-nightly.yml, conformance-differential.yml). pnpm check:gate-manifest reports the same 47 checks / 33 lanes before and after this change, so nothing needed a MANUAL_ONLY_OWNERS entry.

Docs: the only perf-nightly mention outside the workflow itself is docs/agents/contract-projection-output-economy-spike.md:159, a dated investigation closeout describing a past one-off dispatch attempt — not living documentation asserting perf-nightly runs on a schedule. Left as-is; rewriting a historical log to match a later architecture change would misrepresent what happened at the time.

A5 — stop the changed-line coverage gate's cascade double-red

In ci.yml's coverage job, "Enforce changed-line coverage gate" ran if: always() && github.event_name == 'pull_request'. When the preceding "Run coverage" step (unit-ci, the vitest-coverage run) failed, coverage/lcov.info was never written, and the Enforce step then failed too with "no lcov report" — a second, redundant red from the same job, not a coverage verdict.

Retrospective (60-day window, 3259 CI runs): 17 runs had the Enforce step fail. 16/17 were this lcov-missing cascade (Run coverage already failed/crashed). Only 1/17 was a genuine, isolated block: run 32104571856 / PR #1804 ("feat(ai-sdk): add agent-device/ai-sdk tool set"), 6.90% changed-line coverage on a large new file — correctly caught, PR was fixed and merged.

Fix: gave "Run coverage" an explicit id: run-coverage and changed the Enforce step's condition to steps.run-coverage.outcome == 'success' && github.event_name == 'pull_request'. The checker script (scripts/coverage-changed/run.ts) is unchanged.

Four lines — both lanes, as they stand after this change

perf-nightly (parked, dispatch-only):

  • Catches: nothing automatically — no scheduled run, no comparison logic. Manual dispatch remains available for on-demand perf investigation.
  • Evidence: 38/38 scheduled runs green since 2026-07-12 while iOS per-metric medians swung up to +122% night-to-night; no issue or doc ever consumed a report.
  • Cost: frees ~22 min/night of macOS runner occupancy (Actions minutes are free on this public repo, so the saving is occupancy/capacity, not billing). pnpm perf / scripts/perf still cost nothing extra when run on demand.
  • Kill-criterion: un-park when a comparison step with multi-night smoothing exists and has an owner reading it, or when a perf arc needs nightly data.

changed-line coverage gate (still gating, cascade removed):

  • Catches: genuinely undertested new files/hunks that the repo-wide 78-80% average (vitest.config.ts) would hide — 1 confirmed instance in 60 days.
  • Evidence: run 32104571856 / PR feat(ai-sdk): add agent-device/ai-sdk tool set and document the MCP zero-code path #1804, 6.90% changed-line coverage, real block, fixed and merged. 0 waivers granted (the coverage-waiver label doesn't exist in the repo).
  • Cost: ~1s/PR (reuses the job's own lcov output; no extra vitest run).
  • Kill-criterion: n/a — low-but-nonzero legitimate catch rate (1/3259 runs), now measured without the 16 cascade false-reds diluting the signal.

Test plan

  • pnpm format:check, pnpm lint, pnpm typecheck — clean
  • pnpm check:gate-manifest47 checks wired across 33 lanes, manual-only: replay-android, replay-ios, replay-ios-device (unchanged before/after)
  • pnpm check:gate-manifest:test — 37/37 passing
  • YAML syntax validated (yaml.safe_load) for both changed workflow files
  • CI watch on this PR — confirm the coverage job's Enforce step behavior is unaffected on the (expected) green path

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.30 MB 2.30 MB 0 B
JS gzip 756.4 kB 756.4 kB 0 B
npm tarball 878.0 kB 878.0 kB 0 B
npm unpacked 3.07 MB 3.07 MB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.5 ms 26.9 ms +0.4 ms
CLI --help 65.6 ms 66.3 ms +0.7 ms

Top changed chunks: no changes in the largest emitted chunks.

@thymikee

Copy link
Copy Markdown
Member Author

The workflow change is semantically sound, but two readiness items remain. First, the cascade fix has only green-path evidence: per the repo’s planted-red rule, temporarily force Run coverage to fail on this head (or provide an equivalent workflow-level regression witness) and show Enforce changed-line coverage gate is SKIPPED, then revert. Second, replace the ≈$55/month claim: Actions minutes are free for this public repo; the defensible saving is roughly 22 minutes/night of macOS runner occupancy. Current CI is otherwise green.

@thymikee
thymikee force-pushed the ci/1781-a3-park-perf-nightly-a5-cascade branch from a435241 to f9c62b9 Compare August 18, 2026 14:01
@thymikee

Copy link
Copy Markdown
Member Author

Both items addressed.

Planted-red witness for the cascade fix — pushed a temporary commit a4352419a that forced Run coverage to fail on this head, then restored the clean head f9c62b9e1. Run https://github.com/callstack/agent-device/actions/runs/32145339142, Coverage job step conclusions: Run coverage → failure, Enforce changed-line coverage gate → skipped (previously it would have double-reported as its own red: "no lcov report"). Green-path contrast: run 32137057664 on the same clean head, Coverage green with the Enforce step executed.

Cost claim — PR body rewritten: no dollar figures; the defensible saving is ~22 min/night of macOS runner occupancy (Actions minutes are free on this public repo).

Current head is the clean f9c62b9e1; the only red lane on the latest run is Layering Guard, which is red on main itself (#1825 × #1779 interaction, being fixed on main).

@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed #1822: the prior evidence/body blockers are resolved. Planted run 32145339142 shows Run coverage failing while Enforce changed-line coverage gate is skipped; the clean head executes enforcement, and the body now correctly describes ~22 minutes/night of macOS occupancy with no billing savings. The workflow change is code-clean. It is not merge-ready only because Layering is red on the stale base (same R9/R10 failures on base main); rebase onto current main and rerun before applying ready-for-human.

…double-red (#1781 A3, A5)

A3: perf-nightly writes a report and compares nothing, so it structurally
cannot catch a regression. iOS wall-clock medians swing up to +122%
night-to-night at n=5 (a comparator would print noise), no doc/issue reads
the report, and the iOS job holds a macOS runner ~22min nightly. Parked to
workflow_dispatch following the #1781 A1 pattern (replays-manual.yml); it
declares no gate-manifest check, so no declarations.ts change is needed.
`pnpm perf` / scripts/perf are untouched.

A5: the "Enforce changed-line coverage gate" step ran `if: always()`, so
when the preceding "Run coverage" step failed, lcov.info was never written
and this step failed too with "no lcov report" -- a cascade double-red, not
a coverage verdict. 16 of the last 17 red instances (60d) were this cascade;
the step now runs only when Run coverage succeeded.
@thymikee
thymikee force-pushed the ci/1781-a3-park-perf-nightly-a5-cascade branch from f9c62b9 to 1c2466d Compare August 18, 2026 14:54
@thymikee

Copy link
Copy Markdown
Member Author

Rebased onto main (4bba40424, includes the #1838 layering fix); head 1c2466dde, CI re-running.

@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed exact 1c2466d: clean and merge-ready. The rebase resolves the inherited Layering failures without changing the two-workflow scope. Planted run 32145339142 proves coverage failure skips enforcement; the clean head executes enforcement successfully. The public-repo runner-occupancy claim remains accurate, and all exact-head gates and device smoke lanes are green.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Aug 18, 2026
@thymikee
thymikee merged commit 9d6154e into main Aug 18, 2026
28 checks passed
@thymikee
thymikee deleted the ci/1781-a3-park-perf-nightly-a5-cascade branch August 18, 2026 15:47
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-18 15:47 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant