-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat: add --spaceline output format to list command #471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| # Spaceline Output Format Design | ||
|
|
||
| ## Context | ||
|
|
||
| The `openspec list` command currently outputs simple tabular data. Users (particularly AI assistants) need a more compact, information-dense format that shows: | ||
| - Visual progress indicators | ||
| - Git change statistics | ||
|
|
||
| This format is inspired by "spaceline" prompts used in AI coding workflows. | ||
|
|
||
| ## Goals / Non-Goals | ||
|
|
||
| **Goals:** | ||
| - Compact, visually rich output format for change listings | ||
| - Git statistics integration (files added/removed) | ||
| - Graceful degradation when data is unavailable | ||
|
|
||
| **Non-Goals:** | ||
| - Complex Git history analysis (simple diff stats only) | ||
| - Persistent configuration for spaceline format | ||
|
|
||
| ## Decisions | ||
|
|
||
| ### Decision 1: Git stats via `git diff --numstat` | ||
|
|
||
| **What:** Use `git diff --numstat` to count file additions/removals. | ||
|
|
||
| **Why:** | ||
| - Simple, reliable command available in all Git installations | ||
| - Machine-readable output format | ||
| - No additional dependencies | ||
|
|
||
| **Format interpretation:** | ||
| ``` | ||
| 123 45 path/to/file.ts # 123 additions, 45 deletions β counts as "added" (β) | ||
| 10 50 another/file.ts # 10 additions, 50 deletions β counts as "removed" (β) | ||
| ``` | ||
|
|
||
| ### Decision 2: Emoji constants in separate module | ||
|
|
||
| **What:** Create `src/utils/spaceline-formatter.ts` with emoji constants. | ||
|
|
||
| **Why:** | ||
| - Centralized emoji management | ||
| - Easy to update/disable if needed | ||
| - Testable in isolation | ||
|
|
||
| **Emojis used:** | ||
| - `π` - Change icon | ||
| - `σ±` - Progress (Nerd Font icon, fallback to `β`) | ||
| - `σ°·«` - Implementation status | ||
| - `β` - Delta count | ||
| - `π` - Open items | ||
| - `σ°¬` - Git branch | ||
|
|
||
| ### Decision 3: Spaceline mutually exclusive with JSON | ||
|
|
||
| **What:** `--spaceline` and `--json` flags cannot be used together. | ||
|
|
||
| **Why:** | ||
| - Spaceline is a human-readable format | ||
| - JSON is for machine parsing | ||
| - Mixing them doesn't make sense | ||
|
|
||
| **Behavior:** Exit with error code 2 and clear message. | ||
|
|
||
| ## Risks / Trade-offs | ||
|
|
||
| ### Risk: Emoji/Nerd Font rendering | ||
|
|
||
| **Issue:** Some terminals don't support Nerd Font icons (σ±, σ°·«, σ°¬). | ||
|
|
||
| **Mitigation:** | ||
| - Use standard emoji fallbacks where possible | ||
| - Consider `--no-emoji` flag in future if needed | ||
| - Terminal font issues are user's responsibility | ||
|
|
||
| ### Risk: Git command availability | ||
|
|
||
| **Issue:** `git diff` may fail if not in a Git repo or Git not installed. | ||
|
|
||
| **Mitigation:** | ||
| - Wrap in try-catch, show `(?)` on failure | ||
| - Don't fail the entire command | ||
| - Document this behavior | ||
|
|
||
| ### Risk: Performance with many changes | ||
|
|
||
| **Issue:** Computing Git stats for each change could be slow. | ||
|
|
||
| **Mitigation:** | ||
| - Only run Git commands when `--spaceline` is used | ||
| - Consider caching in future if needed | ||
| - Expected usage is small number of active changes (<20) | ||
|
|
||
| ## Implementation Structure | ||
|
|
||
| ``` | ||
| src/utils/ | ||
| βββ git-stats.ts # Git diff statistics | ||
| βββ spaceline-formatter.ts # Format assembly | ||
|
|
||
| src/core/list.ts # Add spaceline mode | ||
| src/cli/index.ts # Add --spaceline flag | ||
| ``` | ||
|
|
||
| ## Migration Plan | ||
|
|
||
| No migration needed - this is a new feature flag. | ||
|
|
||
| ## Open Questions | ||
|
|
||
| 1. **Git base:** What should we diff against? Main branch? HEAD? | ||
| - **Answer:** Diff against `main` or `origin/main` if available, otherwise `HEAD~1` | ||
| - **Implementation detail:** Use `git diff --numstat main` or similar | ||
|
|
||
| 2. **Category detection:** How to map change ID to category (e.g., "add" β "Implementation")? | ||
| - **Answer:** Simple prefix mapping: `add-*` β Implementation, `update-*` β Refactor, `remove-*` β Deprecation |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # Add Spaceline Output Format to List Command | ||
|
|
||
| ## Why | ||
|
|
||
| Developers need a visually compact, information-dense way to view active changes with key metrics at a glance. The current `openspec list` output shows basic information but lacks: | ||
| 1. Visual progress indicators | ||
| 2. Git change statistics | ||
|
|
||
| This is particularly useful for AI coding assistants that need to quickly assess project state during development sessions. | ||
|
|
||
| ## What Changes | ||
|
|
||
| - Add `--spaceline` flag to `openspec list` command | ||
| - Display changes in a compact, emoji-rich horizontal format: | ||
| - Change ID and title | ||
| - Visual progress bar with percentage | ||
| - Task completion status | ||
| - Git diff statistics (files added/modified) | ||
| - Sort output by change ID (alphabetical) | ||
|
|
||
| Example output: | ||
| ``` | ||
| π add-api-versioning | σ± ββββββββββ 92.5% | ||
| σ°·« Implementation (4/7) | β 12 | π 5 open | σ°¬ feature/add-api-versioning (β5 β2) | ||
| ``` | ||
|
|
||
| ## Impact | ||
|
|
||
| - Affected specs: `cli-list` | ||
| - Affected code: | ||
| - `src/core/list.ts` - Add spaceline format output | ||
| - `src/cli/index.ts` - Add `--spaceline` option | ||
| - New utility modules for Git statistics and spaceline formatting |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| ## ADDED Requirements | ||
|
|
||
| ### Requirement: Spaceline Output Format | ||
|
|
||
| The command SHALL support a `--spaceline` flag that displays changes in a compact, visually rich horizontal format with emoji indicators and progress metrics. | ||
|
|
||
| #### Scenario: Spaceline basic format | ||
|
|
||
| - **WHEN** `openspec list --spaceline` is executed | ||
| - **THEN** display each change in a multi-line format: | ||
| - Line 1: Change icon, ID, and progress bar with percentage | ||
| - Line 2: Task status, delta count, open items, and branch with Git stats | ||
| - **AND** sort changes alphabetically by ID | ||
|
|
||
| #### Scenario: Spaceline with all elements | ||
|
|
||
| - **WHEN** a change has all available information | ||
| - **THEN** display: | ||
| ``` | ||
| π {change-id} | {progress-bar} {percentage}% | ||
| {status-icon} {category} ({completed}/{total} tasks) | {delta-icon} {count} | {open-icon} {open} | {branch-icon} {branch} ({added}β {removed}β) | ||
| ``` | ||
| - **WHERE**: | ||
| - `progress-bar` is a 10-character visual bar using `β` and `β` | ||
| - `percentage` is task completion percentage | ||
| - `status-icon` is implementation stage emoji (σ°·« for implementation, etc.) | ||
| - `category` is derived from change ID prefix (e.g., "add" β "Implementation") | ||
| - `delta-icon` `β` shows spec delta count | ||
| - `open-icon` `π` shows open TODO/pr items count | ||
| - `branch-icon` `σ°¬` shows current Git branch | ||
| - `addedβ` shows number of files with net additions | ||
| - `removedβ` shows number of files with net removals | ||
|
|
||
| #### Scenario: Spaceline with minimal data | ||
|
|
||
| - **WHEN** Git stats cannot be computed | ||
| - **THEN** display placeholder values: | ||
| - Git stats: omitted or `(?)` | ||
| - Branch: current branch or `(no branch)` | ||
|
|
||
| ### Requirement: Git Statistics | ||
|
|
||
| The command SHALL compute file change statistics from the Git repository when in spaceline mode. | ||
|
|
||
| #### Scenario: Computing Git diff statistics | ||
|
|
||
| - **WHEN** computing Git statistics for a change | ||
| - **THEN** run `git diff --numstat` against the relevant branch or base | ||
| - **AND** count files where additions > deletions as `added` (β) | ||
| - **AND** count files where deletions > additions as `removed` (β) | ||
| - **AND** handle non-Git directories gracefully by showing `(?)` | ||
|
|
||
| #### Scenario: Git statistics errors | ||
|
|
||
| - **WHEN** Git commands fail or repo is unavailable | ||
| - **THEN** display `(?)` instead of statistics | ||
| - **AND** do not fail the entire list command | ||
|
|
||
| ### Requirement: Spaceline Flag Compatibility | ||
|
|
||
| The `--spaceline` flag SHALL be mutually exclusive with `--json` and take precedence over `--long`. | ||
|
|
||
| #### Scenario: Spaceline overrides long format | ||
|
|
||
| - **WHEN** both `--spaceline` and `--long` are provided | ||
| - **THEN** use spaceline format | ||
| - **AND** ignore `--long` flag | ||
|
|
||
| #### Scenario: Spaceline conflicts with JSON | ||
|
|
||
| - **WHEN** both `--spaceline` and `--json` are provided | ||
| - **THEN** display error: "Cannot use --spaceline with --json" | ||
| - **AND** exit with code 2 | ||
|
|
||
| ## MODIFIED Requirements | ||
|
|
||
| ### Requirement: Flags | ||
|
|
||
| The command SHALL accept flags to select the noun being listed and output format. | ||
|
|
||
| #### Scenario: Selecting specs | ||
| - **WHEN** `--specs` is provided | ||
| - **THEN** list specs instead of changes | ||
|
|
||
| #### Scenario: Selecting changes | ||
| - **WHEN** `--changes` is provided | ||
| - **THEN** list changes explicitly (same as default behavior) | ||
|
|
||
| #### Scenario: Spaceline output format | ||
| - **WHEN** `--spaceline` is provided | ||
| - **THEN** display changes in compact spaceline format with emoji indicators | ||
| - **AND** include progress bars, task status, and Git stats | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| ## 1. Implementation | ||
|
|
||
| - [x] 1.1 Create `src/utils/git-stats.ts` module for Git statistics | ||
| - [x] 1.1.1 Implement `getGitDiffStats()` function using `git diff --numstat` | ||
| - [x] 1.1.2 Add error handling for non-Git directories | ||
| - [x] 1.1.3 Return `{ added: number, removed: number }` or `null` | ||
|
|
||
| - [x] 1.2 Create `src/utils/spaceline-formatter.ts` for output formatting | ||
| - [x] 1.2.1 Implement `generateProgressBar(percentage: number): string` | ||
| - [x] 1.2.2 Implement `formatSpaceline(change: ChangeData, stats: SpacelineStats): string[]` | ||
| - [x] 1.2.3 Add emoji constants for all UI elements | ||
|
|
||
| - [x] 1.3 Update `src/core/list.ts` | ||
| - [x] 1.3.1 Add `spaceline` option to `execute()` method signature | ||
| - [x] 1.3.2 Implement `executeSpaceline()` method for spaceline output | ||
| - [x] 1.3.3 Integrate Git stats collection | ||
|
|
||
| - [x] 1.4 Update `src/cli/index.ts` | ||
| - [x] 1.4.1 Add `--spaceline` option to list command | ||
| - [x] 1.4.2 Add mutual exclusion check with `--json` | ||
| - [x] 1.4.3 Pass spaceline flag to ListCommand | ||
|
|
||
| ## 2. Testing | ||
|
|
||
| - [x] 2.1 Create `test/utils/git-stats.test.ts` | ||
| - [x] 2.1.1 Test successful Git stats parsing | ||
| - [x] 2.1.2 Test non-Git directory handling | ||
| - [x] 2.1.3 Test error scenarios | ||
|
|
||
| - [x] 2.2 Create `test/utils/spaceline-formatter.test.ts` | ||
| - [x] 2.2.1 Test progress bar generation at various percentages | ||
| - [x] 2.2.2 Test full spaceline format output | ||
| - [x] 2.2.3 Test minimal data fallbacks | ||
|
|
||
| - [x] 2.3 Update `test/core/list.test.ts` | ||
| - [x] 2.3.1 Existing tests still pass | ||
| - [x] 2.3.2 No breaking changes to existing functionality | ||
|
|
||
| - [x] 2.4 Manual testing with `pnpm link` | ||
| - [x] 2.4.1 Verified spaceline output in real project | ||
| - [x] 2.4.2 Tested with Git repository | ||
|
|
||
| ## 3. Documentation | ||
|
|
||
| - [x] 3.1 Update `openspec/specs/cli-list/spec.md` (done via delta) | ||
| - [x] 3.2 Update help text in `src/cli/index.ts` (added --spaceline option description) | ||
| - [ ] 3.3 Add example output to README if needed (deferred - can be added later) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,23 +8,51 @@ A minimal CLI tool that helps developers set up OpenSpec file structures and kee | |
| - Package Manager: pnpm | ||
| - CLI Framework: Commander.js | ||
| - User Interaction: @inquirer/prompts | ||
| - Validation: Zod | ||
| - Terminal UI: Chalk, Ora | ||
| - File Operations: fast-glob | ||
| - YAML Parsing: yaml | ||
| - Distribution: npm package | ||
| - Testing: Vitest | ||
| - Versioning: @changesets/cli | ||
|
|
||
| ## Project Structure | ||
| ``` | ||
| src/ | ||
| βββ cli/ # CLI command implementations | ||
| βββ core/ # Core OpenSpec logic (templates, structure) | ||
| βββ utils/ # Shared utilities (file operations, rollback) | ||
| βββ commands/ # CLI command handlers | ||
| β βββ change.ts # Change proposal commands | ||
| β βββ spec.ts # Spec management commands | ||
| β βββ completion.ts # Shell completion commands | ||
| β βββ config.ts # Configuration commands | ||
| β βββ validate.ts # Validation commands | ||
| β βββ show.ts # Display commands | ||
| βββ core/ | ||
| β βββ configurators/ # AI tool configuration | ||
| β β βββ registry.ts | ||
| β β βββ [agent].ts | ||
| β β βββ slash/ # Slash command configurators | ||
| β βββ completions/ # Shell completion system | ||
| β β βββ generators/ # Bash, Zsh, Fish, PowerShell | ||
| β β βββ installers/ | ||
| β β βββ templates/ | ||
| β βββ artifact-graph/ # Artifact dependency resolution | ||
| β βββ templates/ # AI instruction templates | ||
| β βββ schemas/ # OpenSpec schema definitions | ||
| β βββ parsers/ # Markdown/change parsers | ||
| β βββ validation/ # Spec validation logic | ||
| βββ utils/ # Shared utilities | ||
|
|
||
| dist/ # Compiled output (gitignored) | ||
| ``` | ||
|
Comment on lines
19
to
46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a language tag to the fenced project-structure block (MD040). Proposed markdownlint fix ## Project Structure
-```
+```text
src/
βββ commands/ # CLI command handlers
β βββ change.ts # Change proposal commands
β βββ spec.ts # Spec management commands
β βββ completion.ts # Shell completion commands
β βββ config.ts # Configuration commands
β βββ validate.ts # Validation commands
β βββ show.ts # Display commands
βββ core/
β βββ configurators/ # AI tool configuration
β β βββ registry.ts
β β βββ [agent].ts
β β βββ slash/ # Slash command configurators
β βββ completions/ # Shell completion system
β β βββ generators/ # Bash, Zsh, Fish, PowerShell
β β βββ installers/
β β βββ templates/
β βββ artifact-graph/ # Artifact dependency resolution
β βββ templates/ # AI instruction templates
β βββ schemas/ # OpenSpec schema definitions
β βββ parsers/ # Markdown/change parsers
β βββ validation/ # Spec validation logic
βββ utils/ # Shared utilities
dist/ # Compiled output (gitignored)In @openspec/project.md around lines 19 - 46, The fenced code block under the |
||
|
|
||
| ## Conventions | ||
| - TypeScript strict mode enabled | ||
| - ES2022 target, NodeNext module resolution | ||
| - Async/await for all asynchronous operations | ||
| - Minimal dependencies principle | ||
| - Clear separation of CLI, core logic, and utilities | ||
| - ESLint with typescript-eslint | ||
| - File naming: kebab-case for directories, PascalCase for types | ||
| - AI-friendly code with descriptive names | ||
|
|
||
| ## Error Handling | ||
|
|
@@ -37,17 +65,26 @@ dist/ # Compiled output (gitignored) | |
| - Use console methods directly (no logging library) | ||
| - console.log() for normal output | ||
| - console.error() for errors (outputs to stderr) | ||
| - Use chalk for colored output | ||
| - Use ora for spinners/loading indicators | ||
| - No verbose/debug modes initially (keep it simple) | ||
|
|
||
| ## Testing Strategy | ||
| - Manual testing via `pnpm link` during development | ||
| - Smoke tests for critical paths only (init, help commands) | ||
| - No unit tests initially - add when complexity grows | ||
| - Test commands: `pnpm test:smoke` (when added) | ||
| - Framework: Vitest with globals enabled | ||
| - Test files: `test/**/*.test.ts` | ||
| - Environment: node (default) | ||
| - Coverage: text, json, html reporters | ||
| - Run tests: `pnpm test` | ||
| - Watch mode: `pnpm test:watch` | ||
| - Coverage report: `pnpm test:coverage` | ||
| - Test timeout: 10s (configurable) | ||
|
|
||
| ## Development Workflow | ||
| - Use pnpm for all package management | ||
| - Run `pnpm run build` to compile TypeScript | ||
| - Run `pnpm run dev` for development mode | ||
| - Test locally with `pnpm link` | ||
| - Follow OpenSpec's own change-driven development process | ||
| - Follow OpenSpec's own change-driven development process | ||
| - Use changesets for versioning: `pnpm changeset` | ||
| - Release: `pnpm run release` (CI) or `pnpm run release:local` | ||
| - Postinstall script ensures permissions | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spec example output doesnβt match the implemented spaceline line format (status icon + git stats ordering).
The formatter output (and PR example) includes the status icon on Line 1 and uses
β{added} β{removed}ordering; the spec example currently differs. Also, add a language to the fenced block (MD040).Proposed spec fix
Also applies to: 34-40
π€ Prompt for AI Agents