feat(ci): capture crash evidence as artifacts when a run wedges (T-436)

Closes the observability loop: the log + breadcrumb + watchdog files are now
collected by CI so a wedged run leaves downloadable evidence instead of
nothing.

- logDirectory(): CLIDE_LOG_DIR overrides the per-platform default, so CI can
  point the logs at an uploadable workspace dir (and tests at a temp dir).
  Now takes an injectable env map; tested.
- test_app.dart: when CLIDE_LOG_DIR is set, the testmode harness tees its
  logger to a FileLogSink + spawns the watchdog (off by default — normal
  run-testmode keeps the stderr-only path, no isolate). _say breadcrumbs each
  test into the file.
- conpty_orphan_probe.dart: with CLIDE_LOG_DIR set it passes a verbose PtyLog,
  so when soak-conpty-kill.ps1 force-kills the parent, the reader/waiter
  isolates' LAST crumb is fsynced to disk — naming what the wedged isolate was
  doing at the instant of death.
- bundle-smoke job: runs the real release app with CLIDE_LOG=debug +
  CLIDE_LOG_DIR, uploads clide-logs (watchdog heartbeat/sample + FileLogSink)
  in an always() step.
- windows-soak kill-probe job: sets CLIDE_LOG_DIR, uploads the FFI crumbs.

Coverage gate 95.08%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 10:58:48 +02:00
co-authored by Claude Opus 4.8
parent ee8c9dcc11
commit f40be4f758
9 changed files with 87 additions and 9 deletions
+14
View File
@@ -80,6 +80,13 @@ jobs:
- run: flutter pub get
- name: ConPTY abrupt-death orphan probe
shell: pwsh
# CLIDE_LOG_DIR makes the probe emit FFI breadcrumbs (T-436): when a
# parent is force-killed mid-life, its reader/waiter isolates' last
# crumb ("ReadFile enter" / "WaitForSingleObject enter") is fsynced to
# clide-pty.crumbs.log and uploaded below — naming what the wedged
# isolate was doing at the instant of death.
env:
CLIDE_LOG_DIR: ${{ github.workspace }}/kill-crumbs
run: |
$iters = "${{ github.event.inputs.kill_iterations }}"
if (-not $iters) { $iters = "15" }
@@ -99,3 +106,10 @@ jobs:
name: conpty-kill-probe
path: kill-out
if-no-files-found: warn
- name: Upload FFI breadcrumbs (last act of each killed reader/waiter)
if: always()
uses: actions/upload-artifact@v4
with:
name: conpty-kill-crumbs
path: ${{ github.workspace }}/kill-crumbs
if-no-files-found: ignore