GridCraft Flatpak repository
Latest published release: $RELEASE_TAG
flatpak remote-add --if-not-exists gridcraft $base_url/flatpak/gridcraft.flatpakrepo - flatpak install gridcraft $APP_ID
diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 000000000..2408084cf --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +reviews: + auto_review: + # Dependabot bumps are checked by CI; skip CodeRabbit reviews on them. + ignore_usernames: + - "dependabot[bot]" diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..2c4b8cb1a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,30 @@ +version: 2 +updates: + # Maintain Rust / Cargo dependencies + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + time: "06:00" + timezone: "America/New_York" + # Consolidate updates into a single PR rather than one PR per crate + groups: + cargo-dependencies: + patterns: + - "*" + commit-message: + prefix: "chore(deps)" + + # Maintain GitHub Actions workflows + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + time: "06:00" + timezone: "America/New_York" + groups: + actions: + patterns: + - "*" + commit-message: + prefix: "ci(deps)" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77cde0cec..c704eb4d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,7 @@ -# The AGENTS.md quality gate (`cargo xtask ci`: fmt, clippy -D warnings, tests, assets, layers, -# wasm, parity --check) on every pull request and every push to main, so a merge burst can't land -# a red tree that only the next agent session discovers. name: CI +# Quality gates for every push to main and every pull request (`cargo xtask ci`), through the +# suite's shared gate workflow in craft-common-actions. on: push: branches: [main] @@ -12,37 +11,18 @@ on: permissions: contents: read +# A newer push to a PR branch cancels its older run; every push to main runs to the end. concurrency: - group: ci-${{ github.ref }} - cancel-in-progress: true + group: ci-${{ github.event_name == 'pull_request' && github.ref || github.run_id }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: gate: - name: cargo xtask ci - runs-on: ubuntu-24.04 - timeout-minutes: 60 - env: - CARGO_TERM_COLOR: always - CARGO_INCREMENTAL: "0" - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - - name: Install Linux build dependencies (winit, wgpu, rfd) - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev \ - libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev mesa-vulkan-drivers - - - name: Install Rust (stable + clippy, rustfmt, wasm32) - run: | - rustup toolchain install stable --profile minimal --component clippy,rustfmt \ - --target wasm32-unknown-unknown - rustup default stable - - - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - with: - save-if: ${{ github.ref == 'refs/heads/main' }} - - - name: Quality gate - run: cargo xtask ci + # Tracks @main so suite-wide CI fixes reach every app without a PR in each repository. + uses: storytold/craft-common-actions/.github/workflows/gate.yml@main + with: + # The same craft-fonts commit as release.yml and freebsd.yml, so the gate tests the fonts that ship. + craft-fonts-ref: abb83316d96aa59c1cf64784289e378fe9fa5695 + packages: >- + pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev libxi-dev + libgtk-3-dev libfontconfig1-dev libfreetype-dev mesa-vulkan-drivers diff --git a/.github/workflows/flatpak-pages.yml b/.github/workflows/flatpak-pages.yml deleted file mode 100644 index cd8f12ab3..000000000 --- a/.github/workflows/flatpak-pages.yml +++ /dev/null @@ -1,176 +0,0 @@ -name: Publish Flatpak repository to Pages - -on: - release: - types: [published] - workflow_dispatch: - inputs: - release_tag: - description: "Published GitHub release tag to publish (for example, v1.2.3)" - required: true - type: string - -permissions: - contents: read - -concurrency: - group: flatpak-pages-${{ github.repository }} - cancel-in-progress: false - -jobs: - build: - name: Build Flatpak repository - # Pre-releases (rc builds) never reach the stable branch: a published pre-release is skipped - # here, and the validation step below refuses a manual tag with a pre-release suffix. - if: github.event_name != 'release' || !github.event.release.prerelease - runs-on: ubuntu-24.04 - permissions: - contents: read - # configure-pages only reads the Pages configuration (base_url); deploy needs write. - pages: read - env: - GH_TOKEN: ${{ github.token }} - RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }} - APP_ID: ai.storyteller.gridcraft - steps: - - name: Configure Pages - id: pages - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - - - name: Install Flatpak repository tools - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends flatpak ostree - - - name: Download and validate release bundles - shell: bash - run: | - set -euo pipefail - tag="$RELEASE_TAG" - if ! printf '%s' "$tag" | grep -Eq '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then - echo "::error::Release tag '$tag' is not strict SemVer prefixed with v" - exit 1 - fi - # A pre-release has a "-" before any "+build" metadata (v1.2.3-rc.1). - case "${tag%%+*}" in - *-*) - echo "::error::$tag is a pre-release; only stable releases are published to the Flatpak repository" - exit 1 - ;; - esac - published_tag="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$tag" --jq \ - 'select(.draft == false and .prerelease == false and .published_at != null) | .tag_name')" - if [[ "$published_tag" != "$tag" ]]; then - echo "::error::$tag is not a published stable (non-pre-release) release in $GITHUB_REPOSITORY" - exit 1 - fi - - version="${tag#v}" - mkdir -p bundles - gh release download "$tag" --repo "$GITHUB_REPOSITORY" \ - --pattern SHA256SUMS.txt --dir bundles - for arch in x86_64 aarch64; do - asset="gridcraft-$version-linux-$arch.flatpak" - gh release download "$tag" --repo "$GITHUB_REPOSITORY" \ - --pattern "$asset" --dir bundles - test -s "bundles/$asset" - ( - cd bundles - awk -v file="$asset" '$2 == file || $2 == "*" file { print; found=1 } END { exit !found }' \ - SHA256SUMS.txt | sha256sum --check - - ) - done - test "$(find bundles -maxdepth 1 -type f -name '*.flatpak' | wc -l)" -eq 2 - - for arch in x86_64 aarch64; do - asset="bundles/gridcraft-$version-linux-$arch.flatpak" - validation_repo="$(mktemp -d)" - ostree --repo="$validation_repo" init --mode=archive-z2 - flatpak build-import-bundle "$validation_repo" "$asset" - expected_ref="app/$APP_ID/$arch/stable" - ostree --repo="$validation_repo" refs | grep -Fxq "$expected_ref" || { - echo "::error::$(basename "$asset") does not contain $expected_ref" - exit 1 - } - rm -rf "$validation_repo" - done - - - name: Build repository and site - shell: bash - env: - PAGES_BASE_URL: ${{ steps.pages.outputs.base_url }} - run: | - set -euo pipefail - site="$RUNNER_TEMP/site" - repo_dir="$site/flatpak/repo" - mkdir -p "$repo_dir" - ostree --repo="$repo_dir" init --mode=archive-z2 - - previous_url="${PAGES_BASE_URL%/}/flatpak/repo" - if curl --fail --silent --show-error --location \ - --output /dev/null "$previous_url/summary"; then - ostree --repo="$repo_dir" remote add --no-gpg-verify previous "$previous_url" - ostree --repo="$repo_dir" pull --mirror previous - ostree --repo="$repo_dir" remote delete previous - fi - - version="${RELEASE_TAG#v}" - for arch in x86_64 aarch64; do - flatpak build-import-bundle "$repo_dir" \ - "bundles/gridcraft-$version-linux-$arch.flatpak" - done - # Prune unreachable objects and keep at most 3 commits per ref, so the Pages repository - # (re-mirrored and re-deployed on every release) does not grow without bound. - flatpak build-update-repo \ - --prune --prune-depth=3 \ - --title="GridCraft" \ - --comment='Official GridCraft releases' \ - --description='Official Flatpak repository for GridCraft' \ - --homepage="https://github.com/$GITHUB_REPOSITORY" \ - --default-branch=stable \ - "$repo_dir" - - for arch in x86_64 aarch64; do - ostree --repo="$repo_dir" rev-parse "app/$APP_ID/$arch/stable" >/dev/null - done - test -s "$repo_dir/summary" - - base_url="${PAGES_BASE_URL%/}" - repo_url="$base_url/flatpak/repo/" - cat >"$site/flatpak/gridcraft.flatpakrepo" <"$site/flatpak/index.html" <
Latest published release: $RELEASE_TAG
flatpak remote-add --if-not-exists gridcraft $base_url/flatpak/gridcraft.flatpakrepo - flatpak install gridcraft $APP_ID
+
+
- Spreadsheets and data; an open-source, clean-room reimplementation of Microsoft Excel, rebuilt in pure Rust. + Spreadsheets and data; an open-source, high-performance modern spreadsheet application, built in pure Rust.
- A fast, open-source, clean-room take on the Excel workflow. It runs natively on macOS,
+ A fast, open-source, clean-room take on modern spreadsheet workflows. It runs natively on macOS,
Windows, Linux and BSD, and in the browser via WebAssembly.
By the ArtCraft team.
@@ -67,8 +74,8 @@

