Skip to content

List the sessions worked on in a period, on one repo or all - #1226

Merged
alexeyzimarev merged 9 commits into
mainfrom
feat/session-listing-time-window
Sep 29, 2026
Merged

alexeyzimarev merged 9 commits into
mainfrom
feat/session-listing-time-window

Conversation

@alexeyzimarev

Copy link
Copy Markdown
Member

Closes #1222 — AI-3296

What & why

kcap sessions and the list_repo_sessions tool list one repository's sessions, running first, with no way to ask what was worked on last week or across every repository. Both now take --since / --until (an instant, a local date, or a duration such as 14d), --repo all for every repository, and --cursor for the next page, over the server's GET /api/repositories/{hash}/sessions and GET /api/sessions/listing. A windowed listing is ordered by start, newest first, gains a STARTED column, and ends with the command that fetches the next page.

Where to look

A server without the window ignores the parameters and answers an unfiltered list; the command and the tool look for the echoed since / until and refuse to show a result without it. --cursor combines only with --repo, --limit and --json: any other flag beside it is refused by name, because the server ignores filters sent with a cursor. The recap skill's description is condensed to 1007 characters, under the 1024 a strict harness accepts before it silently refuses the skill; a test pins the limit.

The server routes ship in kcap-server AI-3296 (#2129, merged). Release this only after a server carrying them is deployed: against an older server the feature reports itself unusable.

Verification

End-to-end over WireMock: a paged cross-repository listing outside any checkout, and a server that ignores the period reported with nothing listed, for the command and for the tool. Capacitor.Cli.Core.Tests.Unit 3950 passed and Capacitor.Cli.Tests.Integration 384 passed before the last two commits; at head, the listing classes (196 tests across the three hosts) pass, dotnet publish -c Release prints no IL2xxx/IL3xxx warning, and scripts/check-linear-ids.sh exits 0.

🤖 Generated with Claude Code

alexeyzimarev and others added 8 commits September 29, 2026 13:46
A date is read in the zone of the machine that runs the command, at the offset in force at that day's midnight: the server is UTC and cannot know what yesterday means to the caller.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A cursor beside a filter is refused: the server ignores the filter, so the page would look narrowed and not be.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A windowed request answered without the window echoed came from a server that ignored the filter; its rows are not shown, since they would look filtered.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The tool passes the server's JSON through untouched, so a server that ignores the window is caught by reading the body for the echo before it is returned.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The recap skill's description is cut to fit the 1024-character limit a strict harness enforces: past it the skill is refused without a word, and the period triggers would have taken it further over.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The line is what a person pastes in another directory, so it has to carry the repository this run resolved from the checkout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T15:10:21.774039Z e544db5 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-code-review

qodo-code-review Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

PR Summary by Qodo

List sessions by time period across one or all repositories

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add period filters and cross-repository listing to the CLI and MCP tool for finding past work.
• Support cursor pagination while refusing filtered results from servers that ignore the requested
 period.
• Document the workflow and test time parsing, rendering, routing, and older-server behavior.
Diagram

graph TD
  CLI["kcap sessions"] --> Parser["When parser"] --> RepoRoute["Repository route"] --> Response["Listing response"] --> Echo["Window check"] --> Output["CLI or MCP output"]
  MCP["MCP tool"] --> Parser
  CLI --> AllRoute["All-repos route"] --> Response
  MCP --> AllRoute
  MCP --> RepoRoute
Loading
High-Level Assessment

Keep filtering and pagination on the server, with one shared client-side time parser and an echo check in each interface. Client-side filtering was considered but would require retrieving potentially unbounded pages and could not reliably reproduce the server's visibility and window semantics.

Files changed (19) +1230 / -128

Enhancement (6) +437 / -73
Models.csExtend session listing response models +23/-19

Extend session listing response models

• Adds optional repository information to rows and window echoes and a next cursor to pages, while retaining compatibility with older responses.

src/Capacitor.Cli.Core/Models.cs

RepoSessionRepositoryDto.csRepresent a listed session's repository +7/-0

Represent a listed session's repository

• Adds a repository DTO with hash and optional owner and name for cross-repository rows.

src/Capacitor.Cli.Core/RepoSessionRepositoryDto.cs

WhenParser.csResolve written times to UTC instants +123/-0

Resolve written times to UTC instants

• Parses zoned instants, local dates, and durations using the caller's time provider. Handles midnight time-zone transitions and formats values for server requests.

src/Capacitor.Cli.Core/WhenParser.cs

McpSessionsServer.csAdd period, cursor, and all-repository MCP listing +97/-14

Add period, cursor, and all-repository MCP listing

• Routes list_repo_sessions to the appropriate endpoint, validates cursor combinations, and rejects window responses without an echo. Expands the tool schema and description for agents.

src/Capacitor.Cli/Commands/McpSessionsServer.cs

SessionsArgs.csParse and validate new sessions flags +101/-12

Parse and validate new sessions flags

• Accepts --since, --until, --cursor, and --repo all. Defaults windowed listings to every state and rejects filters combined with a cursor.

src/Capacitor.Cli/Commands/SessionsArgs.cs

SessionsCommand.csFetch and render paged period listings +86/-28

Fetch and render paged period listings

• Selects the repository or cross-repository route, checks window echoes before table or JSON output, and displays STARTED and REPO columns when applicable. Prints a command for the next page.

src/Capacitor.Cli/Commands/SessionsCommand.cs

Tests (8) +730 / -34
RepoSessionsModelsTests.csTest new listing response fields +45/-0

Test new listing response fields

• Checks deserialization of window echoes, cursors, and repository identities, including their absence in older responses.

test/Capacitor.Cli.Core.Tests.Unit/RepoSessionsModelsTests.cs

WhenParserTests.csTest time conversion and invalid forms +115/-0

Test time conversion and invalid forms

• Covers UTC instants, local dates and daylight-saving transitions, durations, error messages, and wire formatting.

test/Capacitor.Cli.Core.Tests.Unit/WhenParserTests.cs

McpSessionsServerTests.csExercise MCP listing routes and compatibility +73/-2

Exercise MCP listing routes and compatibility

• Uses WireMock to verify cross-repository period requests and errors when an older server ignores the period or lacks the listing route.

test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs

SessionsCommandTests.csExercise CLI pagination and older-server failures +79/-0

Exercise CLI pagination and older-server failures

• Verifies cross-repository paging outside a checkout and suppression of unfiltered responses in table and JSON modes. Also checks invalid successful responses and missing older-server routes.

test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs

McpSessionsServerTests.csTest MCP URL construction and window safeguards +120/-11

Test MCP URL construction and window safeguards

• Covers route selection, time bounds, defaults, cursor restrictions, and window-echo detection.

test/Capacitor.Cli.Tests.Unit/Commands/McpSessionsServerTests.cs

RecapSkillConformanceTests.csPin recap skill description constraints +38/-0

Pin recap skill description constraints

• Checks that the folded frontmatter description stays within 1024 characters and retains period-question triggers.

test/Capacitor.Cli.Tests.Unit/Commands/RecapSkillConformanceTests.cs

SessionsArgsTests.csTest period and cursor flag validation +126/-9

Test period and cursor flag validation

• Covers all-repository selection, time resolution, state defaults, bound ordering, and named errors for cursor-filter combinations.

test/Capacitor.Cli.Tests.Unit/Commands/SessionsArgsTests.cs

SessionsCommandRenderTests.csTest listing URLs and page presentation +134/-12

Test listing URLs and page presentation

• Checks period and cross-repository columns, repository fallbacks, next-page commands, empty pages, and window-echo rejection.

test/Capacitor.Cli.Tests.Unit/Commands/SessionsCommandRenderTests.cs

Documentation (5) +63 / -21
README.mdDocument period and cross-repository session listing +10/-4

Document period and cross-repository session listing

• Adds CLI examples, accepted time forms, pagination guidance, and the changed list_repo_sessions behavior. Clarifies that cross-repository listing requires an explicit selection.

README.md

README.mdRefresh the MCP session-listing overview +1/-1

Refresh the MCP session-listing overview

• Describes listing sessions across repositories or within a period.

kcap/README.md

SKILL.mdTeach the recap skill period-based discovery +24/-7

Teach the recap skill period-based discovery

• Adds CLI and MCP guidance for questions about work during a period. Condenses the skill description while retaining period-related triggers.

kcap/skills/recap/SKILL.md

help-sessions.txtExplain new sessions flags and period semantics +27/-8

Explain new sessions flags and period semantics

• Documents time bounds, all-repository selection, cursor restrictions, and the distinction between period and default listings.

src/Capacitor.Cli.Core/Resources/help-sessions.txt

help-usage.txtExpose period listing in general CLI help +1/-1

Expose period listing in general CLI help

• Updates the sessions command summary to mention all repositories and time bounds.

src/Capacitor.Cli.Core/Resources/help-usage.txt

@qodo-code-review

qodo-code-review Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Next-page commands can run shell code ✓ Resolved
Description
NextPage inserts the original repository reference and the server-provided cursor into a pasteable
command without shell quoting. If either contains shell metacharacters, a user or agent following
the More: line can execute an additional command.
Code

src/Capacitor.Cli/Commands/SessionsCommand.cs[R178-179]

+    static string NextPage(SessionsOptions options, string repoLabel, string cursor) =>
+        $"kcap sessions --repo {options.Repo ?? repoLabel} --cursor {cursor} --limit {options.Limit}";
Relevance

●●● Strong

Recent precedents accept preserving and safely handling opaque cursors and quoting generated retry
commands.

PR-#1211
PR-#667

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The response cursor is deserialized as an unconstrained string and passed to NextPage; the
original repository reference is also retained after hashing. Repository-reference validation
rejects whitespace but not shell metacharacters, while the recap skill tells agents to run the
printed next-page command.

src/Capacitor.Cli/Commands/SessionsCommand.cs[158-179]
src/Capacitor.Cli.Core/Models.cs[346-354]
src/Capacitor.Cli/Commands/SessionsArgs.cs[56-74]
src/Capacitor.Cli.Core/RepoHashHelper.cs[19-41]
kcap/skills/recap/SKILL.md[86-88]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The printed `More:` command embeds an unquoted repository reference and server-provided cursor, allowing shell syntax in either value to run when the command is followed.
## Fix Focus Areas
- src/Capacitor.Cli/Commands/SessionsCommand.cs[177-179]
- test/Capacitor.Cli.Tests.Unit/Commands/SessionsCommandRenderTests.cs[83-101]
## Recommended Fix
Shell-quote each dynamic argument in the generated command for its intended shell, and test repository references and cursors containing metacharacters.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Invalid page filters go unnoticed ✓ Resolved
Description
Sent uses TextOf to check filters beside a cursor, so it treats a present non-string filter as
absent and lets BuildRepoSessionsUrl return the cursor-only URL. When an agent supplies a cursor
with an invalid filter such as {"owner":42}, the tool returns a page instead of reporting that the
argument was discarded.
Code

src/Capacitor.Cli/Commands/McpSessionsServer.cs[R447-448]

+    static bool Sent(JsonObject? args, string key) =>
+        key == "offset" ? TryReadInt(args, key, out var offset) && offset != 0 : TextOf(args, key) is not null;
Relevance

●●● Strong

Accepted precedent favors defensive validation of non-string MCP arguments before request
construction.

PR-#284

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The cursor branch returns before the ordinary filter readers validate their types. Sent recognizes
only nonblank string values through TextOf, so a non-string owner or since is neither rejected
nor included in the request.

src/Capacitor.Cli/Commands/McpSessionsServer.cs[350-350]
src/Capacitor.Cli/Commands/McpSessionsServer.cs[393-409]
src/Capacitor.Cli/Commands/McpSessionsServer.cs[443-448]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The MCP cursor branch silently discards filters whose JSON values are not strings, rather than rejecting arguments the server will not apply.
## Fix Focus Areas
- src/Capacitor.Cli/Commands/McpSessionsServer.cs[393-400]
- src/Capacitor.Cli/Commands/McpSessionsServer.cs[443-448]
- test/Capacitor.Cli.Tests.Unit/Commands/McpSessionsServerTests.cs[133-153]
## Recommended Fix
Check whether each cursor-incompatible argument is present before treating its value as a blank default; reject non-string values by name and add tests for malformed filters.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. New command tests bypass process limits ✗ Dismissed
Description
SessionsCommandTests adds calls to RunAsync() without a class-level
[ParallelLimiter<SubprocessLimit>] attribute. That helper launches the built command with
Process.Start, so the added tests can run outside the shared subprocess limit.
Code

test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs[82]

+        var json = await RunAsync(repo.Path, "sessions", "--json");
Relevance

●●● Strong

The same subprocess-limit rule applies directly to this integration test class and its Process.Start
helper.

PR-#480

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The newly added invocation reaches a real process spawn, and the containing class has no limiter
required by checklist item 2808212.

Rule 2808212: Use ParallelLimiter<SubprocessLimit> for test classes that spawn real subprocesses
test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs[12-12]
test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs[22-34]
test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs[82-82]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New command integration tests start real subprocesses without participating in the shared subprocess limit.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs[12-12]
- test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs[82-82]

## Recommended Fix
Add `[ParallelLimiter<SubprocessLimit>]` to the test class.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. New tool tests bypass process limits ✗ Dismissed
Description
McpSessionsServerTests adds calls to SpawnMcpServer() without a class-level
[ParallelLimiter<SubprocessLimit>] attribute. Each call starts a real child process through
Process.Start, so the new tests can run outside the shared subprocess limit.
Code

test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[266]

+        using var proc = SpawnMcpServer();
Relevance

●●● Strong

Integration tests spawning real processes are reviewed for subprocess safety and shared
test-resource controls.

PR-#480

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed test invokes a helper that starts a real process, while its test class has no subprocess
limiter, contrary to checklist item 2808212.

Rule 2808212: Use ParallelLimiter<SubprocessLimit> for test classes that spawn real subprocesses
test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[15-15]
test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[43-53]
test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[266-266]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New MCP integration tests start real subprocesses without participating in the shared subprocess limit.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[15-15]
- test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs[266-266]

## Recommended Fix
Add `[ParallelLimiter<SubprocessLimit>]` to the test class.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: 5ca568a0) — View relationship
  Explored: repo: kurrent-io/kcap-deployments (sha: fb899a59) — View relationship
Review mode: 🧠 Deep: This is a substantial, behavior-heavy feature spanning CLI parsing/rendering, MCP/API contracts, time-zone handling, pagination, compatibility behavior, and many independent code paths where redundant review could catch subtle defects.

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread test/Capacitor.Cli.Tests.Integration/McpSessionsServerTests.cs
Comment thread test/Capacitor.Cli.Tests.Integration/SessionsCommandTests.cs
Comment thread src/Capacitor.Cli/Commands/SessionsCommand.cs Outdated
Comment thread src/Capacitor.Cli/Commands/McpSessionsServer.cs Outdated
The line is pasted into a shell, and the cursor in it comes from the server.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@alexeyzimarev
alexeyzimarev merged commit 809be62 into main Sep 29, 2026
8 checks passed
@alexeyzimarev
alexeyzimarev deleted the feat/session-listing-time-window branch September 29, 2026 16:14
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.

List the sessions worked on in a period, on one repo or all

1 participant