Skip to content

feat: sort briefs by updated at#1409

Merged
Crunchyman-ralph merged 3 commits intonextfrom
ralph/feat/sort.briefs.by.updated.at
Nov 15, 2025
Merged

feat: sort briefs by updated at#1409
Crunchyman-ralph merged 3 commits intonextfrom
ralph/feat/sort.briefs.by.updated.at

Conversation

@Crunchyman-ralph
Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph commented Nov 14, 2025

What type of PR is this?

  • 🐛 Bug fix
  • ✨ Feature
  • 🔌 Integration
  • 📝 Docs
  • 🧹 Refactor
  • Other:

Description

Related Issues

How to Test This

# Example commands or steps

Expected result:

Contributor Checklist

  • Created changeset: npm run changeset
  • Tests pass: npm test
  • Format check passes: npm run format-check (or npm run format to fix)
  • Addressed CodeRabbit comments (if any)
  • Linked related issues (if any)
  • Manually tested the changes

Changelog Entry


For Maintainers

  • PR title follows conventional commits
  • Target branch correct
  • Labels added
  • Milestone assigned (if applicable)

Summary by CodeRabbit

  • New Features
    • Brief selection now shows a human-friendly relative timestamp (e.g., "2 hours ago") next to each brief name so you can see when items were last updated.
    • Briefs in the interactive selection are automatically ordered by last update (most recent first), making it easier to find recently modified items.

@changeset-bot
Copy link

changeset-bot bot commented Nov 14, 2025

⚠️ No Changeset found

Latest commit: 7342f7d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

Walkthrough

Adds a relative-time utility and exports it from tm-core, displays briefs' updatedAt as human-friendly relative strings in the CLI, orders briefs by updated_at in the DB query, and adds date-fns as a dependency in root and tm-core.

Changes

