feat(board): create, update, and delete agile boards #148

Merged
Claude-Run merged 1 commit from feat/YT-93-board-crud into main 2026-08-06 13:21:02 +02:00
Member

Adds the three write verbs to the agile board surface, following the plan/execute, --dry-run, and --yes conventions the project administration commands already use. board create <NAME> --project <SHORT>... posts /api/agiles, board update <BOARD> posts /api/agiles/<id> with only the settings the invocation named, and board delete <BOARD> --yes sends DELETE /api/agiles/<id> and re-reads the board list so a delete the server ignored is reported. The MCP mirrors all three as create_board / update_board / delete_board, gated by the per-call dry_run.

The template query parameter on /api/agiles was verified against the live instance rather than assumed: an unknown name is rejected with 400 No template with name <n>, so it really is parsed. kanban and scrum are exposed; version is a third name the server recognises but it is left off the flag so the surface matches project create --template, and the reason is recorded next to create_board.

Several other live shapes drove the design and are recorded in comments beside the client functions. An Agile update merges at the top level and sprintsSettings merges too, but swimlaneSettings does not: posting it without field is rejected with 400 FilterField is null, and posting null is what turns swimlanes off. The instance does expose a per-column subresource that takes a narrower write than rewriting columnSettings, so --wip <COLUMN>=<MIN>:<MAX> posts to columnSettings/columns/<id> rather than replacing the whole column list; the dry run lists those follow-up writes with their own endpoint and body. Setting visibleFor alone leaves visibleForProjectBased true, which makes the group inert, so --visible-for and --updateable-by clear the matching flag with the group.

Name resolution is split from the write for both writes (plan_create_board / plan_update_board), so --dry-run prints the byte-exact body with the name-to-id work in a separate resolved block. Every name-taking flag refuses an ambiguous name and lists the candidates instead of guessing. The same sweep found two pre-existing silent picks in the resolvers these verbs depend on: /api/groups is polymorphic, so a ProjectTeam can share a name with a NestedGroup, and YouTrack does not enforce unique board names (probed: two creates with the same name both succeed), which meant board delete could have removed an arbitrary one of two. Both now error and name the candidates.

#YT-93

Adds the three write verbs to the agile board surface, following the plan/execute, `--dry-run`, and `--yes` conventions the project administration commands already use. `board create <NAME> --project <SHORT>...` posts `/api/agiles`, `board update <BOARD>` posts `/api/agiles/<id>` with only the settings the invocation named, and `board delete <BOARD> --yes` sends `DELETE /api/agiles/<id>` and re-reads the board list so a delete the server ignored is reported. The MCP mirrors all three as `create_board` / `update_board` / `delete_board`, gated by the per-call `dry_run`. The `template` query parameter on `/api/agiles` was verified against the live instance rather than assumed: an unknown name is rejected with `400 No template with name <n>`, so it really is parsed. `kanban` and `scrum` are exposed; `version` is a third name the server recognises but it is left off the flag so the surface matches `project create --template`, and the reason is recorded next to `create_board`. Several other live shapes drove the design and are recorded in comments beside the client functions. An `Agile` update merges at the top level and `sprintsSettings` merges too, but `swimlaneSettings` does not: posting it without `field` is rejected with `400 FilterField is null`, and posting `null` is what turns swimlanes off. The instance does expose a per-column subresource that takes a narrower write than rewriting `columnSettings`, so `--wip <COLUMN>=<MIN>:<MAX>` posts to `columnSettings/columns/<id>` rather than replacing the whole column list; the dry run lists those follow-up writes with their own endpoint and body. Setting `visibleFor` alone leaves `visibleForProjectBased` true, which makes the group inert, so `--visible-for` and `--updateable-by` clear the matching flag with the group. Name resolution is split from the write for both writes (`plan_create_board` / `plan_update_board`), so `--dry-run` prints the byte-exact body with the name-to-id work in a separate `resolved` block. Every name-taking flag refuses an ambiguous name and lists the candidates instead of guessing. The same sweep found two pre-existing silent picks in the resolvers these verbs depend on: `/api/groups` is polymorphic, so a `ProjectTeam` can share a name with a `NestedGroup`, and YouTrack does not enforce unique board names (probed: two creates with the same name both succeed), which meant `board delete` could have removed an arbitrary one of two. Both now error and name the candidates. #YT-93
feat(board): create, update, and delete agile boards
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m29s
Create release / Create release from merged PR (pull_request) Has been skipped
237af403d0
Adds the three write verbs to the agile board surface, following the plan/execute, `--dry-run`, and `--yes` conventions the project administration commands already use. `board create <NAME> --project <SHORT>...` posts `/api/agiles`, `board update <BOARD>` posts `/api/agiles/<id>` with only the settings the invocation named, and `board delete <BOARD> --yes` sends `DELETE /api/agiles/<id>` and re-reads the board list so a delete the server ignored is reported. The MCP mirrors all three as `create_board` / `update_board` / `delete_board`, gated by the per-call `dry_run`.

The `template` query parameter on `/api/agiles` was verified against the live instance rather than assumed: an unknown name is rejected with `400 No template with name <n>`, so it really is parsed. `kanban` and `scrum` are exposed; `version` is a third name the server recognises but it is left off the flag so the surface matches `project create --template`, and the reason is recorded next to `create_board`.

Several other live shapes drove the design and are recorded in comments beside the client functions. An `Agile` update merges at the top level and `sprintsSettings` merges too, but `swimlaneSettings` does not: posting it without `field` is rejected with `400 FilterField is null`, and posting `null` is what turns swimlanes off. The instance does expose a per-column subresource that takes a narrower write than rewriting `columnSettings`, so `--wip <COLUMN>=<MIN>:<MAX>` posts to `columnSettings/columns/<id>` rather than replacing the whole column list; the dry run lists those follow-up writes with their own endpoint and body. Setting `visibleFor` alone leaves `visibleForProjectBased` true, which makes the group inert, so `--visible-for` and `--updateable-by` clear the matching flag with the group.

Name resolution is split from the write for both writes (`plan_create_board` / `plan_update_board`), so `--dry-run` prints the byte-exact body with the name-to-id work in a separate `resolved` block. Every name-taking flag refuses an ambiguous name and lists the candidates instead of guessing. The same sweep found two pre-existing silent picks in the resolvers these verbs depend on: `/api/groups` is polymorphic, so a `ProjectTeam` can share a name with a `NestedGroup`, and YouTrack does not enforce unique board names (probed: two creates with the same name both succeed), which meant `board delete` could have removed an arbitrary one of two. Both now error and name the candidates.

#YT-93
Claude-Run deleted branch feat/YT-93-board-crud 2026-08-06 13:21:02 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pandoras-box/youtrack-cli!148
No description provided.