Add durable [[hotbar]] config bindings for slots 1-8, including default
bindings when no hotbar config is present.
Validate bindings without panicking: skip out-of-range slots, use the last
duplicate slot, and preserve unknown actions so future UI layers can show
disabled placeholders.
On Windows, AltGr is delivered as Ctrl+Alt by crossterm. European keyboard
layouts (French AZERTY, German QWERTZ, etc.) use AltGr to type characters
like @ (AltGr+0), # (AltGr+3), etc. The sidebar-focus shortcuts for
Alt+@/Alt+!/Alt+#/Alt+$/Alt+%) were matching on "contains ALT" alone,
swallowing these AltGr-typed characters instead of inserting them into
the composer.
Exclude the Ctrl modifier from these sidebar-focus shortcut guards so
AltGr-typed glyphs fall through to the catch-all and
are inserted as text. This is consistent with the has_ctrl_or_alt /
is_altgr philosophy in key_hint.rs, which already treats Ctrl+Alt as
AltGr to preserve European keyboard input.
Closes#2863
Six fixes for the bot review comments landed on PR #2864 head
649d3990. See phase2-playbook.md §7 for the triage rationale.
* persistence.rs: oversized state file now surfaces an InvalidData
error instead of silently returning a default. The old behaviour
would let the next save overwrite the oversized file and destroy
the user's data. Test updated to expect the error.
* persistence.rs: PersistedDelegation gains a `status` field so
in-flight `InProgress` delegations aren't silently demoted to
`Pending` on restart. The snapshot now writes the live status
and restore_from_snapshot honours it. Adds a regression test.
* mention.rs: resolve_tab_mention no longer sorts its input — tab
mentions (@Tab2) must map to the visual order in the tab bar,
not to an arbitrary ID sort. Test updated.
* manager.rs: `pending_tasks` renamed to `completed_delegations`
because the getter returns completed DelegationResults, not
in-flight tasks. Docstring points to the in-flight getter
`pending_delegations` to avoid the same confusion recurring.
* manager.rs: delegate_task and start_meeting now validate that
the from/to tab IDs (or all participant IDs) currently exist
in the manager. Returns `None` on any unknown ID, preventing
orphaned tasks / meetings with stale tab references. Two new
regression tests cover both methods.
Local CI matrix (Windows runner, flags matching ci.yml):
- cargo fmt --all -- --check: exit 0
- cargo clippy --workspace --all-features --locked -- -D warnings: exit 0
- cargo test --workspace --all-features --locked: 4282 pass, 6 fail
(the 6 failures are pre-existing on the baseline; not caused
by this PR)
- git diff --exit-code -- Cargo.lock: exit 0
The three deferred threads (#1 close_tab cleanup, #5 cross_tab_links
snapshot, #8 TabGroup::new collision risk) are explicitly out of
scope here; they belong to the follow-up collab/UI PR per the
narrow-harvest promise to Hmbown.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sister PR to #2753, scoped to the narrow tab-core/persistence slice
Hmbown asked for in the v0.9 stewardship review. Adds the `tab`
module under `crates/tui/src/tui/` and a one-line module registration
in `tui/mod.rs`. Nothing else in the host changes here — the
switcher / picker / meeting UI pass and the host wiring
(`App::tab_manager`, keyboard shortcuts, mouse menu, tab-bar layout
in `ui.rs`) live on #2753 and land in a follow-up PR.
Scope:
* `tab::TabManager` with monotonic `next_tab_id`, max 9 tabs by
default, snapshot/restore round-trip, group assignment,
cross-tab event/links, and persistence integration
* `tab::delegator::TaskDelegator` — bounded pending queue with
`MAX_COMPLETED_RESULTS` auto-prune; `take_pending_for_tab` marks
InProgress in place and returns a clone so subsequent
`start_task` / `complete` / `fail_task` / `cancel_task` can still
find the task (the previous `swap_remove` would have dropped it
on the first call)
* `tab::meeting::MeetingManager` — participants, messages by
type (Regular / Question / Answer / Proposal / Agreement /
Objection / Summary), decisions
* `tab::cross_tab` — `CrossTabEvent` (TaskDelegation / ReviewRequest
/ MeetingInvite / ContextSync / ResultReturn) and `SharedContext`
* `tab::group` — `TabGroup` / `TabGroupManager` /
`GroupColor` (Red/Orange/Yellow/Green/Cyan/Blue/Magenta/Gray)
* `tab::mention` — `@Tab<N>`, `@N`, `@tab<n>` (case-insensitive)
parser, with `resolve_tab_mention` for 1-indexed tab lookups
* `tab::persistence` — JSON file in the user's data dir,
`PersistedTabState` / `PersistedTab` / `PersistedDelegation` /
`PersistedGroup` with schema-version header, atomic save,
bounded file size, corruption-tolerant load
* `tab::benches` and `tab::key_e2e` regression suites (roundtrip,
save/load, end-to-end save→load with keymap)
Lint posture:
* `#![allow(dead_code, unused_imports)]` on `tab/mod.rs` because
the collab/UI pass is not on this branch; the public surface is
intentionally exposed for the follow-up wiring in #2753
* One pre-existing `tools/shell.rs` fix piggy-backed: drop the
redundant `as *mut c_void` cast on `child.as_raw_handle()` (the
return type is already `*mut c_void`). Pre-existing on
`codex/v0.9.0-stewardship`; promoted to `clippy::unnecessary_cast`
by rust 1.95
Local CI matrix on this branch (Windows runner, same flags as
`.github/workflows/ci.yml`):
* `cargo fmt --all -- --check` — pass
* `cargo clippy --workspace --all-features --locked -- -D warnings`
— pass, 0 errors
* `cargo test --bin codewhale-tui tab::` — 63/63 pass
* `git diff --exit-code -- Cargo.lock` — clean
GitHub Actions will run on the standard fork-PR approval gate; the
`on.pull_request` branch filter on this repo matches
`codex/v0.9.0-stewardship` so the same matrix will run on
ubuntu-latest, macos-latest, and windows-latest.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add recorded mock-trace replay coverage for workflows/rlm_cache_change.star and prove missing dogfood records produce ReplayDiverged instead of live fallback.\n\nVerification:\n- cargo test -p codewhale-whaleflow rlm_cache_change --locked\n- cargo fmt --all --check\n- git diff --check\n- cmp -s CHANGELOG.md crates/tui/CHANGELOG.md\n- ./scripts/release/check-versions.sh\n- ./scripts/release/check-ohos-deps.sh
Harvests provider-scoped TLS skip-verify from #1893 by @wavezhang. Disabled by default, active-provider-only, doctor-reported, and keeps SSL_CERT_FILE as the preferred custom CA path.