From 66a34cf2a902186bad24e181890cd489aab8b5e9 Mon Sep 17 00:00:00 2001 From: Craig Carlyle Date: Mon, 19 Oct 2026 15:25:38 -0700 Subject: [PATCH] fix(thread): show how many comments a view leaves out thread view stops at 50 comments by default, and its header only counted what came back, so a 68-comment thread read as "50 comments". The header now says "50 of 68 comments" and points at --limit. With --since or --until the thread's total doesn't apply, so it says when the limit was reached instead. The search and mentions help now also says that --since and --until filter by when content was posted. Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/SPEC.md | 4 +- skills/comms-cli/SKILL.md | 8 ++-- src/commands/thread/thread.test.ts | 68 ++++++++++++++++++++++++++++++ src/commands/thread/view.ts | 28 +++++++++++- src/lib/search-helpers.ts | 4 +- src/lib/skills/content.ts | 8 ++-- 6 files changed, 109 insertions(+), 11 deletions(-) diff --git a/docs/SPEC.md b/docs/SPEC.md index 8d23d1a..2a17297 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -345,8 +345,8 @@ Options: - `--channel ` - Filter by channels (comma-separated IDs) - `--author ` - Filter by author (comma-separated IDs) - `--mention-me` - Only results mentioning current user -- `--since ` - Content from date -- `--until ` - Content until date +- `--since ` - Content posted since date +- `--until ` - Content posted until date - `--limit ` - Max results (default: 50) - `--cursor ` - Pagination cursor - `--json` / `--ndjson` - Machine-readable output diff --git a/skills/comms-cli/SKILL.md b/skills/comms-cli/SKILL.md index 849fe78..f02eeed 100644 --- a/skills/comms-cli/SKILL.md +++ b/skills/comms-cli/SKILL.md @@ -93,7 +93,7 @@ tdc thread view --comment # View a specific comment tdc thread view # Comment ID extracted from URL tdc thread view --unread # Show only unread comments tdc thread view --context 3 # Include 3 read comments before unread -tdc thread view --limit 20 # Limit number of comments +tdc thread view --limit 20 # Max comments to show (default: 50; the header says when it left some out) tdc thread view --since # Comments newer than date tdc thread view --raw # Show raw markdown tdc thread create "Title" "content" # Create a new thread @@ -235,14 +235,16 @@ tdc search "query" --to # Messages sent to user tdc search "query" --title-only # Search thread titles only tdc search "query" --mention-me # Results mentioning current user tdc search "query" --conversation # Limit to conversations (comma-separated refs) -tdc search "query" --since # Content from date -tdc search "query" --until # Content until date +tdc search "query" --since # Content posted since date +tdc search "query" --until # Content posted until date tdc search "query" --channel # Filter by channel refs (comma-separated) tdc search "query" --limit # Max results (default: 50) tdc search "query" --cursor # Pagination cursor tdc search "query" --all # Fetch all result pages ``` +`--since` and `--until` filter by when the matching content was posted, not when a thread was last active, so a thread found by its title (`--title-only`) counts from when it was created. + ## Users, Channels & Groups ```bash diff --git a/src/commands/thread/thread.test.ts b/src/commands/thread/thread.test.ts index fb65919..8de0b3f 100644 --- a/src/commands/thread/thread.test.ts +++ b/src/commands/thread/thread.test.ts @@ -725,6 +725,74 @@ describe('thread view date filters', () => { }) }) +describe('thread view comment count header', () => { + beforeEach(() => { + clearWorkspaceUserCache() + vi.clearAllMocks() + configMocks.getConfig.mockResolvedValue({}) + groupsMock.getWorkspaceGroups.mockResolvedValue([]) + groupsMock.getWorkspaceUsers.mockResolvedValue([]) + }) + + const users = { 1: { id: 1, fullName: 'Alice' }, 2: { id: 2, fullName: 'Bob' } } + + async function viewOutput(client: ReturnType, args: string[]) { + apiMocks.getCommsClient.mockResolvedValue(client) + const program = createProgram() + const consoleSpy = captureConsole('log') + await program.parseAsync(['node', 'tdc', 'thread', 'view', '500', ...args]) + return consoleSpy.mock.calls.map((c) => c[0]).join('\n') + } + + it('shows the plain count when every comment came back', async () => { + const client = createClient({ + comments: [createComment(1, 1), createComment(2, 2), createComment(3, 3)], + users, + }) + + const output = await viewOutput(client, []) + + expect(output).toContain('--- 3 comments ---') + }) + + it('says how many comments the limit left out', async () => { + const client = createClient({ + thread: { ...createThreadFixture(500), commentCount: 68 }, + comments: [createComment(1, 1), createComment(2, 2)], + users, + }) + + const output = await viewOutput(client, ['--limit', '2']) + + expect(output).toContain('--- 2 of 68 comments (use --limit for more) ---') + }) + + it('says when a date-filtered view reached the limit', async () => { + const client = createClient({ + thread: { ...createThreadFixture(500), commentCount: 68 }, + comments: [createComment(1, 1), createComment(2, 2)], + users, + }) + + const output = await viewOutput(client, ['--since', '2026-01-01', '--limit', '2']) + + expect(output).toContain('--- 2 comments (limit reached, use --limit for more) ---') + expect(output).not.toContain('of 68') + }) + + it('shows the plain count for a date-filtered view under the limit', async () => { + const client = createClient({ + thread: { ...createThreadFixture(500), commentCount: 68 }, + comments: [createComment(1, 1), createComment(2, 2)], + users, + }) + + const output = await viewOutput(client, ['--since', '2026-01-01']) + + expect(output).toContain('--- 2 comments ---') + }) +}) + describe('thread view error propagation', () => { beforeEach(() => { clearWorkspaceUserCache() diff --git a/src/commands/thread/view.ts b/src/commands/thread/view.ts index d906d84..f677198 100644 --- a/src/commands/thread/view.ts +++ b/src/commands/thread/view.ts @@ -15,6 +15,24 @@ type ViewOptions = PaginatedViewOptions & { context?: string } +// getComments stops at the limit, so say when that left comments out. A date filter makes the +// thread's own count meaningless, so all that's left to report then is hitting the limit. +function formatCommentsHeader( + shown: number, + total: number, + limit: number, + isDateFiltered: boolean, +): string { + const label = `${shown} ${pluralize(shown, 'comment')}` + if (!isDateFiltered && total > shown) { + return `--- ${shown} of ${total} comments (use --limit for more) ---` + } + if (isDateFiltered && shown >= limit) { + return `--- ${label} (limit reached, use --limit for more) ---` + } + return `--- ${label} ---` +} + async function viewSingleComment( client: CommsApi, threadId: string, @@ -200,8 +218,16 @@ export async function viewThread(ref: string, options: ViewOptions): Promise 0) { + const isDateFiltered = options.since !== undefined || options.until !== undefined console.log( - chalk.dim(`--- ${comments.length} ${pluralize(comments.length, 'comment')} ---`), + chalk.dim( + formatCommentsHeader( + comments.length, + thread.commentCount, + limit, + isDateFiltered, + ), + ), ) console.log('') diff --git a/src/lib/search-helpers.ts b/src/lib/search-helpers.ts index 3b32728..1fd2649 100644 --- a/src/lib/search-helpers.ts +++ b/src/lib/search-helpers.ts @@ -88,8 +88,8 @@ export function addSharedSearchOptions( return command .option('--conversation ', 'Limit to conversations (comma-separated refs)') - .option('--since ', 'Content from date') - .option('--until ', 'Content until date') + .option('--since ', 'Content posted since date') + .option('--until ', 'Content posted until date') .option('--limit ', limitDescription) .option('--cursor ', 'Pagination cursor') .option('--all', 'Fetch all pages of results') diff --git a/src/lib/skills/content.ts b/src/lib/skills/content.ts index d48010a..3c7590d 100644 --- a/src/lib/skills/content.ts +++ b/src/lib/skills/content.ts @@ -97,7 +97,7 @@ tdc thread view --comment # View a specific comment tdc thread view # Comment ID extracted from URL tdc thread view --unread # Show only unread comments tdc thread view --context 3 # Include 3 read comments before unread -tdc thread view --limit 20 # Limit number of comments +tdc thread view --limit 20 # Max comments to show (default: 50; the header says when it left some out) tdc thread view --since # Comments newer than date tdc thread view --raw # Show raw markdown tdc thread create "Title" "content" # Create a new thread @@ -239,14 +239,16 @@ tdc search "query" --to # Messages sent to user tdc search "query" --title-only # Search thread titles only tdc search "query" --mention-me # Results mentioning current user tdc search "query" --conversation # Limit to conversations (comma-separated refs) -tdc search "query" --since # Content from date -tdc search "query" --until # Content until date +tdc search "query" --since # Content posted since date +tdc search "query" --until # Content posted until date tdc search "query" --channel # Filter by channel refs (comma-separated) tdc search "query" --limit # Max results (default: 50) tdc search "query" --cursor # Pagination cursor tdc search "query" --all # Fetch all result pages \`\`\` +\`--since\` and \`--until\` filter by when the matching content was posted, not when a thread was last active, so a thread found by its title (\`--title-only\`) counts from when it was created. + ## Users, Channels & Groups \`\`\`bash