From 793726626233f44bc12039b74bf8a7d6e47db6b9 Mon Sep 17 00:00:00 2001 From: Steve Cliff Date: Wed, 18 Feb 2026 21:38:41 +0000 Subject: [PATCH] feat(status): add --project flag for filtering boards by project name - Implemented the --project flag in the pcli status command to filter boards based on the specified project name. - Updated the command to resolve project names to IDs using case-insensitive matching. - Adjusted the totalBoards count in the output to reflect the number of boards matching the project filter. - Enhanced command help text and README documentation to include usage examples for the new flag. - Verified functionality through manual testing and ensured default behavior remains unchanged when the flag is omitted. feat(board): expand GetBoard response to include labels and card associations - Modified the Board struct to include Labels, CardLabels, and CardMemberships fields. - Updated the GetBoard method to parse additional fields from the API response. - Enhanced ListCardsByBoard to include label names for each card based on the enriched board data. - Ensured backward compatibility by making new fields optional and preserving existing output structure. --- .claude/commands/kanban-sync.md | 7 ++--- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/cli-commands/spec.md | 0 .../specs/status-command/spec.md | 0 .../tasks.md | 0 .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/api-client/spec.md | 0 .../specs/card-operations/spec.md | 0 .../tasks.md | 0 openspec/specs/api-client/spec.md | 17 ++++++++++-- openspec/specs/card-operations/spec.md | 14 +++++++--- openspec/specs/cli-commands/spec.md | 6 ++++- openspec/specs/status-command/spec.md | 27 ++++++++++++++++++- 17 files changed, 61 insertions(+), 10 deletions(-) rename openspec/changes/{add-project-filter-to-status => archive/2026-02-18-add-project-filter-to-status}/.openspec.yaml (100%) rename openspec/changes/{add-project-filter-to-status => archive/2026-02-18-add-project-filter-to-status}/design.md (100%) rename openspec/changes/{add-project-filter-to-status => archive/2026-02-18-add-project-filter-to-status}/proposal.md (100%) rename openspec/changes/{add-project-filter-to-status => archive/2026-02-18-add-project-filter-to-status}/specs/cli-commands/spec.md (100%) rename openspec/changes/{add-project-filter-to-status => archive/2026-02-18-add-project-filter-to-status}/specs/status-command/spec.md (100%) rename openspec/changes/{add-project-filter-to-status => archive/2026-02-18-add-project-filter-to-status}/tasks.md (100%) rename openspec/changes/{expand-board-included-parsing => archive/2026-02-18-expand-board-included-parsing}/.openspec.yaml (100%) rename openspec/changes/{expand-board-included-parsing => archive/2026-02-18-expand-board-included-parsing}/design.md (100%) rename openspec/changes/{expand-board-included-parsing => archive/2026-02-18-expand-board-included-parsing}/proposal.md (100%) rename openspec/changes/{expand-board-included-parsing => archive/2026-02-18-expand-board-included-parsing}/specs/api-client/spec.md (100%) rename openspec/changes/{expand-board-included-parsing => archive/2026-02-18-expand-board-included-parsing}/specs/card-operations/spec.md (100%) rename openspec/changes/{expand-board-included-parsing => archive/2026-02-18-expand-board-included-parsing}/tasks.md (100%) diff --git a/.claude/commands/kanban-sync.md b/.claude/commands/kanban-sync.md index 470de65..069802b 100644 --- a/.claude/commands/kanban-sync.md +++ b/.claude/commands/kanban-sync.md @@ -216,10 +216,11 @@ fi # Get existing task names to avoid duplicates EXISTING_TASKS=$(echo "$CARD_DATA" | jq -r '.data.tasks[] | select(.taskListId == "'$TL_ID'") | .name') -# For each task in tasks.md: +# For each task in tasks.md (in order), assign incrementing positions: +# position = (index + 1) * 65536 (i.e. 65536, 131072, 196608, ...) # - If a task with the same name already exists, update its completion state if needed -# - If no matching task exists, create it -pcli task create --task-list $TL_ID --name "" +# - If no matching task exists, create it with explicit position +pcli task create --task-list $TL_ID --name "" --position # For tasks already in Planka, update completion state to match tasks.md: pcli task update --completed # if tasks.md shows [x] diff --git a/openspec/changes/add-project-filter-to-status/.openspec.yaml b/openspec/changes/archive/2026-02-18-add-project-filter-to-status/.openspec.yaml similarity index 100% rename from openspec/changes/add-project-filter-to-status/.openspec.yaml rename to openspec/changes/archive/2026-02-18-add-project-filter-to-status/.openspec.yaml diff --git a/openspec/changes/add-project-filter-to-status/design.md b/openspec/changes/archive/2026-02-18-add-project-filter-to-status/design.md similarity index 100% rename from openspec/changes/add-project-filter-to-status/design.md rename to openspec/changes/archive/2026-02-18-add-project-filter-to-status/design.md diff --git a/openspec/changes/add-project-filter-to-status/proposal.md b/openspec/changes/archive/2026-02-18-add-project-filter-to-status/proposal.md similarity index 100% rename from openspec/changes/add-project-filter-to-status/proposal.md rename to openspec/changes/archive/2026-02-18-add-project-filter-to-status/proposal.md diff --git a/openspec/changes/add-project-filter-to-status/specs/cli-commands/spec.md b/openspec/changes/archive/2026-02-18-add-project-filter-to-status/specs/cli-commands/spec.md similarity index 100% rename from openspec/changes/add-project-filter-to-status/specs/cli-commands/spec.md rename to openspec/changes/archive/2026-02-18-add-project-filter-to-status/specs/cli-commands/spec.md diff --git a/openspec/changes/add-project-filter-to-status/specs/status-command/spec.md b/openspec/changes/archive/2026-02-18-add-project-filter-to-status/specs/status-command/spec.md similarity index 100% rename from openspec/changes/add-project-filter-to-status/specs/status-command/spec.md rename to openspec/changes/archive/2026-02-18-add-project-filter-to-status/specs/status-command/spec.md diff --git a/openspec/changes/add-project-filter-to-status/tasks.md b/openspec/changes/archive/2026-02-18-add-project-filter-to-status/tasks.md similarity index 100% rename from openspec/changes/add-project-filter-to-status/tasks.md rename to openspec/changes/archive/2026-02-18-add-project-filter-to-status/tasks.md diff --git a/openspec/changes/expand-board-included-parsing/.openspec.yaml b/openspec/changes/archive/2026-02-18-expand-board-included-parsing/.openspec.yaml similarity index 100% rename from openspec/changes/expand-board-included-parsing/.openspec.yaml rename to openspec/changes/archive/2026-02-18-expand-board-included-parsing/.openspec.yaml diff --git a/openspec/changes/expand-board-included-parsing/design.md b/openspec/changes/archive/2026-02-18-expand-board-included-parsing/design.md similarity index 100% rename from openspec/changes/expand-board-included-parsing/design.md rename to openspec/changes/archive/2026-02-18-expand-board-included-parsing/design.md diff --git a/openspec/changes/expand-board-included-parsing/proposal.md b/openspec/changes/archive/2026-02-18-expand-board-included-parsing/proposal.md similarity index 100% rename from openspec/changes/expand-board-included-parsing/proposal.md rename to openspec/changes/archive/2026-02-18-expand-board-included-parsing/proposal.md diff --git a/openspec/changes/expand-board-included-parsing/specs/api-client/spec.md b/openspec/changes/archive/2026-02-18-expand-board-included-parsing/specs/api-client/spec.md similarity index 100% rename from openspec/changes/expand-board-included-parsing/specs/api-client/spec.md rename to openspec/changes/archive/2026-02-18-expand-board-included-parsing/specs/api-client/spec.md diff --git a/openspec/changes/expand-board-included-parsing/specs/card-operations/spec.md b/openspec/changes/archive/2026-02-18-expand-board-included-parsing/specs/card-operations/spec.md similarity index 100% rename from openspec/changes/expand-board-included-parsing/specs/card-operations/spec.md rename to openspec/changes/archive/2026-02-18-expand-board-included-parsing/specs/card-operations/spec.md diff --git a/openspec/changes/expand-board-included-parsing/tasks.md b/openspec/changes/archive/2026-02-18-expand-board-included-parsing/tasks.md similarity index 100% rename from openspec/changes/expand-board-included-parsing/tasks.md rename to openspec/changes/archive/2026-02-18-expand-board-included-parsing/tasks.md diff --git a/openspec/specs/api-client/spec.md b/openspec/specs/api-client/spec.md index ff41e05..ab0dba8 100644 --- a/openspec/specs/api-client/spec.md +++ b/openspec/specs/api-client/spec.md @@ -71,11 +71,24 @@ The client SHALL provide methods to list all accessible projects (`GET /projects - **THEN** the client SHALL send `DELETE /projects/{id}` ### Requirement: Board operations -The client SHALL provide a method to get a single board by ID (`GET /boards/{id}`), list board actions (`GET /boards/{boardId}/actions`) with pagination support, create a board (`POST /projects/{projectId}/boards`), and delete a board (`DELETE /boards/{id}`). +The client SHALL provide a method to get a single board by ID (`GET /boards/{id}`), list board actions (`GET /boards/{boardId}/actions`) with pagination support, create a board (`POST /projects/{projectId}/boards`), and delete a board (`DELETE /boards/{id}`). `GetBoard` SHALL parse the `included` object from the response and populate the Board model with `lists`, `cards`, `labels`, `cardLabels`, and `cardMemberships`. #### Scenario: Get board - **WHEN** `GetBoard` is called with a board ID -- **THEN** the client SHALL send `GET /boards/{id}` and return a Board model including its included lists +- **THEN** the client SHALL send `GET /boards/{id}` and return a Board model including its included lists, cards, labels, cardLabels, and cardMemberships + +#### Scenario: Get board includes labels +- **WHEN** `GetBoard` is called and the board has labels defined +- **THEN** the returned Board SHALL contain a `Labels` slice with all board labels + +#### Scenario: Get board includes card-label associations +- **WHEN** `GetBoard` is called and cards on the board have labels attached +- **THEN** the returned Board SHALL contain a `CardLabels` slice with all card-label associations +- **AND** each `CardLabel` entry SHALL contain `cardId` and `labelId` fields + +#### Scenario: Get board includes card memberships +- **WHEN** `GetBoard` is called and cards on the board have members assigned +- **THEN** the returned Board SHALL contain a `CardMemberships` slice with all card-membership associations #### Scenario: List board actions - **WHEN** `ListBoardActions` is called with a board ID and limit diff --git a/openspec/specs/card-operations/spec.md b/openspec/specs/card-operations/spec.md index 6a74af6..f77d0cf 100644 --- a/openspec/specs/card-operations/spec.md +++ b/openspec/specs/card-operations/spec.md @@ -65,18 +65,26 @@ The system SHALL provide `card add-label` and `card remove-label` operations to - **THEN** the system SHALL print an error indicating `--label` is required and exit with code 1 ### Requirement: Enriched board-level card listing -The system SHALL provide a `card list --board ` operation that returns all cards across all lists in a board, with each card enriched with the `listName` field. The operation SHALL: (1) call `GET /boards/{id}` to retrieve the board and its included lists, (2) call `GET /lists/{listId}/cards` for each list to retrieve cards (with pagination support), (3) inject `listName` into each card based on the list it belongs to. The `--limit` flag SHALL apply to the total number of cards returned across all lists. +The system SHALL provide a `card list --board ` operation that returns all cards across all lists in a board, with each card enriched with the `listName` field and a `labels` field. The operation SHALL: (1) call `GET /boards/{id}` to retrieve the board and its included lists, cards, labels, and cardLabels, (2) build a card-to-label-names map by joining `cardLabels` with `labels`, (3) inject `listName` and `labels` into each card. The `labels` field SHALL be an array of label name strings. The `--limit` flag SHALL apply to the total number of cards returned across all lists. #### Scenario: List all cards on a board - **WHEN** `pcli card list --board ` is executed - **THEN** the system SHALL return all cards from all lists in the board - **AND** each card SHALL include a `listName` field with the name of its containing list -- **AND** each card SHALL include a `listId` field +- **AND** each card SHALL include a `labels` field with an array of label names attached to that card + +#### Scenario: Card with multiple labels +- **WHEN** a card has two labels ("bug" and "urgent") attached +- **THEN** the `labels` array for that card SHALL contain both "bug" and "urgent" + +#### Scenario: Card with no labels +- **WHEN** a card has no labels attached +- **THEN** the `labels` array for that card SHALL be an empty array (not null) #### Scenario: Board card listing with limit - **WHEN** `pcli card list --board --limit 10` is executed - **THEN** the system SHALL return at most 10 cards total across all lists -- **AND** each card SHALL include the `listName` field +- **AND** each card SHALL include the `listName` and `labels` fields #### Scenario: Board with no cards - **WHEN** `pcli card list --board ` is executed on a board with empty lists diff --git a/openspec/specs/cli-commands/spec.md b/openspec/specs/cli-commands/spec.md index b74a579..977a153 100644 --- a/openspec/specs/cli-commands/spec.md +++ b/openspec/specs/cli-commands/spec.md @@ -241,12 +241,16 @@ The system SHALL provide a `task` command group with subcommands: `create`, `upd - **THEN** the system SHALL delete the task and output a success confirmation ### Requirement: Status command -The system SHALL provide a top-level `status` command registered directly on the root command (not as a subcommand of any resource group). `pcli status` SHALL take no positional arguments. The command SHALL fetch all boards via `ListBoards`, then fetch each board's details via `GetBoard` sequentially, aggregate card counts per list, and output the result via the standard `output.Print` mechanism respecting the global `--format` flag. +The system SHALL provide a top-level `status` command registered directly on the root command (not as a subcommand of any resource group). `pcli status` SHALL take no positional arguments. The command SHALL accept an optional `--project ` flag (string) to filter boards by project name. The command SHALL fetch all boards via `ListBoards`, optionally filter by project, then fetch each board's details via `GetBoard` sequentially, aggregate card counts per list, and output the result via the standard `output.Print` mechanism respecting the global `--format` flag. #### Scenario: Run status command - **WHEN** `pcli status` is executed - **THEN** the system SHALL output a summary of all boards with their lists and card counts +#### Scenario: Run status command with project filter +- **WHEN** `pcli status --project "MyProject"` is executed +- **THEN** the system SHALL output a summary of only boards belonging to "MyProject" + #### Scenario: Status command respects format flag - **WHEN** `pcli status --format table` is executed - **THEN** the output SHALL be in table format diff --git a/openspec/specs/status-command/spec.md b/openspec/specs/status-command/spec.md index 90dd896..065e09a 100644 --- a/openspec/specs/status-command/spec.md +++ b/openspec/specs/status-command/spec.md @@ -1,7 +1,32 @@ ## ADDED Requirements +### Requirement: Status command project filtering +The system SHALL accept an optional `--project ` flag on the `pcli status` command. When `--project` is provided, the system SHALL resolve the project name to a project ID using case-insensitive exact matching against all accessible projects. The system SHALL then filter the board list to include only boards whose `projectId` matches the resolved project ID. The `totalBoards` count in the output SHALL reflect the filtered board count. When `--project` is omitted, behavior SHALL be unchanged (all boards shown). + +#### Scenario: Status filtered by project name +- **WHEN** `pcli status --project "MyProject"` is executed and the project exists with 2 boards +- **THEN** the output SHALL include only the 2 boards belonging to "MyProject" +- **AND** `totalBoards` SHALL be 2 + +#### Scenario: Status filtered by project name case-insensitive +- **WHEN** `pcli status --project "myproject"` is executed and a project named "MyProject" exists +- **THEN** the output SHALL include boards belonging to "MyProject" + +#### Scenario: Status with project filter and no matching boards +- **WHEN** `pcli status --project "EmptyProject"` is executed and the project exists but has no boards +- **THEN** the output SHALL show `totalBoards` as 0 and an empty boards array + +#### Scenario: Status with project not found +- **WHEN** `pcli status --project "NonExistent"` is executed and no project with that name exists +- **THEN** the system SHALL output an error "project not found: NonExistent" +- **AND** the system SHALL exit with code 1 + +#### Scenario: Status without project flag +- **WHEN** `pcli status` is executed without `--project` +- **THEN** the output SHALL include all boards across all projects (unchanged behavior) + ### Requirement: Status command summary output -The system SHALL provide a top-level `pcli status` command that outputs a summary of all boards, their lists, and card counts. The summary SHALL include the total number of boards. For each board, the summary SHALL include the board name and a breakdown of each list within that board showing the list name, the number of open cards (where `isClosed` is false), and the number of closed cards (where `isClosed` is true). Empty lists SHALL be included in the output with 0 open and 0 closed cards. +The system SHALL provide a top-level `pcli status` command that outputs a summary of all boards (or boards filtered by `--project`), their lists, and card counts. The summary SHALL include the total number of boards. For each board, the summary SHALL include the board name and a breakdown of each list within that board showing the list name, the number of open cards (where `isClosed` is false), and the number of closed cards (where `isClosed` is true). Empty lists SHALL be included in the output with 0 open and 0 closed cards. #### Scenario: Status with multiple boards and lists - **WHEN** `pcli status` is executed and there are boards with lists containing cards