Skip to content

Add OpenSpec proposal auto-refresh - #58

Merged
kkaminsk merged 16 commits into
mainfrom
Spec
Nov 3, 2026
Merged

kkaminsk merged 16 commits into
mainfrom
Spec

Conversation

@kkaminsk

@kkaminsk kkaminsk commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the OpenSpec proposal auto-refresh (openspec/changes/auto-refresh/). Proposal only, no implementation.

  • Every refresh_interval seconds (default 60, 0 = off) a worker thread computes a content digest (name, kind, size, modified time, hidden/system flag, link flag, entry count) of each visible panel's directory. An equal digest changes nothing and draws nothing; a different one re-reads the panel in place, keeping cursor, scroll, selection and sort, with no history visit.
  • Checks are issued, and results applied, only while the panels are the active screen with no dialog, menu, drag or type-ahead in progress, and only for a complete, error-free listing in Full or Brief mode. A result arriving after a dialog opened is dropped, so a delete confirmation can never end up targeting a different file. Probe failure is silent.
  • F12 re-reads the active panel exactly as Ctrl+R does. The main F-key bar gains an eleventh slot: … 10Quit 12Refresh (77 cols), … 10Qit 12Rfr (56 cols, fits the 60-column floor), … 10 12 (23 cols). Slot 11 is not drawn.
  • New capability spec auto-refresh (6 requirements). Deltas to responsive-layout, sort-modes, mouse-input, application-shell, panel-navigation, configuration-files.

openspec validate auto-refresh --strict passes with no issues.

Tracking: BIG-651

Test plan

  • Review proposal.md and design.md (decisions D1–D8)
  • Confirm the key-bar form strings and widths in the responsive-layout delta
  • Confirm the eligibility rules in the auto-refresh spec match the intended behaviour

🤖 Generated with Claude Code

kkaminsk and others added 16 commits October 7, 2026 19:38
Decorative ASCII animations for the startup splash (frame trace, identity-line reveal, title sweep inside the 800 ms hold, then a panel wipe), the F9 menu bar and every pop-up menu (sweep, top-down unfold, highlight settle), and every modal dialog (100 ms iris). All motion is render-only interpolation of the reducer's Tick clock against open-time stamps, so core::update stays pure, input is never blocked, and insta snapshots stay deterministic. Disabled via `animations = false` or `--noanimations` (flag wins); no new theme roles, so user theme files keep validating. Supersedes design doc §4.10's no-animation rule for decorative chrome only; loading feedback stays static. Adds the new ui-animations capability and deltas for startup-splash and pulldown-menus.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
After a confirmed delete (and every other same-directory re-read: copy/move/mkdir completion, Ctrl+R, stale-tab refresh) the panel jumps back to the top because Panel::begin_new_listing resets cursor and scroll offset unconditionally. This proposal adds a re-read anchor so the cursor returns to its entry or the nearest survivor (next after a delete, Norton Commander style) and the scroll offset is restored and re-clamped, applied while the listing streams so there is no transient jump. Modifies panel-navigation and file-operations.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Resolve one per-user profile directory (--config-dir flag, portable marker, or %APPDATA%\FileCommand) for config.toml, history.json, and usermenu.toml instead of the launch directory; create it on first run, fail soft with a startup warning, and show a legacy notice for old files in the working directory without migrating them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Render Full-mode Size, Date, and Time values untruncated (9/8/5 cells, sizes right-aligned) by spending the row's slack cells; reserved widths and the column-drop ladder are unchanged so the 80x24 four-column guarantee holds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Introduce a shared LineEdit model (new text-field-editing capability) so every single-line field and the command line get a movable caret, Home/End, word keys, Delete, Ctrl+Backspace, and clipboard paste, with scrolling field rendering; panel key meanings are preserved.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bind Ctrl+Y (rebindable via key.clear_line) to the existing CommandLineClear command over the panels, ending any history recall; Esc keeps requesting quit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Carry the hidden/system attribute on listing entries and render them with a new panel.hidden theme role in Full and Brief modes, with drag > cursor > selected > hidden > file/directory precedence; no show/hide toggle.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Wire the greyed pull-down items that already have backing features (View, Edit, Filter, New/Close tab), add the small missing ones (Alt+F8 history dialog, Ctrl+U swap panels, Menu file edit with reload), and remove Attributes, Compare directories, Configuration, Editor selection, and Save setup.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add an Open entry to the file-action menu (first and highlighted for documents, after Run for executables, Explorer for directories) that launches the target through the platform file association without suspending the TUI and reports failures on the panel status line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
help-flags: the flag is accepted anywhere, not only first. delete-key-triggers-delete: the guard is an exact no-modifier check, not is_plain. delete-builtins-reject-dot-targets: the function is dispatch_delete_builtin. reread-preserves-cursor: exclude the Tree-mode preview caller, restore TabData, handle quick-filter and Brief-mode offsets. ui-animations: --noanimations precedence is applied in run, stamp About and the startup warning, and correct the config and usage wording.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…reject-dot-targets