Cohort / File(s) Summary
Time Utility
packages/tm-core/src/utils/time.utils.ts
New `formatRelativeTime(date: string
Core Exports
packages/tm-core/src/index.ts
Added export * from './utils/time.utils.js' to public exports.
Dependencies
package.json, packages/tm-core/package.json
Added runtime dependency date-fns ^4.1.0 to both root and tm-core package.json files.
CLI brief display
apps/cli/src/utils/brief-selection.ts
Imported formatRelativeTime and updated interactive/grouped brief labels to compute and append updatedAtDisplay when brief.updatedAt exists; adjusted some imports to type-only.
DB ordering
packages/tm-core/src/modules/auth/services/organization.service.ts
Converted SupabaseClient/Database imports to type-only and added order('updated_at', { ascending: false }) to getBriefs after filtering by account_id.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor CLI
  participant TMCore as tm-core (org service)
  participant DB as Supabase
  participant Utils as formatRelativeTime
  participant UI as CLI UI

  CLI->>TMCore: request briefs (getBriefs)
  TMCore->>DB: query briefs (filter by account_id, order by updated_at desc)
  DB-->>TMCore: briefs list
  TMCore-->>CLI: briefs list
  CLI->>Utils: formatRelativeTime(brief.updatedAt) [per brief with updatedAt]
  Utils-->>CLI: "2 hours ago" (relative string)
  CLI->>UI: render brief list (name + updatedAtDisplay)
  UI-->>CLI: rendered output
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Files with most review value:
    • apps/cli/src/utils/brief-selection.ts — ensure UI string formatting and type imports are correct.
    • packages/tm-core/src/modules/auth/services/organization.service.ts — verify DB ordering placement and query behavior.
    • packages/tm-core/src/utils/time.utils.ts — small utility correctness and timezone handling.

Possibly related PRs

Suggested reviewers

  • eyaltoledano

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: sort briefs by updated at' accurately describes the main change: sorting briefs by their updated_at timestamp, which is reflected across multiple files where ordering and time display functionality were added.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ralph/feat/sort.briefs.by.updated.at

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/tm-core/src/utils/time.utils.ts (1)

13-18: Consider handling invalid dates gracefully.

The function converts strings to Date objects without validation. While formatDistanceToNow can handle invalid dates, it may not produce user-friendly output for malformed date strings.

Consider adding validation:

 export function formatRelativeTime(date: string | Date): string {
 	const dateObj = typeof date === 'string' ? new Date(date) : date;
+	
+	// Handle invalid dates gracefully
+	if (isNaN(dateObj.getTime())) {
+		return 'unknown';
+	}
 
 	// Use date-fns for robust formatting with proper edge case handling
 	return formatDistanceToNow(dateObj, { addSuffix: true });
 }
apps/cli/src/utils/brief-selection.ts (1)

126-129: TEMP comments suggest work in progress.

The "TEMP: Show updatedAt for verification" comments on lines 126 and 167 indicate this feature may still be under testing. Ensure you remove these comments before merging if the feature is finalized.

Additionally, this exact code block appears twice (lines 126-129 and 167-170). Consider extracting it to avoid duplication:

// Near the top of the function or as a helper
const getUpdatedAtDisplay = (updatedAt?: string) => 
	updatedAt ? chalk.gray(` • ${formatRelativeTime(updatedAt)}`) : '';

// Then use it in both places:
const updatedAtDisplay = getUpdatedAtDisplay(brief.updatedAt);

Also applies to: 167-170

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10ec025 and f3077bf.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • apps/cli/src/utils/brief-selection.ts (3 hunks)
  • package.json (1 hunks)
  • packages/tm-core/package.json (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/organization.service.ts (2 hunks)
  • packages/tm-core/src/utils/time.utils.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1069
File: .changeset/fix-tag-complexity-detection.md:0-0
Timestamp: 2025-08-02T15:33:22.656Z
Learning: For changeset files (.changeset/*.md), Crunchyman-ralph prefers to ignore formatting nitpicks about blank lines between frontmatter and descriptions, as he doesn't mind having them and wants to avoid such comments in future reviews.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1132
File: .github/workflows/weekly-metrics-discord.yml:81-93
Timestamp: 2025-08-13T22:10:46.958Z
Learning: Crunchyman-ralph ignores YAML formatting nitpicks about trailing spaces when there's no project-specific YAML formatter configured, preferring to focus on functionality over cosmetic formatting issues.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1132
File: .github/workflows/weekly-metrics-discord.yml:81-93
Timestamp: 2025-08-13T22:10:46.958Z
Learning: Crunchyman-ralph ignores YAML formatting nitpicks about trailing spaces when there's no project-specific YAML formatter configured, preferring to focus on functionality over cosmetic formatting issues.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1105
File: scripts/modules/supported-models.json:242-254
Timestamp: 2025-08-08T11:33:15.297Z
Learning: Preference: In scripts/modules/supported-models.json, the "name" field is optional. For OpenAI entries (e.g., "gpt-5"), Crunchyman-ralph prefers omitting "name" when the id is explicit enough; avoid nitpicks requesting a "name" in such cases.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1200
File: src/ai-providers/custom-sdk/grok-cli/language-model.js:96-100
Timestamp: 2025-09-19T16:06:42.182Z
Learning: The user Crunchyman-ralph prefers to keep environment variable names explicit (like GROK_CLI_API_KEY) rather than supporting multiple aliases, to avoid overlap and ensure clear separation between different CLI implementations.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/subpath-exports.test.ts:6-9
Timestamp: 2025-09-03T12:45:30.724Z
Learning: The user Crunchyman-ralph prefers to avoid overly nitpicky or detailed suggestions in code reviews, especially for test coverage of minor import paths. Focus on more substantial issues rather than comprehensive coverage of all possible edge cases.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1217
File: apps/cli/src/index.ts:16-21
Timestamp: 2025-09-18T16:35:35.147Z
Learning: The user Crunchyman-ralph considers suggestions to export types for better ergonomics (like exporting UpdateInfo type alongside related functions) as nitpicky and prefers not to implement such suggestions.
📚 Learning: 2025-09-26T19:03:33.225Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1252
File: package.json:130-132
Timestamp: 2025-09-26T19:03:33.225Z
Learning: In the eyaltoledano/claude-task-master repository, packages are bundled using tsdown during the build process, which means dependencies imported by the source code (including tm internal packages like tm/ai-sdk-provider-grok-cli) are included in the final bundle and don't need to be available as separate runtime dependencies, so they should remain as devDependencies rather than being moved to dependencies.

Applied to files:

  • package.json
  • packages/tm-core/package.json
📚 Learning: 2025-09-26T19:07:10.485Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1252
File: packages/ai-sdk-provider-grok-cli/package.json:21-35
Timestamp: 2025-09-26T19:07:10.485Z
Learning: In the eyaltoledano/claude-task-master repository, the tsdown build configuration uses `noExternal: [/^tm\//]` which means internal tm/ packages are bundled into the final output while external npm dependencies remain external and are resolved from the root package.json dependencies at runtime. This eliminates the need for peer dependencies in internal packages since the root package.json already provides the required external dependencies.

Applied to files:

  • packages/tm-core/package.json
📚 Learning: 2025-10-08T19:57:00.982Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.

Applied to files:

  • packages/tm-core/package.json
  • packages/tm-core/src/index.ts
📚 Learning: 2025-09-22T19:45:04.337Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1232
File: packages/tm-core/package.json:50-51
Timestamp: 2025-09-22T19:45:04.337Z
Learning: In the eyaltoledano/claude-task-master project, Crunchyman-ralph intentionally omits version fields from internal/private packages in package.json files to prevent changesets from releasing new versions of these packages while still allowing them to be processed for dependency updates. The changesets warnings about missing versions are acceptable as they don't break the process and achieve the desired behavior of only releasing public packages.

Applied to files:

  • packages/tm-core/package.json
📚 Learning: 2025-09-26T19:05:47.555Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1252
File: packages/ai-sdk-provider-grok-cli/package.json:11-13
Timestamp: 2025-09-26T19:05:47.555Z
Learning: In the eyaltoledano/claude-task-master repository, internal tm/ packages use a specific export pattern where the "exports" field points to TypeScript source files (./src/index.ts) while "main" points to compiled output (./dist/index.js) and "types" points to source files (./src/index.ts). This pattern is used consistently across internal packages like tm/core and tm/ai-sdk-provider-grok-cli because they are consumed directly during build-time bundling with tsdown rather than being published as separate packages.

Applied to files:

  • packages/tm-core/package.json
  • packages/tm-core/src/index.ts
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
Repo: eyaltoledano/claude-task-master PR: 0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Track and report changes made during dependency cleanup

Applied to files:

  • packages/tm-core/package.json
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1252
File: tsconfig.json:22-28
Timestamp: 2025-09-26T19:10:32.906Z
Learning: In the eyaltoledano/claude-task-master repository, all internal tm/ package path mappings in tsconfig.json consistently point to TypeScript source files (e.g., "./packages/*/src/index.ts") rather than built JavaScript. This is intentional architecture because tsdown bundles internal packages directly from source during build time, eliminating the need for separate compilation of internal packages.

Applied to files:

  • packages/tm-core/package.json
🧬 Code graph analysis (1)
apps/cli/src/utils/brief-selection.ts (1)
packages/tm-core/src/utils/time.utils.ts (1)
  • formatRelativeTime (13-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (5)
packages/tm-core/src/modules/auth/services/organization.service.ts (2)

6-6: LGTM: Type-only imports improve build optimization.

Converting these to type-only imports is good practice for tree-shaking and cleaner builds.

Also applies to: 12-12


174-175: LGTM: Ordering ensures most recently updated briefs appear first.

The descending order by updated_at aligns well with the new relative time display feature, ensuring users see the most recently updated briefs at the top.

packages/tm-core/package.json (1)

34-34: LGTM: Dependency added for time utilities.

The date-fns dependency correctly supports the new formatRelativeTime utility.

packages/tm-core/src/index.ts (1)

53-53: LGTM: Time utility properly exported.

The new time utility export follows the project's minimal, need-based export strategy and is consumed by the CLI for brief selection.

Based on learnings

package.json (1)

86-86: No issues found.

date-fns version 4.1.0 exists and no security vulnerabilities were detected in the npm registry or GitHub's security advisory database.

@Crunchyman-ralph Crunchyman-ralph changed the title Ralph/feat/sort.briefs.by.updated.at feat: sort briefs by updated at Nov 14, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/cli/src/utils/brief-selection.ts (1)

114-137: Consider extracting duplicate brief option building logic.

The logic for building brief options (computing title, shortId, taskCountDisplay, updatedAtDisplay, and formatting the name) is duplicated in both the ordered and unordered status sections. Extracting this into a helper function would improve maintainability and reduce the risk of inconsistency.

Example helper function:

function buildBriefOption(brief: typeof briefs[0]) {
	const title = brief.document?.title || `Brief ${brief.id.slice(-8)}`;
	const shortId = brief.id.slice(-8);
	const description = brief.document?.description || '';
	const taskCountDisplay =
		brief.taskCount !== undefined && brief.taskCount > 0
			? chalk.gray(
					` (${brief.taskCount} ${brief.taskCount === 1 ? 'task' : 'tasks'})`
				)
			: '';

	const updatedAtDisplay = brief.updatedAt
		? chalk.gray(` • ${formatRelativeTime(brief.updatedAt)}`)
		: '';

	return {
		name: `  ${title}${taskCountDisplay} ${chalk.gray(`(${shortId})`)}${updatedAtDisplay}`,
		value: brief,
		description: description
			? chalk.gray(`  ${description.slice(0, 80)}`)
			: undefined
	};
}

Then replace both duplicated sections with:

statusBriefs.forEach((brief) => {
	groupedOptions.push(buildBriefOption(brief));
});

Also applies to: 154-177

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3077bf and 7342f7d.

📒 Files selected for processing (1)
  • apps/cli/src/utils/brief-selection.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1252
File: package.json:130-132
Timestamp: 2025-09-26T19:03:33.225Z
Learning: In the eyaltoledano/claude-task-master repository, packages are bundled using tsdown during the build process, which means dependencies imported by the source code (including tm internal packages like tm/ai-sdk-provider-grok-cli) are included in the final bundle and don't need to be available as separate runtime dependencies, so they should remain as devDependencies rather than being moved to dependencies.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/auth/config.ts:5-7
Timestamp: 2025-09-02T21:51:27.921Z
Learning: The user Crunchyman-ralph prefers not to use node: scheme imports (e.g., 'node:os', 'node:path') for Node.js core modules and considers suggestions to change bare imports to node: scheme as too nitpicky.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1069
File: .changeset/fix-tag-complexity-detection.md:0-0
Timestamp: 2025-08-02T15:33:22.656Z
Learning: For changeset files (.changeset/*.md), Crunchyman-ralph prefers to ignore formatting nitpicks about blank lines between frontmatter and descriptions, as he doesn't mind having them and wants to avoid such comments in future reviews.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1132
File: .github/workflows/weekly-metrics-discord.yml:81-93
Timestamp: 2025-08-13T22:10:46.958Z
Learning: Crunchyman-ralph ignores YAML formatting nitpicks about trailing spaces when there's no project-specific YAML formatter configured, preferring to focus on functionality over cosmetic formatting issues.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1132
File: .github/workflows/weekly-metrics-discord.yml:81-93
Timestamp: 2025-08-13T22:10:46.958Z
Learning: Crunchyman-ralph ignores YAML formatting nitpicks about trailing spaces when there's no project-specific YAML formatter configured, preferring to focus on functionality over cosmetic formatting issues.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1105
File: scripts/modules/supported-models.json:242-254
Timestamp: 2025-08-08T11:33:15.297Z
Learning: Preference: In scripts/modules/supported-models.json, the "name" field is optional. For OpenAI entries (e.g., "gpt-5"), Crunchyman-ralph prefers omitting "name" when the id is explicit enough; avoid nitpicks requesting a "name" in such cases.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1200
File: src/ai-providers/custom-sdk/grok-cli/language-model.js:96-100
Timestamp: 2025-09-19T16:06:42.182Z
Learning: The user Crunchyman-ralph prefers to keep environment variable names explicit (like GROK_CLI_API_KEY) rather than supporting multiple aliases, to avoid overlap and ensure clear separation between different CLI implementations.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1178
File: packages/tm-core/src/subpath-exports.test.ts:6-9
Timestamp: 2025-09-03T12:45:30.724Z
Learning: The user Crunchyman-ralph prefers to avoid overly nitpicky or detailed suggestions in code reviews, especially for test coverage of minor import paths. Focus on more substantial issues rather than comprehensive coverage of all possible edge cases.
Learnt from: Crunchyman-ralph
Repo: eyaltoledano/claude-task-master PR: 1217
File: apps/cli/src/index.ts:16-21
Timestamp: 2025-09-18T16:35:35.147Z
Learning: The user Crunchyman-ralph considers suggestions to export types for better ergonomics (like exporting UpdateInfo type alongside related functions) as nitpicky and prefers not to implement such suggestions.
🧬 Code graph analysis (1)
apps/cli/src/utils/brief-selection.ts (1)
packages/tm-core/src/utils/time.utils.ts (1)
  • formatRelativeTime (13-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (2)
apps/cli/src/utils/brief-selection.ts (2)

6-12: LGTM - Clean import improvements!

The type-only imports for AuthManager and Ora are appropriate, and the new formatRelativeTime utility is correctly imported for the timestamp display feature.


126-128: Good implementation of relative time display!

The conditional check for brief.updatedAt prevents errors, and using formatRelativeTime provides a user-friendly display. The styling with chalk.gray and the bullet separator maintains visual consistency with the rest of the UI.

Also applies to: 166-168

@Crunchyman-ralph Crunchyman-ralph merged commit 26f77c2 into next Nov 15, 2025
7 checks passed
@Crunchyman-ralph Crunchyman-ralph deleted the ralph/feat/sort.briefs.by.updated.at branch November 15, 2025 11:15
@coderabbitai coderabbitai bot mentioned this pull request Nov 15, 2025
16 tasks
sfc-gh-dflippo pushed a commit to sfc-gh-dflippo/task-master-ai that referenced this pull request Dec 4, 2025
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