fix(task_list): list all tasks by default and add list_lists action#779
fix(task_list): list all tasks by default and add list_lists action#779penso merged 4 commits intomoltis-org:mainfrom
Conversation
Fixes moltis-org#776 Previously task_list.list defaulted to list_id=default when omitted, hiding tasks in custom lists. Agents had no way to discover or query across all lists. Changes: - Omitting list_id on list action defaults to * (all lists) - Wildcard list_id=* queries across every known list - New list_lists action returns all known list IDs - Schema descriptions updated to document new behavior - 4 new tests. All 8 tests pass.
- Fix list_id schema description: was misleading about omit behavior - list_all_tasks now sorts by (list_id, numeric_id) for stable ordering across lists with independent ID counters
Greptile SummaryThis PR fixes invisible cross-list tasks by changing the default Confidence Score: 5/5Safe to merge; all P0/P1 concerns from prior review rounds are resolved, remaining findings are P2 style issues. The three issues from the previous review threads (missing list_id on wildcard tasks, phantom lists in list_ids, and sort allocation) are addressed. The two new findings are P2: blocking Path::exists() inside an async lock (a latency concern, not a correctness bug at this scale) and the missing legacy-task backfill in the single-list path (the wildcard cross-list path — the primary use case — is correctly handled). Neither blocks merge. crates/tools/src/task_list.rs — list_ids filter and single-list list_tasks return path
|
| Filename | Overview |
|---|---|
| crates/tools/src/task_list.rs | Adds list_ids(), list_all_tasks(), wildcard list_tasks dispatch, list_lists action, and Task.list_id field; 7 new tests cover all new paths. Two minor issues: synchronous Path::exists() called while holding the RwLock read guard, and the single-list list_tasks path doesn't backfill list_id for legacy tasks unlike list_all_tasks. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[execute params] --> B{action?}
B -->|list| C{list_id provided?}
C -->|no / omitted| D[effective_id = '*']
C -->|explicit value| E[effective_id = list_id]
D --> F{list_id == '*'?}
E --> F
F -->|yes| G[list_all_tasks]
F -->|no| H[list_tasks single list]
G --> I[list_ids: scan disk + filter phantoms]
I --> J[read lock: collect + backfill list_id]
J --> K[sort by list_id, numeric_id]
H --> L[ensure_list]
L --> M[read lock: filter + sort]
M --> N[⚠️ list_id not backfilled for legacy tasks]
B -->|list_lists| O[list_ids]
O --> P[return sorted list IDs]
B -->|create| Q[ensure_list + write + persist]
Q --> R[Task with list_id set]
B -->|get / update / claim| S[ensure_list + write lock]
Reviews (2): Last reviewed commit: "fix(task_list): clean up review nits fro..." | Re-trigger Greptile
… description - P1: Task struct gains list_id field, set on create and cross-list queries. Agents can now issue follow-up get/update/claim from wildcard results. - P2: list_ids() filters out phantom in-memory lists (empty, non-persisted). - P2: description() updated to include list_lists action. - 3 new tests: wildcard list_id field, single-list list_id field, phantom list exclusion. 11/11 passing.
- Remove dead skip_serializing_if on Task.list_id (always populated) - Fix misleading doc comment on Task.list_id field - Document eventual-consistency in list_ids()
|
@greptileai review |
Fixes #776
Problem
When
task_list.listwas called without specifyinglist_id, it defaulted to"default". Tasks created under custom list IDs (e.g."CURRICULUM_1") were invisible unless the agent explicitly knew to pass that ID. There was also no way to discover what lists existed.Changes
list_idonlistaction now defaults to"*"(all lists) instead of"default". Explicitly passinglist_id="default"still scopes to that list only.list_id="*"queries across every known list.list_listsaction returns all known list IDs by scanning persisted JSON files, filtering out phantom empty lists.Taskstruct gainslist_idfield — always populated on creation, enabling agents to issue follow-upget/update/claimfrom cross-list query results. Forward-compatible with legacy files via#[serde(default)].TaskStoregainslist_ids()andlist_all_tasks()methods.(list_id, numeric_id)tuple for stable ordering.Testing
7 new tests (11 total), all passing:
list_without_list_id_returns_all_tasks— omit sees all listslist_with_wildcard_returns_all_tasks— explicit*sees all listslist_lists_returns_all_known_ids— discovers list IDsexplicit_default_list_id_still_scopes— explicitdefaultstill scopeswildcard_list_includes_list_id_field— cross-list tasks carrylist_idsingle_list_includes_list_id_field— single-list tasks carrylist_idlist_lists_excludes_phantom_empty_lists— no phantom listsValidation
cargo fmt --check✅cargo clippy -D warnings✅ (onmoltis-tools)cargo test -p moltis-tools --lib task_list✅ 11/11Blast Radius
Single-file change (
crates/tools/src/task_list.rs). No other crate importsTask,TaskList,TaskStore, orTaskStatus. TheTaskListTool::new()constructor signature is unchanged. Persisted JSON is forward-compatible.