Repository navigation
Add read-only desk tools for agents - #2594
Merged
Merged
Conversation
This was referenced Oct 19, 2026
pournasserian
added a commit
that referenced
this pull request
Oct 19, 2026
…ts they see their own sets (#2648) Closes #2625 ## What Follow-ups from the independent review of #2594 (F-DSK, #2422). No scoping leak was found; these close the test gaps and tighten what agents are told. - **Tool descriptions.** `get_desk_counts`, `list_desk_queue` and `get_change_set_review` say an agent sees only the change sets it opened, so a count of 0 doesn't read as an empty desk. - **`get_change_set_review`** reads the set and its moves again when the last move disagrees with the set's state, up to three times. A decision that commits between the two reads no longer gives an answer that disagrees with itself. - **`ChangeSetMoves.StateAfter`** names the state each move leaves a set in. The review tool uses it, and a test ties it to the directory. - **`ConnectedAgent.AnotherAgentAsync`** connects a second agent to the same host for tests. ## Why - **Read again rather than derive the state from the moves.** The rejection reason lives on the set, not in the move event, so only a fresh read of both gives a consistent answer. ## Tests On SQLite and PostgreSQL: - **Another agent's sets** are not counted, listed or readable over MCP, while that agent sees its own. This exercises the credential-id half of the `OpenedBy` filter. - **Every queue through `list_desk_queue`:** - `recently_published` lists newest first and leaves out a set published eight days earlier. - `reverted` lists the reverted set. - `stale_facts` pages two and then one of three, with the total on both pages. - The counts match. - **No tool call appends an event,** `get_change_set_review` included. - **Every move the directory makes** appends exactly one known move, and `StateAfter` names the state the move left. The set goes through: - open, submit, checks failed, reopen, submit and awaiting review; - approve and publish; - a published revert, which reverts the original; - a rejection. All nine move names are seen. `dotnet build -warnaserror`, the unit and bUnit suite and the desk, desk tools and queue tests on SQLite and PostgreSQL pass locally. No new package and no new project reference. ## Checklist - [x] Linked to an issue a maintainer has confirmed - [x] Targets `v2` - [x] Tests or docs updated where behaviour changed - [x] No tool-generated co-author trailers or footers
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.
Closes #2591
What
The sixth slice of F-DSK (#2422): read-only desk tools for agents (MCP-01, "DSK (read-only for review decisions)"), on the tool conventions from #2508. It fills the DSK row of
McpCoverageTests.DeskTools(FluentCMS.Core.Builtin.Tools), three read-only tools:get_desk_counts: how many items wait in each queue.list_desk_queue: one page of a queue, ordered as the desk orders it.awaiting_review,checks_failed,stale_facts,recently_publishedandreverted. Awaiting me is a person's queue, so it is not offered.pageandlimitare optional (1 to 200, 50 by default), and the result has the total.list_stale_factsshows it.get_change_set_review: the state and since when, the rejection reason, the set it reverts, and every move in order with who made it and when.argument_invalid. An unknown set ischange_set_not_foundwith a hint.CheckChangeSetReadAsync).ChangeSetListQuerygainsOpenedBy, whichChangeSetListsfilters on.DeskQueuessets it when the caller is an agent, so an agent's queues and counts hold its own sets. A person's view is unchanged.get_change_set_reviewreads throughGetAsync, so another party's set is refused withagent_not_change_set_owner.ChangeSetMoves(FluentCMS.Core.ChangeSets) names the open and move operations once.ChangeSetLists, the set view and the review tool used to keep their own copies.DeskToolsConformanceTests, and the DSK rows ofMcpCoverageTestsin place of the missing one.Why
DeskQueues, not in each tool. The queues are defined once for the desk and the tools. Applying the read rule where the queries are built keeps the counts and lists consistent, and a later tool cannot forget it. The rule itself stays inAgentPermissions. The list only follows it, asGetAsyncdoes.get_change_set_reviewnext toget_change_set.get_change_setreturns the set's content. The review status is the decisions: who moved it, when, and why it was rejected. An agent needs that to follow up on a rejection.Tests
Unit:
DeskQueuesTests: an agent's lists and counts carryOpenedByas the agent, and a person's carry none.ToolProviderConformanceTestsforDeskTools, andMcpCoverageTestswith the new rows.Integration over MCP, each on SQLite and PostgreSQL:
stateSinceat the rejection. Another party's set is refused withagent_not_change_set_owner.awaiting_me), a limit of 500, a page of 0 and an unknown set are refused, the last with a hint.DeskQueueTestsnow reads the queues as a person, since the scenario's default caller is an agent.McpAgents.BuiltInToolslists the three new tools.dotnet build -warnaserror, the full suite with the browser tests, and markdownlint pass locally against apostgres:17container as well as SQLite. No new package and no new project reference.Checklist
v2