Skip to content

feat: the task tools return compact lists, find a project by name, and say when more remain EXO-91948 - #683

Draft
bmestrallet wants to merge 6 commits into
feat/EXO-91902-tasks-changed-sincefrom
feat/EXO-91948-compact-task-tool-responses
Draft

bmestrallet wants to merge 6 commits into
feat/EXO-91902-tasks-changed-sincefrom
feat/EXO-91948-compact-task-tool-responses

Conversation

@bmestrallet

@bmestrallet bmestrallet commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Why

Task tool answers were far larger than an assistant needs: on the Tribe, list_projects over 427 projects returned ≈ 89k characters and list_tasks for 200 tasks ≈ 457k, so clients cut them without saying so and agents concluded on partial data. Each project carried its allowed statuses and labels (two queries per project); each task its full HTML description, full user profiles for the assignee and every coworker, and two constant strings. limit had no upper bound, and nothing let an assistant find a board by name.

How

  • list_projects takes an optional name: it lists the projects whose name holds all its words, ignoring case (ProjectQuery#setNameWords, AND); only when none does and the name has several words, those holding any one of them (setKeyword, OR). Same in a run limited to a space. Items become {project_id, name, space_id, url}; get_project_by_id keeps the full project. The total is counted with the same ProjectQuery selection as the list, so a project with several managers or participants counts once and has_more is exact.
  • list_tasks, list_assigned_tasks, list_unscheduled_tasks return compact items (task_id, title, link, completed, project_id, project_name, status, labels, assignee{username, display_name}, due_date, created_date, days_overdue, priority, comments_count, plus changes with changed_since/completed_since). The compact path skips HTML rendering, coworker and user-model lookups. include_change_log=true keeps the full shape; get_task_by_id stays full.
  • On request (include_description: true), each compact task item also carries its description as plain text — HTML and entities removed with Jsoup, mentions and links shown as their text, one line per block, cut at 500 characters on a word or line boundary with description_truncated: true when cut — for readers that need a card's qualification lines without one get_task_by_id per task. Without it the item is unchanged and the description is not read.
  • limit is capped at 100 (local MAX_LIMIT), a zero or negative one means 10. Collections carry has_more and next_offset (absent when nothing remains); count and used_limit keep their meaning.
  • list_assigned_tasks takes offset. It now reads getAssignedTasksQuery + findLastUpdatedTasks instead of getUncompletedTasks, which had no offset and no order: same selection (open, assignee or coworker), now most recently active first.
  • list_unscheduled_tasks reports has_more but has no offset (it scans the project's 100 most recently active open tasks).
  • The constant strings list_task_comments_tool / list_allowed_project_labels leave TaskModel (so get_task_by_id too); their content moves to the tool descriptions, which are trimmed to keep the per-call prompt small.

Measured on a local instance (50 projects, 206 tasks)

Call Before After
Find a board: full list_projects traversal vs list_projects name= 31,637 chars 199
list_tasks, 110 tasks 259,740 45,517
list_assigned_tasks, 206 tasks 483,603 87,259
list_tasks title= (filter existed before) 4,740 878

Depends on

Tests

mvn -o test -pl services at 6a0407a3d: 375 tests, 0 failures. They pin the compact shapes (exact JSON key sets, created_date equal to the full task's), the all-words query and its fallback (structure, and run through the engine in TestProjectDAO: count, AND, case, exclusion outside the memberships), a project counted once with several participants, the one-word name without fallback, the clamp, has_more/next_offset on full, last and empty pages, the list_assigned_tasks offset, and the opt-in description (default key set unchanged and the description never read; plain text, line per block, cut at a boundary, surrogate pairs kept whole, flag only when cut); each was mutation-checked.

Classification: N1 proposed — the space-scope allowed_args gain name (list_projects) and include_description (list_tasks), so a run limited to a space may pass a new argument (it only narrows projects already selected by the scope check), and a new DAO query condition (setNameWords). No ACL, getTaskQuery or require_approval change.
Knowledge: Meeds-io/eng-standards#668, Meeds-io/eng-standards#669, Meeds-io/eng-standards#630, Meeds-io/eng-standards#670

🤖 Generated with Claude Code

bmestrallet and others added 3 commits October 22, 2026 10:38
…d say when more remain EXO-91948

list_projects takes a name, a keyword passed to the project list and count
(and to the scan of a space's projects in a run limited to a space), and
lists compact items {project_id, name, space_id, url}; get_project_by_id
keeps the full project. list_tasks, list_assigned_tasks and
list_unscheduled_tasks list compact items: the search result's fields plus
the assignee as {username, display_name}, due_date, days_overdue, priority,
comments_count, and the changes of a changed_since/completed_since listing;
include_change_log and get_task_by_id keep the full task. list_assigned_tasks
takes an offset. Every list tool's limit is 10 by default and 100 at most.
The project and task collections carry has_more and next_offset. The two
constant per-task tool names move to the tool descriptions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…XO-91948

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…asked for comes alone EXO-91948

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bmestrallet and others added 3 commits October 22, 2026 16:36
…name skips the useless fallback EXO-91948

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… a date are found EXO-91948

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…equest EXO-91948

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

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