sheets-diff 2.5.0

Structured diff engine for Microsoft Excel .xlsx workbooks
Documentation
# RFC-029 — GUI Integration View Adapters

**Status.** Implemented (2.0.0–2.2.3) — verified 2026-08-16 against the implementation.
**Target:** v2.1 candidate  
**Related:** RFC-003, RFC-009, RFC-010, RFC-011, RFC-012, RFC-014

## 1. Summary

Add optional adapter types that help GUI applications present `WorkbookDiff`
without exposing GUI-framework-specific dependencies. The core result remains
framework-neutral; adapters provide navigation, grouping, filtering, and summary
views.

## 2. Motivation

Downstream GUI tools need common presentation structures:

- workbook summary;
- sheet tree;
- list of changed cells;
- navigation to next/previous change;
- filtering by change kind;
- grouped view by sheet, row, or address;
- stable anchors for virtualized tables.

Every app can build these independently, but a lightweight adapter layer reduces
integration friction and encourages consistent semantics.

## 3. Goals

- Provide GUI-friendly, framework-neutral view models.
- Keep the core model unchanged.
- Avoid dependencies on Dioxus, Iced, egui, Tauri, or web frameworks.
- Support virtualized table rendering through stable row IDs and anchors.

## 4. Non-goals

- Building a GUI inside `sheets-diff`.
- Providing merge UI.
- Owning app-specific state management.

## 5. Public API

```rust
pub struct DiffView<'a> {
    pub workbook: &'a WorkbookDiff,
}

pub struct SheetChangeSummaryView<'a> { /* borrowed fields */ }

pub struct CellChangeRow<'a> {
    pub id: ChangeAnchor,
    pub sheet_name: &'a str,
    pub address: CellAddress,
    pub row: u32,
    pub col: u32,
    pub kinds: CellChangeKinds,
    pub old_display: Option<String>,
    pub new_display: Option<String>,
    pub severity: ChangeSeverity,
}

pub struct ChangeAnchor {
    pub sheet_index: usize,
    pub row: u32,
    pub col: u32,
    pub subkind: Option<CellSubChangeKind>,
}
```

Adapters should borrow from `WorkbookDiff` where possible and allocate display
strings only when requested.

## 6. Filtering

```rust
pub struct ViewFilter {
    pub include_values: bool,
    pub include_formulas: bool,
    pub include_formatting: bool,
    pub include_diagnostics: bool,
    pub sheets: Option<Vec<SheetId>>,
}
```

Filtering should not mutate the underlying diff.

## 7. Navigation

Provide deterministic navigation over visible changes:

```rust
impl<'a> DiffView<'a> {
    pub fn rows(&self, filter: &ViewFilter) -> impl Iterator<Item = CellChangeRow<'a>>;
    pub fn next_after(&self, anchor: &ChangeAnchor, filter: &ViewFilter) -> Option<ChangeAnchor>;
    pub fn previous_before(&self, anchor: &ChangeAnchor, filter: &ViewFilter) -> Option<ChangeAnchor>;
}
```

## 8. Internal design

Adapters can be implemented as borrowed iterators over sorted `WorkbookDiff`.
If performance requires indexing, build an optional `DiffIndex`:

```rust
pub struct DiffIndex {
    by_sheet: Vec<SheetIndex>,
    anchors: Vec<ChangeAnchor>,
}
```

Index construction is explicit so callers control memory cost.

## 9. Acceptance criteria

- A GUI app can render a sheet tree and changed-cell table without inspecting
  internal fields beyond public adapters.
- Adapters have no GUI framework dependency.
- Navigation order matches JSON/CLI deterministic order.
- Virtualized table rows have stable anchors.