> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nextedy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scoping and Filtering Project Swimlanes

> A deep dive into how Nextedy PLANNINGBOARD's Project assignment mode scopes which sub-projects appear as swimlanes using the Project Query parameter, and what changes once a board spans multiple projects.

This page is a deep dive into [Project Mode](/planningboard/concepts/assignment-modes) swimlane scoping — how a board that spans multiple Polarion projects controls exactly which projects appear, and what else changes once it does.

***

## Scoping with Project Query

Project Mode's swimlane list isn't limited to "every sub-project in the current group." The **Project Query** widget parameter is a Lucene query, evaluated once per board load, that defines exactly which projects belong on the board. Set it to describe the projects you're planning for, and only those appear.

Project Query filters three things at once, from the same query:

* Which projects show up as swimlanes.
* Which work items get loaded onto the board.
* Which Plans appear as columns.

The unplanned-items sidebar respects it too. Because the scope lives in the query rather than in the page the widget is embedded on, the same board keeps working even if projects are later reorganized into different project groups.

<Note>
  If no Project Query is set, the board falls back to discovering sub-projects of the current project group, as described in [Project Mode](/planningboard/concepts/assignment-modes). Setting Project Query explicitly is recommended for any board meant to keep tracking a specific, fixed set of projects.
</Note>

### Query Examples

| Goal                                        | Query                                  |
| ------------------------------------------- | -------------------------------------- |
| Only projects with "Team" in the name       | `name:*Team*`                          |
| A fixed, small set of projects              | `id:(team-alpha team-beta team-gamma)` |
| Every project whose ID starts with a prefix | `id:squad-*`                           |
| Combine conditions                          | `name:*2025* AND id:proj-*`            |
| Everything except one project               | `name:*Team* AND NOT id:team-archived` |

Any indexed project field can be used — not just `id` and `name` — including custom project fields.

<Tip>
  Changing the Project Query re-computes swimlanes, loaded work items, and the dependency/parent role menus (below) immediately — there's nothing else to refresh.
</Tip>

***

## Filtering with a Page Parameter

To let planners choose the projects themselves — rather than editing a fixed query each time — Project Query can be driven by a page parameter instead of a literal string.

This starts with a page parameter that lets planners pick one or more projects — for example, one named `Projects`, added via the page's **Parameters** flyout (gear icon). Its type is typically Enumeration, so people can select from real Polarion projects rather than typing IDs.

Unlike the general work-items **Query** field, which accepts Velocity syntax typed directly into the field, **Project Query does not** — typing a page-parameter reference straight into it does not work. Project Query only supports binding to a page parameter through the gear icon, and only to a **String**-typed parameter. `Projects` itself, being Enumeration-type, isn't String-typed, so it can't be bound directly either — it never appears in that gear icon's list at all.

The fix is a **Page Script** that reads `Projects`, computes the full query clause as a string, and exposes it as a new scripted parameter:

```velocity theme={null}
#set($projectsQuery = "")
#if($pageParameters.Projects && !$pageParameters.Projects.values().isEmpty())
  #set($ids = $pageParameters.Projects.toLucene())
  #set($projectsQuery = "id:($ids)")
#end
$!scriptedPageParameters.put("projectsQuery", $factory.string("Projects Query").value($projectsQuery).build())
```

Then click the gear icon on **Project Query** → **Parameters**, and select **Projects Query** — the scripted parameter, not the raw project-picker parameter.

<Note>
  The scripted parameter's value becomes the *entire* content of the Project Query field — there's no surrounding `id:(...)` for it to slot into. Compute the complete clause, including the field prefix, inside the Page Script itself; don't expose just the bare `.toLucene()` output.
</Note>

<Note>
  The page parameter's selectable projects still need to fall within **Scope** — Scope restricts the searchable project set before Project Query ever runs. A project outside Scope never appears, no matter what Project Query says.
</Note>

