fix(tasks): order board and list reads newest-first, and report the window - #25
Merged
Conversation
…indow task_board and task_list silently omitted recently created tasks. Four tasks created hours earlier were absent from both while task_get returned them in full, so an agent that captured a deferral and read the board back could not see its own write -- which looks like the write failed. The cause is that the limit was applied by CQL with no ordering. The table is PRIMARY KEY (tenant_id, task_id), so rows arrive in task_id order and a LIMIT therefore took an ARBITRARY SLICE rather than the newest rows. With a few hundred open tasks the window stopped including anything recent. CQL cannot fix this with ORDER BY: created_at is not a clustering column, so ordering has to happen after the fetch, which means fetching enough to order meaningfully and applying the caller's limit afterwards. - reads fetch to MAX_FETCH_ROWS, sort newest-first, THEN apply limit/offset; - ties break on task_id, so the order is total and a page boundary cannot return one task twice and another never; - list_tasks_paged reports total and truncated, so a capped read says so. A capped read that reports itself is usable; one that does not is worse than an error. Also fixes a payload size problem that made the board unreadable by a different route: task_board returned 619,574 characters for 382 tasks and exceeded the tool-result token limit outright, so it could not be read without spilling to a file. Rows are now slim by default -- body, result and metadata dropped, summary kept because a one-line summary is what makes a listing decidable. `full: true` restores everything, and task_get was always the way to get detail for the one task you pick. The CLI keeps emitting a plain array on stdout, because `frg task list | jq` depends on it. It gains the ordering fix, and truncation is warned on STDERR so a capped read still says so without breaking the pipe. Verified against a live board: the newest triage rows are now 08-17 14:40, where before the same query returned 08-14 08:19 as its first row.
The Format & Lint gate rejected the previous commit: hand-written code did not match rustfmt. No behaviour change.
Merged
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.
task_boardandtask_listsilently omitted recently created tasks.Four tasks created hours earlier were absent from both, while
task_getreturned them in full — so an agent that captures a deferral and reads the board back cannot see its own write, which looks like the write failed./whats-nextand/roadmapboth depend on the board being the durable record.Cause
The limit was applied by CQL with no ordering. The table is
PRIMARY KEY (tenant_id, task_id), so rows arrive intask_idorder and aLIMITtook an arbitrary slice rather than the newest rows. With a few hundred open tasks the window stopped including anything recent.CQL cannot fix this with
ORDER BY—created_atis not a clustering column. So ordering has to happen after the fetch, which means fetching enough to order meaningfully and applying the caller's limit afterwards.Changes
MAX_FETCH_ROWS, sort newest-first, then apply limit/offset.task_id, so the order is total and a page boundary cannot return one task twice and another never.list_tasks_pagedreportstotalandtruncated. A capped read that reports itself is usable; one that does not is worse than an error.offsetadded totask_listfor paging a long board.Also: the board exceeded the token limit
Separately from the invisibility,
task_boardreturned 619,574 characters for 382 tasks and exceeded the tool-result token limit outright, so it could not be read at all without spilling to a file first.Rows are now slim by default —
body,resultandmetadatadropped,summarykept because a one-line summary is what makes a listing decidable.full: truerestores everything, andtask_getwas always the way to get detail for the task you actually pick.CLI
frg task listkeeps emitting a plain array on stdout, becausefrg task list | jqdepends on it. It gains the ordering fix, and truncation is warned on stderr so a capped read still says so without breaking the pipe.Verification
84 test blocks pass, clippy clean. New tests cover newest-first ordering, tie-breaking on id, and that
slimdrops the bulk while keeping the decidable fields.Verified against a live board — same query, before and after:
Not merging this myself: standing rule is no auto-merge on public repos.