Commit Graph

352 Commits

Author SHA1 Message Date
Edward Langley 9634c95687 docs: update git merge command in AGENTS.md
Update git merge command in AGENTS.md to use origin/main.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:14 -07:00
Edward Langley df9a02b2a9 fix(ui): fix multi-level header suppression during scrolling
Implemented `show_sublabel` to ensure the first rendered entry in a
scrolled viewport always shows its full group labels.

Add regression tests for scrolling behavior in multi-level headers.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:14 -07:00
Edward Langley 9e02245f37 refactor(ui): improve panel focus cycling logic
Refactored `CyclePanelFocus` to follow a consistent
`Formula -> Category -> View` order.

Focus now correctly wraps around and handles non-panel modes.

Add regression tests for improved cycling logic.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:13 -07:00
Edward Langley 47ad9e6032 fix(io): improve persistence robustness and CSV compliance
Improved numeric parsing in Markdown files to surface errors instead of
defaulting to 0.0.

`export_csv` now uses `csv::Writer` to ensure RFC 4180 compliance (e.g.,
quoting fields containing commas).

`export_csv` now correctly respects the view's number format.

Add regression tests for numeric error handling and RFC 4180 compliance.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:13 -07:00
Edward Langley 77a5124d16 fix(io): enforce category limit in import wizard
The import wizard now proactively checks the `MAX_CATEGORIES` limit during
the proposal and configuration steps.

Advancing is blocked with a descriptive message if the limit would be
exceeded.

Fixed UI rendering order in `ImportWizardWidget` so messages are correctly
displayed.

Add regression tests for category limit enforcement.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:13 -07:00
Edward Langley f0b9227d8f feat(io): enhance CSV import with warnings and improved headless parsing
`parse_csv` now supports `parse_csv_with_warnings` to detect and report
short rows.

Short rows are now padded with `Value::Null` instead of being silently
dropped.

`ImportJsonHeadless` now uses `parse_csv_with_warnings` and surfaces
warnings in the status message.

`ImportJsonHeadless` now reuses parsed JSON/CSV data via
`json_import_records` instead of re-parsing.

Add regression tests for short row handling and headless import.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:13 -07:00
Edward Langley f04fe517ae fix(core): improve view robustness and axis management
`records_display` now returns `None` for out-of-bounds columns.

Added `try_axis_of` to `View` for non-panicking axis retrieval.

`cycle_axis` now uses `try_axis_of` to avoid panicking on unknown
categories.

Add regression tests for out-of-bounds access and unknown category cycling.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:13 -07:00
Edward Langley 45bfe2c4c7 refactor(core): use epsilon for float comparison and IndexSet for stem collection
Use `FLOAT_EQ_EPSILON` for equality/inequality operators and
division-by-zero guards in formula evaluation to ensure consistent
semantics.

Replace `Vec` with `IndexSet` for stem collection in `recompute_formulas`
to improve performance from O(n²) to O(n).

Add regression tests for epsilon-based comparison and stem collection
performance.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 21:43:13 -07:00
Edward Langley 0fe04de53e docs(context): refresh repo-map after ModelState/ViewState refactor
Line counts, 16 AppMode variants (RecordsNormal/RecordsEditing), 16 mode
keymaps, ModelState/ViewState split, crossterm 0.29. Findings from the
2026-06-09 systematic review (issues improvise-1cz .. improvise-2ud).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 21:00:31 -07:00
Edward Langley ecb524c947 chore(deps): update dependencies
Update Cargo.lock with new versions and additional dependencies.

This includes updates to bitflags, chrono, and hashbrown, along with the
addition of new packages such as approx, critical-section, and the futures
suite.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 20:48:44 -07:00
Edward Langley 62d18ffe7c chore(dev): add universal-ctags and global to devShell
Adds pkgs.global and pkgs.universal-ctags to the development shell.