<Info>
  The `id:` field prefix used above has not been independently confirmed against a live Project Query field — it's inferred from the static query examples elsewhere on this page, which query project documents directly. A related, more general Planningboard query field uses `project.id:` instead (see [Work Items Parameters](/planningboard/reference/widget-parameters/work-items-parameters)), which filters work items rather than projects. Confirm which prefix Project Query actually expects before relying on this in production.
</Info>

***

## Cross-Project Board Behavior

### Dependency and Parent Role Menus

Two menus need to work across every project a board shows: **Work Items → Dependency Roles** and **Unplanned Sidebar → Parent Roles**. Each Polarion project can define its own `workitem-link-role` enumeration, which replaces the global one — so the same logical role (e.g. "depends on") can have a different internal ID per project.

Both menus are built from the union of link roles across every project the board currently shows, so a role from any in-scope project can be selected, regardless of which project's page the board lives on.

How roles are labelled:

* Options are keyed by role **ID**, titled by role **name**.
* If multiple projects use the same ID with different names, they collapse into one option listing all names joined by `/` — e.g. `depends on / requires`.
* If a role has no name anywhere, its ID is shown as the title.
* Once more than one project is in scope, a selected role's ID is appended in parentheses — `depends on (depends_on)` — so overlapping names stay distinguishable. Only selected roles get this treatment, to keep the rest of the list readable.

See [Dependencies and Links](/planningboard/concepts/dependencies) for the general link/dependency model this builds on.

### Swimlane Order

Project Query is a pure include/exclude filter — it doesn't control order. Swimlanes are ordered the same way projects appear in the Polarion project tree (the project group hierarchy), and the query is applied after that order is resolved.

For example, if a group contains `[alpha, beta, gamma, delta]` in that order and the query matches `[beta, delta]`, the swimlanes appear as `beta | delta` — in hierarchy order, not query-match order.

<h3 id="merged-iteration-release-columns">
  Merged Iteration/Release Columns
</h3>

Say two projects each run a Plan with the same plan ID — `Iteration_35`. The board's column key used to combine the project with the plan (effectively `alpha/Iteration_35` vs. `beta/Iteration_35`), so two projects sharing a plan ID produced two separate columns with the same name — and the more projects on the board, the more duplicate columns piled up.

Plans that share the same plan ID now collapse into a single column, regardless of how many projects define them:

* One column per iteration/release ID, however many projects run it.
* A work item still belongs to the Plan of its own project — it shows up in the merged column, in its own project's swimlane row.
* Dropping a card into a merged column plans it into that project's own Plan with that ID; nothing is written to other projects' Plans.
* Matching is on the full plan ID, not a prefix — `Iteration_35` and `Iteration_350` stay separate columns.

***

## Common Misconceptions

**"Which projects appear is decided by where the widget is placed."** Only when Project Query is left empty. Placement (inside a project, inside a project group, or at global scope) is a fallback default, not the primary mechanism — Project Query is what actually controls scope.

**"Project Query and Scope are the same setting."** They aren't. Scope restricts the searchable project set before Project Query ever runs; Project Query then filters within whatever Scope allows. A project excluded by Scope never appears, regardless of what Project Query says.

**"Project Query controls the order swimlanes appear in."** It doesn't — it's a pure include/exclude filter. Order always follows the Polarion project group hierarchy, applied after the query has already narrowed the set.

**"Two projects with a plan of the same ID always produce duplicate columns."** Not anymore. Plans sharing the same plan ID collapse into a single column regardless of how many projects define them — see Merged Iteration/Release Columns above.

***

## Related Concepts

* [Swimlane Assignment Modes](/planningboard/concepts/assignment-modes) — the full set of assignment types, including Project mode's basics
* [Dependencies and Links](/planningboard/concepts/dependencies) — the general link/dependency model referenced above
* [Plans Modes](/planningboard/concepts/plans-modes) — how Plan columns are organized, independent of swimlane rows
