Repository navigation
Let agents read the next-work feed from the CLI - #1178
Conversation
A copy of the server's sanitiser: rows from an older or other server may not have been through it, and nothing inside the block may close it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repository is resolved only when this tool is called, so the other work-items tools still start with no git probe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The capability rides the live post only; a spooled replay must not make the server run the feed for rows nobody renders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A proxy or error page can put arbitrary text in a non-2xx body; the sibling tools still echo theirs verbatim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-next-work # Conflicts: # src/Capacitor.Cli/Commands/McpWorkItemsServer.cs
PR Summary by QodoExpose ranked next work through MCP and SessionStart
AI Description
Diagram
High-Level Assessment
Files changed (16)
|
Code Review by Qodo
1.
|
The server runs the feed before acking, so the capability is sent only when the time left, less a reserve for the POST itself, fits at least the server's default feed budget; a server that predates next_work_budget_ms spends that default anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under NativeAOT a string assigned into a JsonObject throws, and the catch around the capability block would silently drop every capability. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The body is read from the stream at headers-read time, so an oversized reply is refused without being buffered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The line sits outside the data block, so a timestamp, arm, state or code that fails to parse is dropped rather than sanitised and shown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Any other body text is server or proxy prose that would reach the agent outside the data block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its guidance tells the agent to call declare_loose_end and get_next_work, so without the server the feed is neither requested nor rendered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/agentic_review |
| if (!nextWorkDisabled && NextWorkEmitter.FeedBudgetMs(budget.Remaining) is { } feedBudgetMs) { | ||
| node["next_work"] = AotJsonString(NextWorkEmitter.CapabilityVersion); | ||
| node["next_work_budget_ms"] = feedBudgetMs; |
There was a problem hiding this comment.
9. Configured feeds outlast session starts 🔗 Cross-repo conflict ☼ Reliability
ClaudeHookCommand sends next_work_budget_ms, but kcap-server's SessionStartHook has no matching field and its handler always uses the configured SessionStartBudgetMs. When that server setting exceeds the CLI's remaining advertised budget, the feed can consume the POST deadline, so the live session-start response may arrive too late to render.
Agent Prompt
## Issue description
The CLI sends a per-request `next_work_budget_ms`, but the pinned kcap-server request model ignores it and uses only its independently configurable session-start budget. A server configured above the CLI's available time can therefore overrun the live hook deadline.
## Fix Focus Areas
- src/Capacitor.Cli/Commands/Harness/ClaudeHookCommand.cs[697-699]
- /cross_repos/kcap-server/src/Capacitor.Api.Public.Abstractions/Hooks/SessionStartHook.cs[66-70]
- /cross_repos/kcap-server/src/Capacitor.Server/Hooks/SessionHookHandlers.cs[463-467]
## Recommended Fix
Add an optional `next_work_budget_ms` field to the server request contract, validate and clamp it, and run the feed with the minimum of that request budget and `SessionStartBudgetMs`. Coordinate deployment so the server understands the field before the CLI relies on it; otherwise withhold the capability unless the remaining deadline can accommodate the server's maximum supported configured budget.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Addressed on the server side in kurrent-io/kcap-server#2070: SessionStartHook gains next_work_budget_ms and the handler spends the smaller of it and NextWork:SessionStartBudgetMs, skipping the feed below the 200 ms floor. Until that server ships, this CLI advertises next_work only when the remaining time covers the server's 1500 ms default plus the POST reserve, so a server at its default budget cannot outlast the deadline either way.
In .NET `$` also matches before a final newline, which let a code or arm name carry a newline outside the data block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Code review by qodo was updated up to the latest commit da87247 |
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit a5bf022 |
A headers-read request is otherwise unbounded while the body trickles in, and the stdio loop serves one call at a time, so a stalled body would hang every later tool call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The memory-index setup runs between the two reads, so an earlier read could promise the server more time than the POST would wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entries are deduplicated by arm and limited in number, and trailing ones are dropped until the line fits its length cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
On the one summary-only finding without an inline thread, "New vendor logic sits in wrong folder": declining. ClaudeHookCommand already lives under Commands/Harness, alongside every other harness hook command; this PR edits that existing file rather than adding vendor code in a new place. Moving the Claude hook command under Harness/Claude is a relocation of pre-existing code and belongs in its own change, not in this feature PR. |
|
/agentic_review |
| /// <summary>The feed has eight arms; room for all of them and no more.</summary> | ||
| internal const int MaxArmEntries = 10; |
There was a problem hiding this comment.
5. Arm limit comment states wrong count 📘 Rule violation ⚙ Maintainability
MaxArmEntries is set to 10 while its new summary says the feed has eight arms and allows “no more.” A later change can rely on the stated eight-entry invariant even though nine or ten distinct arms are deliberately accepted and rendered.
Agent Prompt
## Issue description
The summary for `MaxArmEntries` claims that only eight arm entries are allowed, but the constant permits ten, leaving maintainers with conflicting guidance.
## Fix Focus Areas
- src/Capacitor.Cli/NextWorkEmitter.cs[40-41]
## Recommended Fix
Remove the redundant summary, or rewrite it to explain the actual non-obvious reason the limit is ten without claiming that eight is the maximum.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
Code review by qodo was updated up to the latest commit c67a629 |
Closes #1177 — AI-3142
What & why
Agents cannot see the user's next-work feed from the CLI. This adds a
get_next_worktool tokcap mcp workitemsover the server'sGET /api/next-work, and a SessionStart emitter that renders page one from the ack'snext_workfield, with guidance to finish listed work first and declare loose ends at the moment of deferral. The CLI advertisesnext_work: "v1"so the server only runs the feed for a client that renders it;disable_nextwork_nudgeopts out of both.Where to look
Every server-supplied string is untrusted: label, because, href, evidence, arm states and error bodies go through one sanitiser and sit inside a single
<next-work-data>block, with the imperative guidance outside it. The capability goes on the live post body only, never the spooled one, because a replay renders nothing.Verification
Hostile labels, hrefs and freshness strings containing newlines, control characters and a literal closing tag render on one line inside the block with exactly one open and one close tag; removing the sanitiser from the freshness line fails its test. A 500 spools a body without the capability while the live post carried it. A release publish ran with no AOT warnings, and the published binary against a stub server listed the tool and rendered a hostile row safely.
🤖 Generated with Claude Code