Sub-issue of #138. Hardened spec — do not re-derive decisions. This umbrella introduces the azdo boards work-item relation subgroup beneath azdo boards work-item. Sibling umbrella: #138 itself.
Command Group Description
Create a relation subgroup beneath azdo boards work-item that centralises work-item link management flows. The group exposes the four Azure Boards work-item relation operations that map directly to the official AzDO Extension's boards work-item relation group (Python implementation at azure-devops/azext_devops/dev/boards/relations.py):
Each leaf is a thin JSON-Patch wrapper over workitemtracking.Client.UpdateWorkItem (for add and remove) and a thin read wrapper over workitemtracking.Client.GetWorkItem / GetRelationTypes (for show and list-type). The REST surface is Work Items - Update (REST 7.1) and Relation Types - Get (REST 7.1).
Implementation Notes
- Add
internal/cmd/boards/workitem/relation/relation.go that exposes NewCmd(ctx util.CmdContext) *cobra.Command.
- Register the new subgroup inside
internal/cmd/boards/workitem/workitem.go so that commands such as azdo boards work-item relation add are discoverable via the CLI hierarchy.
- Keep the short description focused on Azure Boards work-item relations; do not duplicate descriptions of the parent work-item group.
- The Python implementation calls the work item with
expand='All' after every write so that the response carries the populated relations array (with friendly names). We mirror this in all add/remove/show leaves.
- Each leaf command lives in its own subdirectory under
internal/cmd/boards/workitem/relation/<leaf>/<leaf>.go per AGENTS.md "New Subgroup Under Existing Group" guidance.
- The four leaves share a small helper at
internal/cmd/boards/workitem/relation/shared/relation.go that resolves a friendly relation-type name to its ReferenceName (mirroring get_system_relation_name in the Python source) and a second helper that fills friendly names in a *WorkItem's relations array (mirroring fill_friendly_name_for_relations_in_work_item). The helpers are owned by the umbrella and consumed by the leaves.
- The
add leaf additionally needs util.SplitAndTrimCSV (in internal/cmd/util/csv.go or a relation-shared CSV helper) to support both repeated-flag and comma-separated target lists. If the umbrella is implemented before util.SplitAndTrimCSV exists in the codebase, the add leaf's implementation must add it as a relation-shared helper at internal/cmd/boards/workitem/relation/shared/csv.go to keep the scope contained.
Command Wiring
- Implement the relation group in
internal/cmd/boards/workitem/relation/relation.go and ensure NewCmd only wires child commands under this package.
- Update
internal/cmd/boards/workitem/workitem.go to call cmd.AddCommand(relation.NewCmd(ctx)) so the work-item hierarchy exposes the relation subtree.
- Each leaf exports
NewCmd(ctx util.CmdContext) *cobra.Command from its own subdirectory.
- Run
make docs once wiring is complete to update generated documentation.
SDK / Client Requirements
- All four leaves rely on the Work Item Tracking client via
ClientFactory().WorkItemTracking(...).
- The
add and remove leaves additionally call GetWorkItem and GetRelationTypes for friendly-name resolution and target validation.
- No new client methods are required:
UpdateWorkItem, GetWorkItem, GetRelationTypes are all in the vendored SDK (vendor/.../v7/workitemtracking/client.go:205, 137, 113).
Tooling & Validation
- Format new Go code with
gofmt/goimports.
- Run
go build ./cmd/azdo/... to ensure the CLI compiles with the new wiring.
- Add/update hermetic tests and execute
go test ./... (include documentation regeneration in the validation checklist).
- Per AGENTS.md, do not regenerate mocks:
internal/mocks/workitemtracking_client_mock.go already contains the GetWorkItem, GetRelationTypes, and UpdateWorkItem mocks (lines 849, 669, 1358).
Sub-Issues
References
Sub-issue of #138. Hardened spec — do not re-derive decisions. This umbrella introduces the
azdo boards work-item relationsubgroup beneathazdo boards work-item. Sibling umbrella: #138 itself.Command Group Description
Create a
relationsubgroup beneathazdo boards work-itemthat centralises work-item link management flows. The group exposes the four Azure Boards work-item relation operations that map directly to the official AzDO Extension'sboards work-item relationgroup (Python implementation atazure-devops/azext_devops/dev/boards/relations.py):azdo boards work-item relation add— attach a relation to a work item (Implementazdo boards work-item relation addcommand #272)azdo boards work-item relation list-type— list the relation types supported in the organization (Implementazdo boards work-item relation list-typecommand #273)azdo boards work-item relation remove— detach a relation from a work item (Implementazdo boards work-item relation removecommand #274)azdo boards work-item relation show— list all relations of a work item (Implementazdo boards work-item relation showcommand #275)Each leaf is a thin JSON-Patch wrapper over
workitemtracking.Client.UpdateWorkItem(foraddandremove) and a thin read wrapper overworkitemtracking.Client.GetWorkItem/GetRelationTypes(forshowandlist-type). The REST surface is Work Items - Update (REST 7.1) and Relation Types - Get (REST 7.1).Implementation Notes
internal/cmd/boards/workitem/relation/relation.gothat exposesNewCmd(ctx util.CmdContext) *cobra.Command.internal/cmd/boards/workitem/workitem.goso that commands such asazdo boards work-item relation addare discoverable via the CLI hierarchy.expand='All'after every write so that the response carries the populatedrelationsarray (with friendly names). We mirror this in alladd/remove/showleaves.internal/cmd/boards/workitem/relation/<leaf>/<leaf>.goper AGENTS.md "New Subgroup Under Existing Group" guidance.internal/cmd/boards/workitem/relation/shared/relation.gothat resolves a friendly relation-type name to itsReferenceName(mirroringget_system_relation_namein the Python source) and a second helper that fills friendly names in a*WorkItem'srelationsarray (mirroringfill_friendly_name_for_relations_in_work_item). The helpers are owned by the umbrella and consumed by the leaves.addleaf additionally needsutil.SplitAndTrimCSV(ininternal/cmd/util/csv.goor a relation-shared CSV helper) to support both repeated-flag and comma-separated target lists. If the umbrella is implemented beforeutil.SplitAndTrimCSVexists in the codebase, theaddleaf's implementation must add it as a relation-shared helper atinternal/cmd/boards/workitem/relation/shared/csv.goto keep the scope contained.Command Wiring
internal/cmd/boards/workitem/relation/relation.goand ensureNewCmdonly wires child commands under this package.internal/cmd/boards/workitem/workitem.goto callcmd.AddCommand(relation.NewCmd(ctx))so thework-itemhierarchy exposes the relation subtree.NewCmd(ctx util.CmdContext) *cobra.Commandfrom its own subdirectory.make docsonce wiring is complete to update generated documentation.SDK / Client Requirements
ClientFactory().WorkItemTracking(...).addandremoveleaves additionally callGetWorkItemandGetRelationTypesfor friendly-name resolution and target validation.UpdateWorkItem,GetWorkItem,GetRelationTypesare all in the vendored SDK (vendor/.../v7/workitemtracking/client.go:205, 137, 113).Tooling & Validation
gofmt/goimports.go build ./cmd/azdo/...to ensure the CLI compiles with the new wiring.go test ./...(include documentation regeneration in the validation checklist).internal/mocks/workitemtracking_client_mock.goalready contains theGetWorkItem,GetRelationTypes, andUpdateWorkItemmocks (lines 849, 669, 1358).Sub-Issues
azdo boards work-item relationsubgroup wiringazdo boards work-item relation addcommand (Implementazdo boards work-item relation addcommand #272)azdo boards work-item relation list-typecommand (Implementazdo boards work-item relation list-typecommand #273)azdo boards work-item relation removecommand (Implementazdo boards work-item relation removecommand #274)azdo boards work-item relation showcommand (Implementazdo boards work-item relation showcommand #275)References
transform_work_item_relations,transform_work_item_relation_type_table_output)expand: relationsparameter on the read tool is the only relation handling — no dedicated relation tool exists. Reference: https://github.com/microsoft/azure-devops-mcp/blob/main/src/tools/work-items.ts7.1-preview.3), Relation Types - Get (GET, API version7.1-preview.2)azdo boards work-itemcommand group #138.