All three are fully implemented, so their spec deltas are synced into application-shell, panel-tabs, and command-line and the changes move to the archive. delete-key-triggers-delete stays open until its manual check (task 3.3) is done.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The manual Delete-key check (task 3.3) is confirmed done and validation is clean. The spec delta was already present in operation-dialogs, so the archive only moves the change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Resolves the duplicate archive of delete-key-triggers-delete in favour of
main's 2026-10-14 copy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Checks each visible panel's directory every refresh_interval seconds
(default 60, configurable, 0 = off) on a worker thread by comparing a
content digest of its entries with the listing on screen, and re-reads the
panel in place — cursor, scroll, selection, and sort kept, no history
visit — only when the directory actually changed; a no-change check draws
nothing. Adds F12 as a second binding for Ctrl+R's re-read and an eleventh
`12Refresh` slot on the F-key bar (77/56/23-column forms). Deltas touch
responsive-layout, sort-modes, mouse-input, application-shell,
panel-navigation, and configuration-files.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99aca5f528

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- [ ] 3.1 Add `Command::DirectoryProbed { panel, path, request, digest: Option<u64> }` and `Effect::ProbeDirectory { panel, path, request }` in `update/command.rs`.
- [ ] 3.2 Add `State::next_probe_ms` and `PanelState::probe_request`; on `Tick`, when due and `refresh_interval_ms > 0`, issue a probe for each eligible panel (design D3) and advance `next_probe_ms`.
- [ ] 3.3 Extend `anim::next_wake_ms` with the probe deadline (only when enabled and some panel is eligible).
- [ ] 3.4 Extract `reread_in_place(state, side)` in `update/listing.rs` from `refresh_activated_stale_tab`; make the latter call it; update `begin_listing_inner`'s doc comment.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve selection in the auto-refresh helper

Extracting reread_in_place as specified here does not preserve the selection: the existing begin_listing_inner calls PanelState::begin_new_listing, which unconditionally executes self.selected.clear(). No other task captures/restores the selected names or tests the required “Selection survives an automatic refresh” scenario, so any external directory change will silently deselect the user's files. Add explicit same-directory selection preservation followed by reconciliation when the refreshed listing completes.

Useful? React with 👍 / 👎.

## 6. TUI: worker and event loop

- [ ] 6.1 `worker::spawn_probe(panel, path, request, cancel, tx, token)` runs `read_dir_digest` and delivers `DirectoryProbed` (`digest: None` on error); it never delivers after cancellation.
- [ ] 6.2 `app.rs` runs `Effect::ProbeDirectory`; a `DirectoryProbed` that yields no effects does not set the redraw flag (design D5).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Suppress the redraw when a probe is issued

Special-casing only the DirectoryProbed result still leaves one redraw per interval: the current timeout branch sets needs_draw = true after every due Command::Tick, and that tick is what will emit Effect::ProbeDirectory. Thus an unchanged check redraws once when issued even if its result is suppressed, contradicting the new idle-loop scenario and the integration test on the next line. The plan needs to distinguish a probe-only tick from a tick with a visible deadline, or otherwise prevent that issue-side draw.

Useful? React with 👍 / 👎.


- [ ] 2.1 Add `listing::content_digest(entries)` hashing `(name, kind, size, modified, hidden, link)` over entries sorted by name, plus the count; the synthetic `..` is excluded.
- [ ] 2.2 Add `listing::read_dir_digest(reader, path, cancel) -> io::Result<u64>` — a non-streaming enumeration through the same `classify_entry` path, skipping unreadable entries exactly as the listing does.
- [ ] 2.3 `PanelState::content_digest: Option<u64>` — computed at `ListingComplete`, cleared by `begin_new_listing`; tests that identical entry sets in different arrival order digest equally and that a change to any hashed field differs.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Carry digest state through tab switches

Adding content_digest only to PanelState leaves tab switching with the wrong baseline: completed background tabs are restored through the manually enumerated TabData fields in to_tab_data/adopt_tab_data, and they do not start a new listing unless marked stale. Unless this task also adds the digest to TabData (and handles any outstanding probe consistently), activating a completed tab retains the digest/request bookkeeping of the tab just left, causing a spurious re-read or delaying checks for the newly active directory. Include these fields in the tab lifecycle and cover a switch between two completed tabs.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T19:22:40.303479Z 99aca5f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kkaminsk
kkaminsk merged commit 7bcb2c9 into main Nov 3, 2026
2 of 3 checks passed
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.

1 participant