Skip to content

fix(tui): bulk-edit include toggles invisible + raw custom-field labels (v1.6.1)#138

Merged
thomaschristory merged 3 commits into
mainfrom
release/1.6.1
Jun 29, 2026
Merged

fix(tui): bulk-edit include toggles invisible + raw custom-field labels (v1.6.1)#138
thomaschristory merged 3 commits into
mainfrom
release/1.6.1

Conversation

@thomaschristory

Copy link
Copy Markdown
Owner

Closes #137. Patch release v1.6.1.

Problem

In the TUI bulk-edit form, custom-field edits silently didn't save and showed an ugly custom_fields.<name> name.

Root causes & fixes

  1. Invisible include toggle → silent no-save (the real bug). .bulk-include { width: 6 } is too narrow for a Textual Switch (border + padding + slider ≈ 10 cells). With the real stylesheet the slider clipped to zero width, so every per-field include toggle rendered blank. No visible toggle → no field opted in → empty patch → silent no-change. Fixed by sizing .bulk-include to fit (width: auto), with a regression test asserting the slider never clips to zero.
  2. Raw custom_fields.<name> labels. Both forms rendered Label(name) instead of CustomFieldDef.label. Now WidgetSpec carries label; the form rows and the change-preview diff show the human label.
  3. Latent destructive bug. A select whose choice-set didn't resolve rendered empty; opting it in seeded None and silently nulled the field. A blank select now seeds nothing on opt-in; only the explicit ∅ button nulls.

Tests

7 new tests (TDD, each watched fail first): toggle-not-clipped regression (real CSS loaded), human-label rendering in both forms + diff, end-to-end custom-field save, and blank-select-doesn't-null.

Docs

  • CHANGELOG.md — v1.6.1 section.
  • docs/guides/interactive-tui.md — clarified the include-toggle / per-field opt-in and that custom fields appear under their label.

Release

Version bumped to 1.6.1 across pyproject.toml, nsc/_version.py, uv.lock, and CHANGELOG. Tag v1.6.1 to be pushed on main HEAD after merge.

🤖 Generated with Claude Code

…els human-readable

The per-field include switch in the bulk-edit form was clipped to zero width
by `.bulk-include { width: 6 }` (a Textual Switch needs ~10 cells for its
border + padding + slider), so it rendered blank. Users couldn't see or flip
it, so no field was opted in and applies produced no change with no error —
custom-field edits silently didn't save.

Also render custom fields by their human label (`spec.label or name`) in both
the single-edit and bulk-edit forms and in the change-preview diff, instead of
the raw `custom_fields.<name>` key. And stop a blank `select` (unresolved
choice set) from seeding a null on opt-in, which silently cleared a field the
user never edited.

Bumps version to 1.6.1.

Closes #137

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thomaschristory

Copy link
Copy Markdown
Owner Author

Claimed by maintainer's agent. Branch release/1.6.1. Running adversarial review next, then merge + tag v1.6.1.

Thomas Christory and others added 2 commits June 29, 2026 23:24
…elect null

Adversarial review of the bulk-edit fix surfaced a newly-reachable data-loss
path: because the include toggle is now visible and usable, opting in a custom
field whose widget didn't reflect the records' shared value would overwrite it.
A shared boolean custom field rendered as a default-False switch, so opting it
in unchanged silently flipped every record True -> False; a shared multiselect
cleared to []. Seed custom-field widgets (including multiselect) from the
records' shared value over the flattened custom_fields.<name> keys so an
opted-in-but-unedited field is a no-op.

Also harden on_select_changed so a blank select can't stage a null before the
field is opted in (only the explicit null button nulls), and add a guard test
that the single-edit diff modal renders the custom-field label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thomaschristory

Copy link
Copy Markdown
Owner Author

Adversarial review (3 parallel read-only agents) + fixes

Correctness/regression, break-the-fix, and test-quality reviews ran against the diff. Verdicts: ship, with findings.

Findings actioned:

  • Data-loss bug, newly reachable — because the toggle is now usable, opting in a custom field whose widget didn't reflect the records' shared value would overwrite it: a shared boolean rendered False and opting it in unchanged flipped all records to False; a shared multiselect cleared. Fixed: custom-field widgets (incl. multiselect) now seed the shared value over flattened custom_fields.<name> keys → opt-in-without-edit is a no-op. (+2 tests)
  • on_select_changed could stage a mount-time/blank NULL — added a guard so a blank select can't stage a null before opt-in. (defensive)
  • Test gap — added a single-edit diff-modal label assertion (live wiring path).

Findings dismissed (with reason):

  • detail.py diff_rows missing field_labels — detail view edits only top-level body fields (no .label); custom fields there are non-editable flattened rows, so it'd be dead code.
  • bulk tags don't seed shared — pre-existing intentional design (tags have their own {name,slug} flow); left untouched.

Full suite: 1335 passed, 1 skipped; ruff + mypy --strict clean.

@thomaschristory thomaschristory merged commit e69889b into main Jun 29, 2026
9 checks passed
@thomaschristory thomaschristory deleted the release/1.6.1 branch June 29, 2026 21:29
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.

TUI bulk-edit: custom-field edits silently don't save (include toggle invisible) + raw custom_fields.<name> labels

1 participant