Formulas. 500+ functions, dynamic arrays, LET and LAMBDA, structured table references.

Dark mode and the Insert tab: tables, charts, sparklines, pictures, shapes, links and comments.

PivotTables. Field list, filters, layouts, date grouping and show-values-as, saved to and read from XLSX.

Dark mode and the Insert tab: tables, charts, sparklines, pictures, shapes, links and comments.

Pivot tables. Field list, filters, layouts, date grouping and show-values-as, saved to and read from XLSX.

Charts. Seventeen chart types, Chart Design tab and a Format pane; selecting a chart outlines its source data.
diff --git a/ROADMAP.md b/ROADMAP.md
index fba2c6a35..591d6a5c9 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -2,7 +2,7 @@
**Stage: alpha** · next: beta, ~25 points of "ready for real work" and ~160–240 h away
-> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-14 · **Change:** minor (lookups compare numbers exactly, like Excel) · **Target:** Microsoft Excel (Microsoft 365)
+> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-22 · **Change:** trivial (progress log: formula hardening, #2163/#2162; previously minor: Page Setup paper sizes: JIS B4/B5/B6, the Japanese postcards and envelopes, and A6; long flat operator chains up to Excel's formula limit) · **Target:** Microsoft Excel (Microsoft 365)
GridCraft aims at full Microsoft Excel parity, and at being better in places: faster, open (XLSX
is the native format), fully scriptable by agents (MCP, control channel, CLI), and on the web.
@@ -21,6 +21,7 @@ This page is the summary. The detail is in:
| Number | Value | Kind |
|---|---|---|
+| 2026-10-14 | Editing a cell with text that would read back as a number, boolean, date or formula (entered with a leading apostrophe) shows the apostrophe in the editor and formula bar, so Enter unchanged keeps it text (#1362) |
| **Feature breadth** (weighted) | **~75%** | estimated, anchored on two measurements: ribbon catalog 274 / 290 (94.5%), worksheet functions 513 / 523 (98.1%; 504 working, 96.4%) |
| **Ready for real work** | **~50%** | estimated from written weights (51.6); [target-app-parity.md](docs/target-app-parity.md) |
| **Mainstream practitioner** | **~50%** | estimated: typical analyst/finance user, weekly features, × 0.90 interaction × 0.92 stability × 0.88 file exchange; [method](docs/target-app-parity.md#mainstream-practitioner) |
@@ -93,7 +94,9 @@ The ribbon is translated into Japanese, Simplified Chinese, Korean, Brazilian Po
and German (266–268 labels each, ~12% of ~2,200 strings; merged 10-10 in #31, #104, #82, German
added 10-11), the
interface follows the system language, and CJK, Thai and Hebrew text falls back to system fonts
-(#38). Dialogs, menus and messages are English; formulas and number formats are en-US only.
+(#38). Japanese (10-17) and Brazilian Portuguese also translate the dialog titles and labels,
+message boxes, Backstage/File-view items, template names and native menus: 943 strings each, ~43%.
+The remaining dialogs, menus and messages are English; formulas and number formats are en-US only.
Localized German formulas and numbers are in PR #163. Detail: [localization-parity.md](docs/localization-parity.md).
| Language | Code | Status | UI strings |
@@ -104,14 +107,14 @@ Localized German formulas and numbers are in PR #163. Detail: [localization-pari
| Hindi | hi | none | 0% |
| Arabic | ar | none (no RTL layout, no shaping) | 0% |
| French | fr | none | 0% |
-| Portuguese | pt-BR | menus only | ~12% |
+| Portuguese | pt-BR | menus, File view, dialogs | ~43% |
| Indonesian | id | none | 0% |
-| Japanese | ja | menus only | ~12% |
+| Japanese | ja | menus, File view, dialogs, messages | ~43% |
| German | de | menus only | ~12% |
| Korean | ko | menus only | ~12% |
| Vietnamese | vi | none | 0% |
-Other shipped languages: 2 (Russian and German, menus only, ~12%).
+Other shipped languages: 3 (Russian and German, menus only, ~12%; Dutch, menus, File view and dialog titles, ~24%).
## Upcoming
@@ -132,7 +135,32 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in
| Date | What landed |
|---|---|
+| 2026-10-22 | Formula hardening: digits too many for a finite number are text, so `"1 <400 digits>/<400 digits>"` no longer coerces to NaN; a NaN column index in VLOOKUP, HLOOKUP and the D-functions is `#VALUE!` instead of an index underflow; REGEXREPLACE stops building a result as soon as it can only be too long (a worst case went from 1 GB to 7 MB) (#2163, #2162) |
+| 2026-10-21 | Page Setup paper sizes match Japanese Excel: `B4`/`B5`/`B6` are the JIS sizes (ISO B4/B5/B6 stay reachable by name), so a Japanese B5 worksheet prints at 182×257 mm; Japanese Postcard (100×148 mm), Double Postcard (148×200 mm), Envelope #3/#4 (120×235/90×205 mm), Kaku #2/#3 (240×332/216×277 mm) and A6 are added, both sizes reach the PDF page (`file.exportPdf`/`file.print` MediaBox) and the size survives an XLSX round-trip; the Page Layout Size menu lists them. `B4`/`B5` used to be the ISO sizes, which is changed here |
+| 2026-10-20 | Japanese interface catalog covers every key the Brazilian Portuguese catalog translates: the 398-label shared core plus 545 dialog, message, Backstage and menu strings (943 total, ~43% of ~2,200). A test parses `pt.rs`'s source, so the two catalogs stay in step |
+| 2026-10-20 | Interface translated into Dutch (518 labels: ribbon, context menus, File view, dialog titles, Options); `nl`, `nl-NL`, `nl-BE` locale tags resolve to Dutch |
+| 2026-10-19 | Long flat operator chains (`=A1+A2+…`) up to Excel's 8,192-character limit (4,096 operands): entering, filling, inserting rows, undo, Evaluate Formula and XLSX save no longer overflow the stack; chains past 64 operands are saved as plain formulas, not dynamic arrays; Spanish formula entry accepts chains past 256 operands (#916) |
+| 2026-10-19 | Linux: "Use system setting" for the theme keeps following the desktop when the XDG Desktop Portal stops answering: each read gives up after 2 s and the next poll reconnects, where one unanswered call stalled the watcher for the rest of the session |
+| 2026-10-16 | Memory: undo steps share a sheet's picture bytes and the workbook's VBA project instead of copying them: 50 edits on a sheet with a 20 MB picture keep 22 MB instead of 992 MB |
+| 2026-10-16 | Memory: floating pictures are decoded at about the size they are drawn, with limits, into a cache bounded by bytes and dropped with their workbook, instead of at full size into one that never let go; two open workbooks no longer show each other's picture. 12 large pictures scrolled through keep 40 MB of textures instead of 258 MB, and none once the workbook closes |
+| 2026-10-16 | The web app keeps its preferences between visits (#1562): theme (dark mode), interface size, language, editing options and the rest of what the desktop app saves in `ui.json` and `prefs.json` are kept in the browser's `localStorage`, written as soon as they change |
+| 2026-10-16 | Memory: the interface and script fallback fonts are read once per run and shared with egui instead of copied into it: an empty workbook settles at 158 MB instead of 258 MB on macOS |
+| 2026-10-15 | Function help follows the interface language: argument hints, autocomplete, Insert Function (search and readable categories) and the Formulas-tab menus read per-language tables of descriptions and argument names; Spanish keeps its 10 functions in the new format |
+| 2026-10-15 | Row auto-fit counts a cell's line breaks only when the cell wraps, as Excel does: a file whose unwrapped cells hold multi-line text no longer opens with tall rows (typing a break still turns wrap on and grows the row) |
| 2026-10-14 | Lookups (MATCH, XMATCH, VLOOKUP, HLOOKUP, XLOOKUP, LOOKUP) compare numbers exactly like Excel, so a computed key such as `=0.1+0.2` no longer finds 0.3; `=` and COUNTIF/SUMIF keep their 15-digit comparison |
+| 2026-10-14 | Protect Sheet on a protected sheet: Home › Format, its keytips (HOP, RPS) and the tab menu now read Unprotect Sheet… and unprotect (straight away without a password); a protected sheet that forbids selecting locked (or unlocked) cells is enforced for clicks, arrows and Go To, and the Protect Sheet dialog has the select options (#1346) |
+| 2026-10-14 | XLSX: formulas opened with dynamic-array metadata (`cm`) keep it on save, with `xl/metadata.xml`. Before, a formula returning one value lost it (11 of 40 corpus files that have the part lost it entirely), and Excel recalculated some of them with implicit intersection (`SUMPRODUCT(IFERROR(...))` changed value) |
+| 2026-10-14 | Recalculation: a dynamic array's anchor given a new formula that reads its old spill area (`A1` was `=SEQUENCE(3)`, becomes `=SUM(A2:A3)+1` or `=SEQUENCE(1,A2+1)`) sees that area empty instead of the old values |
+| 2026-10-14 | Recalculation: when two arrays of one recalculation want the same empty cells, the formulas that read the one laid out second (at its anchor or over the cells it would have spilled into) read `#SPILL!` and empty cells instead of its values |
+| 2026-10-13 | Formula-entry Command/Ctrl-click inserts another reference with the locale's argument separator; Shift-click extends from a stable, sheet-aware anchor. Pointer tests cover repeated clicks, reversed ranges, ordinary replacement, typed separators, Spanish syntax, sheet switches and keyboard continuation. Readiness estimates unchanged. |
+| 2026-10-13 | `formulas.evaluate` (`gridcraft-cli eval`, MCP `evaluate_formula`) refuses what entering the formula in a cell refuses, with the reason (`=SUM(1;2)`: "expected `,` or `)`"), instead of `#NAME?` for any formula that doesn't parse |
+| 2026-10-13 | Colour menus: Fill Color, Font Color and the Format Cells pickers end with Recent Colors (the last ten custom colours) and More Colors… (hue/saturation area, RGB, hex box, preview, OK/Cancel) (#928) |
+| 2026-10-13 | Multi-level category axes: a category range two or more columns wide beside a column of values (year beside month, Excel's `multiLvlStrRef`) draws its innermost labels across the plot and the outer levels in rows under them with group separators (columns beside the labels in bar charts), instead of flattening the two columns into twice as many categories; saving writes the reference back as `multiLvlStrRef` with Excel's level caches, so the axis survives a round trip |
+| 2026-10-13 | Charts: a huge trendline forecast no longer collapses the chart: on a category axis it adds at most four times the data in empty slots (at least 32), the line is sampled over the plot only, and forecasts read from XLSX or set by command are clamped, NaN and infinity becoming 0 (#1148)
+| 2026-10-13 | XLSX export writes a picture used on several sheets once, as one `xl/media` part every drawing points to (it wrote a copy per drawing: a 16-sheet workbook with one 112 KB logo grew from 0.4 to 1.9 MB) (#985) |
+| 2026-10-13 | XLSX: `[Content_Types].xml`, `_rels/.rels`, the workbook rels and `xl/workbook.xml` are the first zip entries (document properties last), so libmagic and PHP `finfo` detect the file type even with large properties (#1090) |
+| 2026-10-13 | Conditional formatting: a rule gathers range statistics only when it reads them (top/bottom, above average, duplicates, scales, bars, icons) and borrows them instead of copying them per cell, so the per-frame lookup of an expression or cell-value rule no longer visits its whole range (#1098, part 1) |
+| 2026-10-12 | Next/previous sheet navigation stops at the first/last visible worksheet instead of activating a hidden boundary sheet; the current selection is retained |
| 2026-10-12 | Rows auto-fit oversized fonts: opening a file and whole-row/column formatting grow non-custom rows to their tallest font (#833) |
| 2026-10-12 | Number formats: parsing a format code is linear in its length (long runs of `[`, `,` or `/` no longer take quadratic time), and an unclosed `[` is a literal when splitting sections as well as when tokenizing (#810) |
| 2026-10-12 | Number formats: a fraction denominator with 65,536 zeros no longer crashes; format codes are capped at 255 characters like Excel (longer codes display as General, `TEXT` gives `#VALUE!`) (#807) |
@@ -194,7 +222,24 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in
| Date | Change | Summary |
|---|---|---|
+| 2026-10-22 | trivial | Progress log: formula hardening (#2163, #2162) |
+| 2026-10-21 | minor | Page Setup paper sizes: JIS B4/B5/B6 (ISO by name), Japanese postcards and envelopes, A6; PDF page size follows, XLSX round-trips |
+| 2026-10-20 | minor | Dutch (nl) listed under other shipped languages; progress log row |
+| 2026-10-19 | minor | Progress log: long flat operator chains (#916) |
+| 2026-10-19 | trivial | Progress log: desktop theme portal read timeout |
+| 2026-10-16 | minor | Progress log: undo steps share picture and macro bytes |
+| 2026-10-16 | minor | Progress log: floating pictures' textures bounded and kept per workbook |
+| 2026-10-16 | trivial | Progress log: web preferences kept between visits (#1562) |
+| 2026-10-16 | minor | Progress log: interface fonts held once instead of twice |
| 2026-10-14 | minor | Progress log: lookups compare numbers exactly |
+| 2026-10-14 | minor | XLSX dynamic-array `cm` metadata kept on save; progress log row |
+| 2026-10-14 | minor | Progress log: spill anchor reading its old spill area |
+| 2026-10-14 | minor | Progress log: formulas reading an array that loses a spill conflict |
+| 2026-10-13 | trivial | Progress log: More Colors… and Recent Colors in the colour menus (#928) |
+| 2026-10-13 | minor | Multi-level category axes (read, drawn, written); progress log row |
+| 2026-10-13 | trivial | Progress log: shared pictures written once on XLSX export (#985) |
+| 2026-10-13 | minor | Progress log: conditional-format lookups no longer scan the range for rules without statistics (#1098) |
+| 2026-10-12 | minor | Progress log: hidden-sheet navigation at workbook boundaries |
| 2026-10-12 | minor | Rows auto-fit oversized fonts on open and whole-row/column formatting (#833); progress log row |
| 2026-10-12 | minor | Progress log: multi-area row/column delete (#758) |
| 2026-10-12 | trivial | Progress log: XLSX chart sheets kept on save (#727) |
diff --git a/apps/gridcraft-cli/src/check.rs b/apps/gridcraft-cli/src/check.rs
index 2b8529876..74d2fca71 100644
--- a/apps/gridcraft-cli/src/check.rs
+++ b/apps/gridcraft-cli/src/check.rs
@@ -139,9 +139,10 @@ impl RoundTrip {
#[derive(Clone, Debug, Default, PartialEq)]
pub struct FileReport {
pub path: String,
- /// GridCraft couldn't open the file: its message.
+ /// Opening the file or discovering the requested inputs failed: its message.
pub error: Option