Skip to content

Waivers: accept known changes so CI gates still pass (#425) - #480

Open
Cimos wants to merge 1 commit into
mainfrom
cimos-diff-waivers
Open

Cimos wants to merge 1 commit into
mainfrom
cimos-diff-waivers

Conversation

@Cimos

@Cimos Cimos commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Fixes #425 (part of #418).

What

etchy old/ new/ --waivers waivers.toml accepts known changes, such as a bumped date code or revision text, so --fail-on-area, --fail-on-regions and the any-change exit code still pass.

[[waiver]]
layer = "top-silk"
box = [10.0, 5.0, 30.0, 9.0]   # x_min, y_min, x_max, y_max, board mm
reason = "date code bumped each revision"
  • Core (etchy-core/src/waiver.rs, pure): Waiver::new validates the layer name, box and reason. apply_waivers(&BoardDiff, &[Waiver]) -> WaiverReport classifies every changed shape, including sub-floor slivers, so waived and unwaived areas add up exactly. Areas are summed as exact twice-area integers. The report renders as text, Markdown and HTML, and its warnings() covers stale waivers and partial overlaps.
  • CLI: adds --waivers FILE and --fail-on-stale-waivers (which requires --waivers). TOML parsing uses the toml crate (MIT/Apache, already in Cargo.lock) with deny_unknown_fields.
  • Outputs: the terminal summary, JSON (top-level waivers object), Markdown (### Waivers section, so the Action PR comment gets it too) and HTML all list each waiver's region count, area, reason and status. They also list the waived regions and the regions that partially overlap a waiver without being waived. The raw diff (layers, totals, overlays) is unchanged, so waiving never hides a change.

Design decisions (user unavailable — please check)

  1. Explicit flag only, no auto-discovery of .etchy.toml. A waiver file that is picked up silently could quietly disarm a gate. Whenever a file is used, etchy prints etchy: using N waiver(s) from PATH.
  2. Units: mm in the board's own absolute coordinates, the same numbers etchy prints as a region's bbox. Coordinates beyond ±1000 mm are rejected as a likely unit mix-up.
  3. Containment uses the region's bounding box, edges inclusive. A region is waived only if its bbox lies entirely inside a box. A partial overlap is not waived: it counts toward the gate and is named in a warning and in every output. A region that spans two adjacent boxes is not waived either. If boxes overlap, the first matching waiver in file order claims the region.
  4. Stale: a waiver that waives nothing is stale. That includes a waiver that only partially overlaps changes, and such a waiver is reported both ways. Stale waivers are a warning by default; --fail-on-stale-waivers makes them exit 1.
  5. Fail loud (exit 2) on an unknown layer name (valid names are what etchy prints: top-copper, inner-copperN, drill-pth, …), an unknown key, a box that isn't 4 finite values or is inverted or zero-width, a missing or blank reason, invalid TOML, a file with no [[waiver]] entries, or --waivers with PDF inputs.
  6. Gates sum exact unwaived nm² per layer, so a fully waived layer contributes exactly 0. Drill-table counts don't drive the exit code today, so there is no drill gating to change.
  7. No fingerprint waivers. A geometry hash breaks under any re-export or nudge and is hard to review, so the boxes are the robust option. I left fingerprints out.
  8. Action: action.yml doesn't expose the gate thresholds or extra flags yet, so it doesn't get a waivers input here. Its comment renders from --format md, so once a flag passthrough exists it will show waivers with no further work.

Tests

  • 11 core unit tests: containment, inclusive edges, partial overlap, spanning two boxes, stale on another layer, exact mixed areas, slivers, first wins, inner-copper names, malformed boxes and reasons, and escaping of reasons in Markdown and HTML.
  • CLI unit tests for parse_waivers (integer boxes, unknown keys and tables, bad layer, 3-value box, blank and missing reason, empty file).
  • CLI integration tests:
    • A fully waived diff exits 0, and the summary, JSON, Markdown and HTML all list the waived region.
    • A partial overlap exits 1 and is named.
    • Stale waivers are reported, and --fail-on-stale-waivers exits 1.
    • Bad files and a missing file exit 2.
  • cargo fmt --check, cargo clippy --workspace --exclude etchy-gui --all-targets -D warnings, cargo test --workspace --exclude etchy-gui and cargo deny check all pass.

Docs: README, site/docs.html (flags and a Waivers section), docs/REQUIREMENTS.md (new CLI-14, referencing TRUST-3) and CHANGELOG [Unreleased].

Add `--waivers FILE` (TOML) with per-layer mm boxes and a required reason.
Only a changed region wholly inside a box is waived; partial overlaps stay
unwaived and are reported. Gates count only unwaived changes; summary,
JSON, Markdown and HTML list every waived region with count, area and
reason (TRUST-3). Stale waivers warn; --fail-on-stale-waivers exits 1.
A malformed file, unknown key or unknown layer exits 2.

Fixes #425

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 12:08

Copilot AI 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.

🟡 Changes recommended

The review found an issue that should be addressed before approval.

3 open issues
What changed in this PR

Adds explicit, box-based waivers for known PCB changes, implementing #425 within the feature expansion tracked by #418. CLI gates count only unwaived changes while retaining the complete raw diff.

Changes:

  • Adds core waiver validation, geometry classification, and reporting for matched, stale, and partially overlapping waivers.
  • Integrates TOML waiver files and stale-waiver enforcement into CLI gates and report outputs.
  • Adds unit/integration coverage and documents the waiver workflow.
File Description
site/​docs.html Updated as part of this pull request.
README.md Updated as part of this pull request.
docs/​REQUIREMENTS.md Updated as part of this pull request.
crates/​etchy-core/​src/​waiver.rs Updated as part of this pull request.
crates/​etchy-core/​src/​report.rs Updated as part of this pull request.
crates/​etchy-core/​src/​lib.rs Updated as part of this pull request.
crates/​etchy-core/​src/​export.rs Updated as part of this pull request.
crates/​etchy-core/​src/​diff.rs Updated as part of this pull request.
crates/​etchy-cli/​tests/​cli.rs Updated as part of this pull request.
crates/​etchy-cli/​src/​main.rs Updated as part of this pull request.
crates/​etchy-cli/​Cargo.toml Updated as part of this pull request.
CHANGELOG.md Updated as part of this pull request.
Cargo.lock Updated as part of this pull request.

Review effort: Balanced

pub layer: String,
/// `[x_min, y_min, x_max, y_max]` in mm, in the board's own coordinates
/// (the same numbers etchy prints as a region's bbox).
pub box_mm: [f64; 4],
Comment on lines +326 to +327
let unwaived_nm2 = if any_waived {
unwaived_2x / 2
m.matched_area_mm2,
Self::status(m),
m.reason
);

This branch has not been deployed

No deployments
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.

Waivers: accept known changes so CI gates still pass

2 participants