Skip to main content

Scope Context and Filtering

Much of the Agility application is looking at work through a subset of the Scope tree — a scope context. Understanding it explains a lot of filtering behaviour, and gives you the same idioms the product uses.

First, a naming note: the Scope asset type has worn two display names — Project originally, and mostly Planning Level in current versions. All three words mean the same asset type.

What a Scope Context Is​

A scope context is the set of scopes defined by:

  1. a root scope — the context includes it and its subtree, and
  2. optional narrowing by Schedule and ScopeLabels — keeping only subtree scopes on a given sprint schedule, or carrying a given label. (ScopeLabel is displayed in the UI as Program — another naming split worth knowing.)

The One-Query Idiom​

The subtree-membership filter from Relations takes the narrowing inside its bracket filter — and with variables keep the values out of the expression:

{
"from": "Story",
"filter": ["Scope.ParentMeAndUp[Schedule=$Sched;ScopeLabels=$Label]=$Scope"],
"select": ["Number", "Name", "Scope.Name"],
"with": {
"$Sched": "Schedule:1064",
"$Label": "ScopeLabel:2001",
"$Scope": "Scope:1308"
},
"page": { "size": 50, "start": 0 }
}

Read it as: the story's scope has, among its ancestors-or-self that are on $Sched and carry $Label, the root $Scope — i.e. the story is in the narrowed subtree. Drop either bracket term if you are not narrowing by it.

The Precompute Pattern for Large Hierarchies​

When the scope tree is large, evaluating the traversal per asset gets expensive. It is often more efficient to build the scope context once, then filter assets against the set — and with variables accept arrays, which the filter treats as an in-list match:

{
"from": "Scope",
"filter": ["ParentMeAndUp=$Root", "Schedule=$Sched"],
"select": ["Name"],
"with": { "$Root": "Scope:1308", "$Sched": "Schedule:1064" },
"page": { "size": 200, "start": 0 }
}
{
"from": "Story",
"filter": ["Scope=$Context"],
"select": ["Number", "Name"],
"with": { "$Context": ["Scope:1308", "Scope:1450", "Scope:1451"] },
"page": { "size": 50, "start": 0 }
}

The same array-variable technique works on query.v1 and the Bulk API's query command.

Rooms Are Scope Contexts​

One of the most important things a Room — TeamRoom or PlanningRoom — represents is a scope context: its Scope and Schedule define the slice of the tree the room looks at.

Visibility follows from that in a way worth stating precisely:

  • Every member can view every room — rooms themselves are not permission-gated.
  • What a member sees inside a room is gated by their scope access — the room shows each viewer the intersection of its scope context with the scopes their role grants them.

Two members can open the same room and see different content; neither is broken.