Skip to content

Conversation

@TabishB
Copy link
Contributor

@TabishB TabishB commented Dec 30, 2025

Summary

  • Add lastModified field showing when each change was last modified (based on most recent file in the change directory)
  • Default sort order is now recent (most recently modified first) instead of alphabetical
  • Add --sort option to choose between recent and name ordering
  • Add --json option for programmatic access with structured output
  • Fall back to directory mtime for empty change directories (fixes 1970 date issue)
  • Display relative time (e.g., "2h ago", "3d ago") in human-readable output

Example Output

Changes:
  add-claude-code-skills                 0/22 tasks    4h ago
  add-antigravity-support                ✓ Complete    20/11/2025
  add-scaffold-command                   0/7 tasks     19/11/2025

JSON output (--json):

{
  "changes": [
    {
      "name": "add-claude-code-skills",
      "completedTasks": 0,
      "totalTasks": 22,
      "lastModified": "2025-12-29T08:04:49.323Z",
      "status": "in-progress"
    }
  ]
}

Test plan

  • openspec list shows changes sorted by most recent
  • openspec list --sort name shows alphabetical order
  • openspec list --json outputs structured JSON
  • Empty directories show directory mtime instead of 1970

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added --sort flag to list changes by name or recent modification date (default: recent).
    • Added --json flag for structured JSON output format.
    • Changes now display their last modified time in human-readable format (e.g., "2d ago").

✏️ Tip: You can customize this high-level summary in your review settings.

- Add lastModified field showing when each change was last modified
- Default sort order is now "recent" (most recently modified first)
- Add --sort option to choose between "recent" and "name" ordering
- Add --json option for programmatic access with structured output
- Fall back to directory mtime for empty change directories
- Display relative time (e.g., "2h ago", "3d ago") in human output
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

The pull request adds sorting and JSON output capabilities to a CLI list command by introducing --sort and --json flags, updating the CLI to parse these options, and extending the underlying ListCommand to compute lastModified timestamps for changes, support configurable sorting ('recent' or 'name'), and emit structured JSON or formatted text output.

Changes

Cohort / File(s) Summary
CLI Options & Integration
src/cli/index.ts
Added --sort <order> (default: "recent") and --json flags to list command; updated action handler to compute sort value and pass { sort, json } options object to ListCommand.execute
Core List Command Enhancement
src/core/list.ts
Added lastModified: Date field to ChangeInfo; introduced ListOptions interface (sort, json flags); implemented formatRelativeTime utility for human-readable timestamps; enhanced ListCommand.execute to accept options parameter, compute lastModified per change, apply dynamic sorting (recent/name), and conditionally output JSON or formatted text

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant ListCommand
    participant FileSystem as File System
    participant Formatter

    User->>CLI: list --sort recent --json
    CLI->>ListCommand: execute(path, mode, { sort: 'recent', json: true })
    
    ListCommand->>FileSystem: scan change directories
    FileSystem-->>ListCommand: directory entries
    
    ListCommand->>FileSystem: get lastModified for each change
    FileSystem-->>ListCommand: mtime values
    
    Note over ListCommand: Sort by lastModified (descending)
    
    alt json flag = true
        ListCommand->>Formatter: formatAsJSON(changes with status)
        Formatter-->>ListCommand: JSON string
    else json flag = false
        ListCommand->>Formatter: formatAsText(changes with timeAgo)
        Formatter-->>ListCommand: formatted text
    end
    
    ListCommand-->>User: output (JSON or text)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit hops through changes new,
Sorting recent, sorting by name too!
With timestamps gleaming, JSON so bright,
Last modified tracked—everything's right!
Thump-thump goes the list command's might! 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically summarizes the main changes: adding last modified timestamps and sorting capabilities to the list command.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@vibe-kanban-cloud
Copy link

Review Complete

Your review story is ready!

View Story

Comment !reviewfast on this PR to re-generate the story.

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)
src/core/list.ts (2)

27-40: Consider handling transient file errors in the walk.

If a file is deleted between readdir and fs.stat, the function will throw an unhandled error. This is a race condition that could occur if files are being modified concurrently.

🔎 Proposed fix to handle transient file errors
   async function walk(dir: string): Promise<void> {
     const entries = await fs.readdir(dir, { withFileTypes: true });
     for (const entry of entries) {
       const fullPath = path.join(dir, entry.name);
-      if (entry.isDirectory()) {
-        await walk(fullPath);
-      } else {
-        const stat = await fs.stat(fullPath);
-        if (latest === null || stat.mtime > latest) {
-          latest = stat.mtime;
+      try {
+        if (entry.isDirectory()) {
+          await walk(fullPath);
+        } else {
+          const stat = await fs.stat(fullPath);
+          if (latest === null || stat.mtime > latest) {
+            latest = stat.mtime;
+          }
         }
+      } catch {
+        // Ignore files that disappear between readdir and stat
       }
     }
   }

154-192: Consider supporting --sort and --json for specs mode in a follow-up.

The new sort and json options are only implemented for 'changes' mode. For consistency, users might expect these options to work for specs as well. This could be addressed in a future enhancement.

📜 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 fb7ff52 and 45d4b6b.

📒 Files selected for processing (2)
  • src/cli/index.ts
  • src/core/list.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/cli/index.ts (1)
src/core/list.ts (1)
  • ListCommand (77-194)
src/core/list.ts (1)
src/utils/task-progress.ts (1)
  • getTaskProgressForChange (27-35)
🔇 Additional comments (5)
src/cli/index.ts (1)

99-106: LGTM! CLI options properly integrated.

The new --sort and --json options are correctly defined with appropriate defaults, and the action handler properly processes these options before passing them to ListCommand.execute. The fallback to 'recent' when sort is anything other than 'name' provides sensible default behavior.

src/core/list.ts (4)

8-18: LGTM! Clean interface definitions.

The ChangeInfo interface properly includes the new lastModified field, and ListOptions provides a well-typed options object with appropriate optional fields and literal types for the sort option.


53-75: LGTM! Well-structured relative time formatting.

The function correctly handles various time ranges with a logical progression from days to minutes to "just now". Using toLocaleDateString() for dates older than 30 days provides appropriate locale-aware formatting.


77-79: LGTM! Clean signature update with sensible defaults.

The execute method signature properly accepts the new options parameter with default values, and the destructuring with defaults makes the code clean and maintainable.


121-139: LGTM! Sorting and JSON output implementation.

The sorting logic correctly handles both modes (recent by timestamp descending, name alphabetically), and the JSON output provides a well-structured format with ISO date strings suitable for programmatic consumption.

@TabishB TabishB merged commit 48b5ed9 into main Dec 30, 2025
7 checks passed
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.

2 participants