# rusty-pdfgrep — CI Runtime Baseline
**Status**: v0.2.0 baseline projection (E011 Phase 10 T115).
**Authority**:
- Spec 00011 SC-010 — wall-clock for the longest-path job MUST stay
under 25 minutes (HARD gate per Clarifications Q1).
- HINT-010 of spec 00011 — remediation strategies if the gate is
approached.
## Method
rusty-pdfgrep is a tightly-coupled-capability port per spec 00011 §Scope
Edge Cases. The CI matrix scales with the leaf count; since zero leaves
are carved, Tier 4 (`check-leaf-<leaf>`) is empty, leaving a
smaller-than-average matrix vs the reference rusty-figlet port (which has
5 v0.2.0 leaves and 5 corresponding Tier 4 jobs). The matrix shape matches
the rusty-sponge v0.2.0, rusty-vipe v0.2.0, rusty-pee v0.2.0, rusty-pwgen
v0.2.0, rusty-detox v0.2.0, and rusty-pv v0.2.0 baselines (also zero-leaf
ports; rusty-detox additionally retains its v0.1.x `inline-detox`
feature under Tier 4, but rusty-pdfgrep has no such pre-existing leaf
and its Tier 4 is fully empty).
The full v0.2.0 CI matrix for rusty-pdfgrep has these jobs:
| Pre-gates | fmt, clippy, audit, msrv | Linux | 4 | Identical to v0.1.x. |
| Tier 1 | test-default | linux x86_64 + aarch64 + macos x86_64 + macos aarch64 + windows x86_64 | 5 | Full DDR-003 cross-compile matrix (preserves v0.1.x coverage). The Linux x86_64 entry also runs the SC-002 default-install smoke (drives `--help`, `--version`, and the completions subcommand). |
| Tier 2 | test-no-default | Linux x86_64 | 1 | Bare library + SC-001 dep-tree audit. |
| Tier 3 | test-pdfgrep-classic, test-pdfgrep-minimal | Linux x86_64 | 2 | Preset bundle install + SC-003 size check. |
| Tier 3 (SC-004) | test-keeplist | Linux x86_64 | 1 | Keep-list workaround install smoke. |
| Tier 4 | (none) | — | 0 | **Zero leaves carved — Tier 4 intentionally empty per docs/feature-layout.md.** |
| Tier 5 | lint-convention | Linux x86_64 | 1 | Vendored `tools/feature-lint/run.sh` invocation. |
| Optional | convention-lint-self-test | Linux x86_64 | 1 | `workflow_dispatch` only — does NOT run on PR/main. |
| Legacy | library-no-default-features | Linux x86_64 | 1 | Retained v0.1.x parity gate. |
| Publish | publish-dry-run | Linux x86_64 | 1 | Runs after every tier above; cargo publish --dry-run. |
**Total scheduled jobs per PR/main push**: 4 (pre-gates) + 5 (Tier 1) + 1
(Tier 2) + 2 (Tier 3) + 1 (SC-004) + 1 (Tier 5) + 1 (legacy) + 1
(publish-dry-run) = **16 jobs**.
The `convention-lint-self-test` job runs only on `workflow_dispatch`
and is excluded from the steady-state PR/main load.
## Wall-clock projection
The longest single-job wall-clock is expected to be the `test-default`
matrix entry running `aarch64-unknown-linux-gnu` under `cross`
(cross-compile via QEMU adds ~30-50% on cargo-build wall vs native), or
the Windows x86_64 entry (Windows runners are typically the slowest in
GitHub-hosted matrix). rusty-pdfgrep's heaviest cargo-build path is the
all-features build, which links `lopdf` (PDF parser), `regex` +
`fancy-regex` (engines), and the full CLI surface (`clap`,
`clap_complete`, `anyhow`, `termcolor`, `anstyle`, `walkdir`,
`globset`). The library API tests cover the engine compiler, the
page-iterator state machine, and the `PdfGrep` / `PdfGrepBuilder`
send-safety assertions; the binary integration suite drives the
cli/strict argv pre-scanners and the completions drift gate.
Per the v0.1.0 baseline (single matrix entry per target, no Cargo
Features Convention overlays):
| linux x86_64 (native) | ~3 min |
| linux aarch64 (cross via QEMU) | ~7-9 min |
| macos x86_64 | ~3 min |
| macos aarch64 | ~3 min |
| windows x86_64 | ~5-7 min |
The v0.2.0 matrix adds 5 Tier 2/3/SC-004/5 Linux x86_64 jobs that all
run in parallel with Tier 1. Each is bounded by a single Linux
`cargo build/test --features <bundle>` cycle (~2-3 min each on a warm
rust-cache). Net effect on the longest-path wall-clock: negligible
(the critical path remains the slowest Tier 1 cross-compile).
**Projected longest-path wall-clock for v0.2.0**: ~9-11 minutes
(aarch64-linux cross via QEMU; lopdf compile is the dominant cost),
well under the 25-minute HARD gate per SC-010.
## Empirical local capture (cargo check baseline)
A local `cargo check` matrix run was performed on Windows during T115
validation to confirm Cargo.lock regeneration and per-feature
compilability. Sanitized output (all on a warm dep-graph after the
initial cold compile):
| `cargo check --all-features` (warm) | ~0.3 s |
| `cargo check --no-default-features` | ~0.2 s |
| `cargo check --no-default-features --features cli` | ~0.3 s |
| `cargo check --no-default-features --features pdfgrep-classic` | ~0.3 s |
| `cargo check --no-default-features --features pdfgrep-minimal` | ~0.3 s |
| `cargo check --no-default-features --features full` | ~0.3 s |
The cold compile of `--no-default-features` populates the
`thiserror` + `regex` + `fancy-regex` + `lopdf` dep graph and is the
slowest single step (~5-6 s locally on a warm registry).
These are local-machine checks (toolchain pinned via
`rust-toolchain.toml` at 1.85) intended only as a quick sanity check
that the per-feature graph compiles. The CI matrix uses
`cargo build/test` on cold rust-caches per target and will be slower;
the empirical CI capture (3 full runs, median of the slowest matrix
entry) is deferred until the v0.2.0 PR opens its first CI run.
## Empirical capture (deferred)
Per HINT-010 the empirical capture (3 full CI runs, median of the
slowest matrix entry) is deferred until the v0.2.0 PR opens its first
CI run. The projection above is well under the 25-minute gate; if the
first 3 CI runs show otherwise, this document is updated with the
empirical numbers and remediation steps per HINT-010(a/b/c).
## Remediation strategies (HINT-010, not yet needed)
If the empirical wall-clock approaches the 25-minute gate:
1. **Cache aggressively** — the existing `Swatinem/rust-cache@v2`
keyed by target already does this; verify cache hit-rate.
2. **Drop `cross` for aarch64-linux** — use `actions/setup-qemu` +
native arm runners if available, or accept the cross-compile-only
(no test) for that target.
3. **Move per-preset SC-003 install + size check to a single
matrix-driven job** — currently each Tier 3 job redundantly
compiles the binary. A single matrix-strategy job could
parallelize across preset bundles with one shared rust-cache.
4. **Trim the `lopdf` cold-compile path** — the PDF parser dominates
the cold-build wall-clock. Cache the registry / dep graph
aggressively; consider a workspace-level `cargo nextest`
parallelization if a future iteration adds significant test
surface.
None of these are needed at v0.2.0; capturing here for future
maintenance.