This update also includes the corresponding changes in flake.lock.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-06-09 20:46:00 -07:00
Edward Langley 7249facf94 docs(ui): classify App-resident runtime/derived fields (improvise-99k)
Step 4 of vb4. After steps 1–3, App owns model_state, view_state, and a
residue of five fields that don't belong to either slice. Add a top-level
doc on App explaining the slice structure and tag each residue field as
derived cache / runtime metadata / transient / config with a one-line
rationale. No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:33:27 -07:00
Edward Langley 9ad8abd8a5 refactor(ui): move UI session fields into ViewState (improvise-ew0)
Step 3 of vb4. Populates ViewState with the 20 UI session fields (mode,
status_msg, wizard, search_query, search_mode, three panel-open flags,
three panel cursors, formula_cursor, yanked, tile_cat_idx, two view nav
stacks, drill_state, help_page, expanded_cats, buffers, transient_keymap)
and routes every read/write site through app.view_state.X. App now
contains only model_state, view_state, and the runtime/derived residue
(term dims, layout, last_autosave, abort_effects, keymap_set).

ViewState gets a manual Default impl mirroring the previous App::new
field initialisers; AppMode has no Default of its own so AppMode::Normal
is the explicit baseline. Effect::apply still takes &mut App; narrowing
remains step 5 (improvise-drg).

A structural test (app_view_state_owns_ui_session_fields) locks in the
20-field layout. 624 tests pass workspace-wide (+1 new). cargo clippy
--workspace --tests clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:19:31 -07:00
Edward Langley 917b928759 refactor(ui): move workbook/file_path/dirty into ModelState (improvise-x2c)
Step 2 of vb4. Populates ModelState with the document slice and routes
every read/write site (effects, draw, main, app methods, tests) through
app.model_state.X. App no longer owns workbook, file_path, or dirty
directly. Effect::apply signatures still take &mut App; narrowing happens
in step 5 (improvise-drg).

A structural test (app_model_state_owns_workbook_file_path_and_dirty)
locks in the field layout. ModelState now has a manual Default impl
that creates an "Untitled" Workbook so the existing constructibility
test keeps working.

623 tests pass workspace-wide (+1 new). cargo clippy --workspace --tests
clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:06:33 -07:00
Edward Langley f11d79f700 refactor(ui): scaffold ModelState and ViewState types (improvise-3vr)
Step 1 of vb4 (Split AppState into ModelState + ViewState): introduce the
named slice types in src/ui/app.rs as empty structs, with doc comments
pointing at the follow-up issues that fill them in. App still owns every
field directly; subsequent steps migrate the fields.

