Offer only unarchived projects, weightiest first, when creating a task - #168
Merged
Merged
Conversation
The project picker listed every project alphabetically, archived ones included. An archived project refuses new work (DESIGN.md §5), so offering it is offering a choice that can only fail — and in the $EDITOR and planning flows it fails only after the operator has written the task out. Alphabetical order also says nothing about which project the work is in; project weight already carries that answer. The filtering and ordering live in voro-core as a pure helper over an already-loaded &[Project], since App refreshes its list every tick and the ordering policy is business logic rather than rendering. Store::projects() keeps its name ordering — the projects screen, the header, and `voro project list` all depend on it. All three create flows route through the helper: new_task branches on the filtered length, so one live project beside archived ones skips the picker, and an all-archived store refuses with a status line pointing at the projects screen instead of raising an empty picker. The key handler and the draw arm index the same filtered list, so sel means the same thing to each, and the mouse path rides Hit::PickerOption into that sel unchanged. Rows carry the weight they sort on, as the projects screen does, and the popup widens to 48 columns to fit it. Verified with cargo test --workspace (unit tests on the helper's filtering and ordering, TUI tests for the direct-create, all-archived and nth-row cases, and a render test that the picker shows weights and omits an archived project), clippy and fmt clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011QKHoB9Afi5zyB4TpqSgQg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The project picker that opens when creating a task listed every project in the store, archived ones included, ordered alphabetically. Both halves were wrong.
Store::create_taskrefuses an archived project (DESIGN.md §5), so offering one is offering a choice that can only fail — and in theEditorandPlanflows it fails late, after the operator has written the task out in$EDITORor sat through a planning session. Alphabetical order also says nothing about which project the operator is working on this week; project weight already carries that answer (§7) and is what they edit every morning.What changed
voro_core::projects_for_new_task(crates/voro-core/src/model.rs) is a pure helper over an already-loaded&[Project]: it drops archived projects and returns the rest weight-descending, name-ascending within a weight. It lives in core because the ordering is business logic, not rendering, and takes a slice rather than issuing a second query becauseApprefreshesself.projectsevery tick.Store::projects()is untouched and keeps its name ordering — the projects screen, the header, andvoro project listall depend on it.All three create flows route through it.
App::creatable_projectswraps the helper, andnew_tasknow branches on the length of the filtered list: one live project beside archived ones goes straight tostart_createon the live one rather than opening a picker, and a store whose every project is archived opens no picker and no longer firesNO_PROJECTS_HINT— it leaves a newALL_PROJECTS_ARCHIVED_HINTstatus line pointing at the projects screen and theAkey that unarchives, in the same no-op-with-an-explanation style as the neighbouring keys.key_pick_projectand theMode::PickProjectdraw arm both index the filtered list, soselmeans the same thing to each; the mouse path needed no change, since clicks route throughHit::PickerOptioninto the samesel. Each picker row carries its weight ahead of the name, as the projects screen does (4 zeta), so weightiest-first reads as an order rather than a shuffle, and the popup widens from 44 to 48 columns to fit it.Parked projects stay on the list — weight 0 is a snooze, not a retirement (§5) — and simply sort last. The cockpit/task-browser gate that fires while no project is registered still counts all projects, archived included, and the CLI is untouched:
voro addnames its project explicitly andcreate_taskalready refuses an archived one.DESIGN.md §9 gains a passage recording that the create keys ask which project only when there is a choice, offer only projects that can take the work, and order them weightiest first — enforcement of §5's existing rule rather than a new one. CHANGELOG has an entry under Unreleased/Changed.
Verification
cargo test --workspace— 849 tests, all passing, including new ones:voro-coreunit tests that archived projects are excluded at any weight and that ordering is weight-then-name with a parked project kept and sorted last;vorotests thatnwith one unarchived project beside three archived ones opens the create modal directly on the live one, thatn/Nwith every project archived open no picker and leave the explanatory status, and that ⏎ on the picker's nth row starts the create flow on the project the filtered order puts there rather than the alphabetical one; and aui.rsrender test that the picker shows weights and omits an archived project's name despite it outweighing every row shown.cargo clippy --workspace --all-targets -- -D warningsandcargo fmt --allclean.