A structural test locks in that both types are constructible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 11:31:03 -07:00
Edward Langley 1181ffd0ab chore: update roadmap 2026-04-26 11:10:32 -07:00
Edward Langley 6756b00e4a chore: minor formatting changes 2026-04-26 11:08:41 -07:00
Ed L 3324ceef69 chore: don't use IFD for Cargo.nix 2026-04-26 10:28:37 -07:00
Ed L 452234f2d5 chore(merge): remote-tracking branch 'gh/dependabot/cargo/rand-0.8.6' 2026-04-26 10:09:29 -07:00
Ed L 782ca9dfaa chore(merge): remote-tracking branch 'me/main' 2026-04-26 10:09:16 -07:00
Ed L 36ee0e229f chore: update issues.jsonl 2026-04-26 10:08:57 -07:00
Edward Langley 9e310b9e4b chore: update agent instructions 2026-04-26 09:45:23 -07:00
dependabot[bot] 699d4d58dc chore(deps): bump rand from 0.8.5 to 0.8.6
Bumps [rand](https://github.com/rust-random/rand) from 0.8.5 to 0.8.6.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/0.8.6/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.8.5...0.8.6)

---
updated-dependencies:
- dependency-name: rand
  dependency-version: 0.8.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-22 22:17:23 +00:00
Ed L 21fc03cf18 chore: save session memories via bd remember
Captures three insights from 2026-04-16 deep review session:
- review-methodology-scoped-explore-agents
- compiler-exhaustiveness-theme
- agent-issue-drift-pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 16:07:45 -07:00
Ed L 47313c4e80 chore: update repo-map 2026-04-16 16:05:42 -07:00
Ed L 6362078032 chore: bd dolt sync conf + issue jsonl 2026-04-16 11:11:30 -07:00
Ed L 8242ef3dbe bd: update sync.remote 2026-04-16 11:04:54 -07:00
Ed L c158a8b99e bd init: initialize beads issue tracking 2026-04-16 10:58:57 -07:00
Edward Langley d99cb5ac8c Merge branch 'main' into worktree-improvise-ewi-formula-crate 2026-04-15 23:43:14 -07:00
Edward Langley 4e37e12f9a style: reformat code and cleanup whitespace
Reformat code for improved readability and remove unnecessary whitespace.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 23:42:44 -07:00
Edward Langley a900f147b5 feat(cmd): use new effects to improve command behavior
Update various commands to utilize the new AbortChain and CleanEmptyRecords
effects.

- CommitAndAdvance now pushes a mode change effect when aborting.
- ToggleRecordsMode now cleans up empty records upon exiting.
- EnterAdvance now emits AbortChain when at the bottom-right corner.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 23:42:44 -07:00
Edward Langley 489e2805e8 feat(ui): implement AbortChain and CleanEmptyRecords effects
Implement AbortChain and CleanEmptyRecords effects to allow
short-circuiting effect batches and purging cells with empty coordinates.
Update the App struct to support aborting effects during the application of
an effect batch.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 23:42:44 -07:00
Edward Langley f272a9d459 chore: update roadmap 2026-04-15 23:35:08 -07:00
Edward Langley ff74d619a3 docs(io): note improvise-io layout in repo-map
Reflect improvise-8zh: `persistence/` and `import/` now live in the
`improvise-io` sub-crate under `crates/`.

- Sub-crate list expanded to describe improvise-io's scope, its
  dependencies (improvise-core, improvise-formula), and the
  standalone-build guarantee.
- File Inventory reorganized: "Import layer" + persistence entries
  collapsed into a single "I/O crate layers" block with paths rooted at
  `crates/improvise-io/src/`.
- Updated line/test counts to current contents.
- Top-level block trimmed (persistence/format no longer live there) and
  lib.rs annotated as a re-export facade.

No consumer-facing path changes; `crate::persistence::*` and
`crate::import::*` still resolve via the main crate's re-exports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:08:55 -07:00
Edward Langley 5807464fc7 refactor(io): move persistence and import into improvise-io (improvise-8zh)
Relocate the two I/O module trees into the improvise-io sub-crate
scaffolded in the previous commit:

  git mv src/persistence -> crates/improvise-io/src/persistence
  git mv src/import      -> crates/improvise-io/src/import

The grammar file `improv.pest` moves alongside `persistence/mod.rs`;
the `#[grammar = "persistence/improv.pest"]` attribute resolves relative
to the new crate root and keeps working unchanged.

No path edits inside the moved code: the `crate::model::*`,
`crate::view::*`, `crate::workbook::*`, `crate::format::*`, and
`crate::formula::*` imports inside persistence and import all continue
to resolve because improvise-io's lib.rs re-exports those modules from
improvise-core and improvise-formula, mirroring the pattern improvise-core
uses for `formula`. Verified no `crate::ui::*`, `crate::command::*`,
`crate::draw::*` imports exist in the moved code (per improvise-8zh
acceptance criterion #3).

Main-crate `src/lib.rs` now re-exports `import` and `persistence` from
improvise-io, keeping every `crate::persistence::*` and `crate::import::*`
path in the 4 consumer files (ui/app.rs, ui/effect.rs,
ui/import_wizard_ui.rs, main.rs) resolving unchanged — no downstream
edits needed.

`examples/gen-grammar.rs` had `include_str!("../src/persistence/improv.pest")`;
updated the relative path to the new location under
`crates/improvise-io/src/persistence/`.

Verification:
- cargo check --workspace --examples: clean
- cargo test --workspace: 616 passing (219 main + 190 core + 65 formula + 142 io)
- cargo clippy --workspace --tests: clean
- cargo build -p improvise-io: standalone build succeeds, confirming no
  UI/command leakage into the IO crate (improvise-8zh acceptance #2, #3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:08:00 -07:00
Edward Langley bd17aed169 refactor(io): scaffold empty improvise-io sub-crate
Lay groundwork for Phase 3 of the workspace split (improvise-8zh): a new
`crates/improvise-io/` sub-crate that will house the persistence and
import layers once the files move in the next commit.

Only scaffolding here:
- New `crates/improvise-io/Cargo.toml` declares deps on improvise-core,
  improvise-formula, and the external crates persistence+import already
  use: anyhow, chrono, csv, flate2, indexmap, pest, pest_derive, serde,
  serde_json. Dev-deps: pest_meta, proptest, tempfile.
- New `crates/improvise-io/src/lib.rs` re-exports the core modules under
  their conventional names (`format`, `model`, `view`, `workbook`,
  `formula`) so in the next commit the moved code's `crate::model::*`,
  `crate::view::*`, `crate::workbook::*`, `crate::format::*`, and
  `crate::formula::*` paths resolve unchanged.
- Root `Cargo.toml` adds the new crate to workspace members and the main
  crate's `[dependencies]`, ready to receive the move.

No source files change yet; cargo check --workspace still compiles as
before.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:05:17 -07:00
Edward Langley 79dc54de21 Merge branch 'main' into worktree-improvise-ewi-formula-crate
# Conflicts:
#	TAGS
2026-04-15 22:47:51 -07:00
Edward Langley 9efbed403a chore: update tags 2026-04-15 22:46:03 -07:00
Edward Langley 03c7c00b25 chore: update tags 2026-04-15 22:45:35 -07:00
Edward Langley 08f190a036 chore: update gitignore 2026-04-15 22:45:18 -07:00
Edward Langley d20eb75a0b feat: roadmap from beads 2026-04-15 22:44:47 -07:00
Edward Langley 30383f203e refactor(keymap): pass mode arguments in keybindings
Update keybindings for normal, records-normal, editing, and records-editing
modes to pass the appropriate mode names as arguments to the parameterized
commands.

This ensures that the correct mode is entered when using commands like
`edit-or-drill` , `enter-edit-at-cursor` , `commit-cell-edit` , and
`commit-and-advance-right` .

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 22:44:13 -07:00
Edward Langley cece34a1d4 refactor(command): parameterize mode-related commands and effects
Make mode-related commands and effects mode-agnostic by passing the target
mode as an argument instead of inspecting the current application mode.

- `CommitAndAdvance` now accepts `edit_mode` .
- `EditOrDrill` now accepts `edit_mode` .
- `EnterEditAtCursorCmd` now accepts `target_mode` .
- `EnterEditAtCursor` effect now accepts `target_mode` .

Update the command registry to parse mode names from arguments and pass
them to the corresponding commands.

Add tests to verify the new mode-passing behavior.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 22:44:13 -07:00
Edward Langley 79f78c496e docs(core): note improvise-core layout in repo-map
Reflect Phase B of improvise-36h: `model/`, `view/`, `workbook.rs`, and
`format.rs` now live in the `improvise-core` sub-crate under `crates/`.

- Sub-crate list expanded to describe improvise-core's scope, its
  dependency on improvise-formula, and the standalone-build guarantee.
- File Inventory reorganized into a single "Core crate layers" block
  covering model/view/workbook/format, with paths rooted at
  `crates/improvise-core/src/`.
- Updated line/test counts to match current contents (Phase A + merge
  with main brought in records mode, IndexMap-backed DataStore, etc).

No architectural change; the main crate's re-exports keep every
`crate::model`/`crate::view`/`crate::workbook`/`crate::format` path
resolving unchanged, so no "How to Find Things" table edits are needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:33:45 -07:00
Edward Langley fc9d9cb52a refactor(core): move model, view, workbook, format into improvise-core
Relocate the four pure-data module trees into the improvise-core
sub-crate scaffolded in the previous commit. Phase A already made
these modules UI/IO-free; this commit is purely mechanical:

  git mv src/format.rs   -> crates/improvise-core/src/format.rs
  git mv src/workbook.rs -> crates/improvise-core/src/workbook.rs
  git mv src/model       -> crates/improvise-core/src/model
  git mv src/view        -> crates/improvise-core/src/view

The moved code contains no path edits: the `crate::formula::*`,
`crate::model::*`, `crate::view::*`, `crate::workbook::*`,
`crate::format::*` imports inside the four trees all continue to
resolve because the new crate mirrors the same module layout and
re-exports improvise_formula under `formula` via its lib.rs.

Main-crate `src/lib.rs` flips from declaring these as owned modules
(`pub mod model;` etc.) to re-exporting them from improvise-core
(`pub use improvise_core::model;` etc.). This keeps every
`crate::model::*`, `crate::view::*`, `crate::workbook::*`,
`crate::format::*` path inside the 26 consumer files in src/ (ui,
command, persistence, import, draw, main) resolving unchanged — no
downstream edits needed.

Verification:
- cargo check --workspace: clean
- cargo test --workspace: 612 passing (357 main + 190 core + 65 formula)
- cargo clippy --workspace --tests: clean
- cargo build -p improvise-core: standalone build succeeds, confirming
  zero UI/IO leakage into the core crate

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:31:42 -07:00
Edward Langley 0d75c7bd0b refactor(core): scaffold empty improvise-core sub-crate
Lay the groundwork for Phase B of improvise-36h: a new
`crates/improvise-core/` sub-crate that will house the pure-data core
(model, view, workbook, format) once the files move in the next commit.

Only scaffolding here:
- New `crates/improvise-core/Cargo.toml` mirroring improvise-formula's
  structure; declares deps on improvise-formula, anyhow, indexmap, serde.
- New `crates/improvise-core/src/lib.rs` with the single re-export
  `pub use improvise_formula as formula;` so that in the next commit the
  moved code's `crate::formula::*` paths resolve unchanged.
- Root `Cargo.toml` adds the new crate to the workspace members and the
  main crate's `[dependencies]`, ready to receive the move.

No source files change yet; cargo check --workspace still compiles as
before.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:21:58 -07:00
Edward Langley a22478eb87 Merge branch 'main' into worktree-improvise-ewi-formula-crate
# Conflicts:
#	src/ui/app.rs
#	src/ui/effect.rs
#	src/view/layout.rs
2026-04-15 21:39:00 -07:00
Edward Langley 242ddebb49 chore: matches -> method 2026-04-15 21:33:18 -07:00
Edward Langley 030865a0ff feat(records): implement records mode for data entry
Implement a new "Records" mode for data entry.
- Add `RecordsNormal` and `RecordsEditing` to `AppMode` and `ModeKey` .
- `DataStore` now uses `IndexMap` and supports `sort_by_key()` to ensure
  deterministic row order.
- `ToggleRecordsMode` command now sorts data and switches to
  `RecordsNormal` .
- `EnterEditMode` command now respects records editing variants.
- `RecordsNormal` mode includes a new `o` keybinding to add a record row.
- `RecordsEditing` mode inherits from `Editing` and adds an `Esc` binding
  to return to `RecordsNormal` .
- Added `SortData` effect to trigger data sorting.
- Updated UI to display "RECORDS" and "RECORDS INSERT" mode names and
  styles.
- Updated keymaps, command registry, and view navigation to support these
  new modes.
- Added comprehensive tests for records mode behavior, including sorting
  and boundary conditions for Tab/Enter.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 21:32:35 -07:00
Edward Langley ded35f705c feat(model): use IndexMap for deterministic insertion order in DataStore
Replace `HashMap` with `IndexMap` in `DataStore::cells` to preserve
insertion order. This allows records mode to display rows in the order they
were added. Update `remove` to use `shift_remove` to maintain order during
deletions.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf)
2026-04-15 21:32:35 -07:00