Value Stream Analytics

Value Stream Analytics traces each work item’s journey from creation to completion, measuring how long work spends in development, code review, merge, and testing phases. It combines data from your issue tracking system (Jira, Azure DevOps, or GitHub) with Git activity from GitLab and GitHub into a single timeline so you can see exactly where time is spent — and where it gets stuck.

Use it to answer questions like:

  • How long does it take our team to ship a typical story?
  • Are merge requests sitting in review for days before anyone looks at them?
  • Which epic has the longest cycle time, and what is causing the delay?

Every provider renders the same unified page: the only thing that changes between Jira, Azure DevOps, and GitHub is how you select the items to analyze. Everything below the header bar — the summary cards, the issue table, the expandable cycle-time detail, and the AI analysis — works identically for all three sources.


Getting Started

Navigate to Value Stream in the sidebar. If more than one issue tracking provider is configured, a submenu lets you choose between them:

Each provider requires at least one Git source to be configured and synced as well:

  • GitLab and/or GitHub — provides development events (commits, branches, merge requests, code reviews).

If no Git source is connected, the report will still run but the development, review, merge, and QA metrics cannot be measured.

The Value Stream entry is only shown in the sidebar when at least one provider has its Use as issue management system toggle enabled in Settings → Data Sources. If no provider has this toggle on, the menu entry is hidden; navigating to the page directly will show a short message with a link to the settings page. The same toggle is also used by Issue Hierarchy and Worklog.

The Header Bar

The bar at the top of every value-stream page follows the same fixed layout for all three sources:

[ source-specific query controls ] [ Load ] [ Show / Hide parents ] [ ✨ Analyze with AI ▾ ]

  • Load runs the report: it fetches the matching items, resolves their parent-child hierarchy, collects all related activity events from every configured data source, and computes cycle-time metrics. The results appear immediately below. Pressing Enter in the query input does the same.
  • Show / Hide parents controls whether ancestor-context rows (parent items pulled in only to give a matched child its place in the tree) are included. See Show / Hide Parents below. The control is disabled for sources where it has no effect.
  • Analyze with AI queues a background job that assembles the structured data and sends it to the configured LLM provider (Claude or OpenAI) for a written analysis, then opens that job’s progress page in a new tab. See AI Analysis below. When prompt debugging is enabled for your organization, a small chevron next to the button reveals a Generate Prompt option that shows the exact prompt that would be sent, without calling the model. Prompt preview is immediate rather than queued: the prompt is rendered inline in a Prompt Preview card above the results — with its estimated token count and a Regenerate control — rather than in a separate window. The card belongs to that visit: leaving the page and coming back does not rebuild it, so use Generate Prompt again when you want it.

URL parameters update as you interact with the controls, so you can bookmark or share a specific report configuration. Once an AI analysis has been queued, the URL records that it ran rather than the request to run it, so returning to the page — or opening a bookmarked or shared link — never starts another analysis. See AI Analysis.

The query controls themselves differ by source:

Jira

Two modes, selectable from a dropdown:

  • JQL — type a Jira Query Language expression directly (e.g. project = PROJ).
  • Filter — select from your organization’s saved Jira filters. The dropdown is searchable — start typing to narrow the list. Only the filter id is stored in the URL; the live JQL is resolved on every load, so a filter whose definition changes in Jira is never served stale.

Jira records both planned and actual effort, so its table includes the Estimate and Time Logged columns. Jira queries can also pull in ancestor-context rows, so the Show / Hide parents toggle is active.

Azure DevOps

A two-step selector:

  1. Project — pick the Azure DevOps project to report on. All projects accessible to the configured service account are listed.
  2. Query (optional) — type a WIQL filter expression to narrow the work items returned (e.g. [System.WorkItemType] = 'Bug'). If left empty, the project’s full backlog is used.

Azure DevOps returns only the work items that match the query — there is no ancestor context to add or remove — so the Show / Hide parents toggle is rendered disabled.

Project dropdown is empty? The configured service account has no accessible projects, or the Azure DevOps Personal Access Token (PAT) does not have the Work Items (Read) scope. Check your PAT permissions in Settings → Data Sources → Azure DevOps.

WIQL query error? Verify the expression syntax against the WIQL reference. Common mistakes: field names must use the internal [System.FieldName] format, string values must be single-quoted, and IN lists must use comma separation inside parentheses.

GitHub

Two controls:

  1. Repository — pick a repository from the dropdown. If the configured token cannot list repositories (for example, a token without the repo scope), the dropdown becomes a free-text box so you can type an owner/repo slug by hand to qualify bare issue numbers.
  2. Issue numbers — a list of issue numbers, e.g. 42, 43. Bare numbers are qualified with the selected repository; fully-qualified owner/repo#N keys are accepted verbatim, so you can analyze issues across several repositories in one report.

GitHub correlates development activity to issues through github_issue_refs (PRs and commits that reference an issue). When Show parents is on, GitHub now also pulls in the ancestor (epic / parent issue) of each entered issue, the same context Jira includes by default.


Understanding the Report

Summary Panel

Two cards appear at the top of the report:

Aggregate Metrics shows a quick overview of the result set:

MetricDescription
Issues analyzedTotal number of items returned by the query
CompletedItems whose status is Done, Closed, Resolved, or Completed
Avg cycle timeAverage total cycle time across all issues with metrics
Avg dev timeAverage development phase duration
Avg review waitAverage time from MR/PR ready for review to first review comment or approval
Avg review timeAverage time from first review to approval or merge
Avg merge timeAverage time from approval to merge
Avg QA timeAverage time in testing/QA phase

Longest Cycle Times lists the three items with the highest total cycle time. Click any of them to scroll directly to that issue in the list below.

Work Item List

Below the summary, work items are displayed in a grid with the following columns. The same column set is used for every source, except that the two effort columns appear only where the source supplies them — Estimate for Jira, GitLab and Azure DevOps, and Time Logged for Jira and GitLab. Azure DevOps therefore shows an Estimate and no Time Logged; GitHub shows neither.

ColumnDescription
KeyThe source identifier — Jira key (PROJ-123), Azure DevOps work item id (#123), or GitHub issue (#42). Links to the source system when a URL can be built.
TitleThe item summary. Resolved items are shown struck through.
TypeThe item type (e.g. Epic, Story, Bug, User Story).
StatusThe current workflow status shown as a badge.
ProgressFor parent items, a progress bar showing how many children are completed out of the total (e.g. 3/5).
AssigneeThe current assignee, when known.
Estimate(Jira, GitLab, Azure DevOps.) Planned effort on the item; parent rows show a Σ-prefixed roll-up of the row’s own estimate and all its descendants’.
Time Logged(Jira, GitLab.) Time logged against the item; parent rows show a Σ-prefixed roll-up of the row’s own logged time and all its descendants’.
EventsThe number of correlated activity events. Parent rows show the merged count of their own events plus all descendants.
Cycle TimeThe total cycle time for the item. Parent items show an aggregated span value (see Parent Metric Aggregation below).
Details toggleClick the chart icon to expand the detail view for that item.

Items are organized in a tree structure based on parent-child relationships (Jira epics/stories; ADO epics/features/user stories; GitHub parent issues / sub-issues). Parent items can be collapsed or expanded by clicking the chevron. Children appear indented beneath their parent.

Show / Hide Parents

When a query matches a child but not its parent, the parent is still useful as context — it shows where the matched work sits in the tree. The Show / Hide parents control in the header bar decides whether those ancestor-context rows are included:

  • Show parents (default) — ancestor rows are included so each matched item appears under its epic/parent.
  • Hide parents — only items that directly match the query are shown; ancestors are dropped and matched items become the top-level roots.

This toggle is meaningful for Jira and GitHub, both of which can pull in ancestor context. Azure DevOps returns only the items its query matched, so the toggle is rendered disabled there.

Detail View

Expanding any item reveals two sections:

Cycle Metrics Bar — a color-coded horizontal bar that visualizes how the total cycle time breaks down across phases:

ColorPhase
BlueDevelopment
AmberReview wait
PurpleReview
GreenMerge
OrangeQA / Testing

A legend below the bar shows each phase with its duration. Phases with zero duration are omitted.

The bar is also a filter: click a segment (or its legend entry) to narrow the timeline below to only the events that fall within that phase. The selected phase is highlighted while the others dim; click it again to clear the filter and show the full timeline.

Timeline — a chronological list of every event associated with the item. Each entry shows the timestamp, source tag (Jira, ADO, GitLab, or GitHub), event type, the person who performed the action, and a detail summary. For example:

2026-02-06 03:57 [GitLab] Commit pushed: feat: Add startup options (+75 -3)
2026-02-06 05:01 [Jira] Issue assigned: Assigned to a team member

Parent Metric Aggregation

When a parent issue (such as an epic) has children, its cycle time is computed as the span of all descendant events — not an average. The system collects every event from the parent and all of its children and grandchildren, merges them into a single chronological timeline, and then computes cycle metrics from that combined sequence.

This means a parent’s total cycle time reflects the wall-clock time from when the first child started work to when the last child was completed. The cycle time column shows the label “span” to distinguish this from a leaf issue’s own metrics.


Cycle Time Metrics

Each item’s cycle time is broken into five phases that together make up the total. The start and end points of each phase are determined by specific events in the issue’s timeline:

MetricStarts whenEnds when
Total cycle timeIssue moves to “In Progress” or “In Development” (or first commit if no status change)Issue is closed, resolved, or completed
Dev timeSame as total cycle time startMR/PR is marked ready for review (falls back to last commit before first review, then MR/PR creation)
Review waitMR/PR is marked ready for review (falls back to last commit before first review, then MR/PR creation)First review comment is posted (or MR/PR is approved, if no comments)
Review timeFirst review commentMR/PR is approved (or merged, if no explicit approval)
Merge timeMR/PR is approvedMR/PR is merged
QA timeMR/PR is merged, or issue status changes to a testing phase (whichever comes first)Issue is closed, resolved, or completed

QA status detection — the following statuses are recognized as the start of a QA/testing phase: In Test, In Testing, Testing, In QA, QA, Ready for Test, Ready for Testing, Ready for QA. Status matching is case-insensitive. For Azure DevOps the same keywords are matched against the work item’s state field.

If an issue’s workflow skips a phase entirely (for example, a merge request is merged without a separate approval step), that phase will show as empty (–) in the metrics table and will not appear in the cycle metrics bar.

Event Types

Value Stream Analytics recognizes the following events from each data source:

Jira events:

EventDescription
Issue createdA new issue was created
Issue assignedThe issue was assigned or reassigned
Status changedThe issue’s workflow status changed (e.g., To Do to In Progress)
Issue commentedA comment was added to the issue
Issue resolvedThe issue was marked as resolved
Issue closedThe issue was closed

GitLab / GitHub events:

EventDescription
Branch createdA new branch was created
Commit pushedOne or more commits were pushed (includes lines added/removed)
MR/PR createdA merge request or pull request was opened
MR/PR marked readyA draft MR/PR was marked as ready for review
Review commentA reviewer left a comment on the MR/PR
MR/PR approvedThe MR/PR was approved
MR/PR mergedThe MR/PR was merged

Azure DevOps events:

EventDescription
Work item createdA new work item was created
Work item assignedThe work item was assigned or reassigned
Status changedThe work item’s workflow state changed (e.g., New to Active)
Work item commentedA comment was added to the work item
Work item resolvedThe work item was marked as resolved or closed

Events are matched to issues and work items differently depending on the source:

  • Jira — Git events are matched by Jira issue keys found in commit messages, branch names, and MR/PR titles and descriptions.
  • Azure DevOps — Git events are matched by ADO work item IDs embedded by the Azure DevOps integration when a branch or pull request is linked to a work item in ADO, and by the AB#123 smart-commit reference (e.g. Fixes AB#123) in a commit message. A bare #123 is not recognized — Azure DevOps only auto-links the AB# form.

How the Jira analysis is assembled

When you run a Jira value stream report, ActivityPulse fetches each issue’s full change history live from Jira at that moment and merges it with Git events (commits, merge/pull requests, reviews) collected from your synced GitLab and GitHub sources. The two are linked by Jira issue keys found in commit messages, branch names, and MR/PR titles and descriptions.

Because the Jira side is read live, the report always reflects the issue’s current status and complete transition history — you do not need to wait for a scheduled sync. The Git side, however, only appears if GitLab/GitHub has been synced and the work carries the Jira key. Running a report over a very large issue set issues many live calls to Jira and may be slower or hit rate limits; narrow the query if a report is slow.

Status names recognized for Jira

Phase boundaries are detected from Jira status names. The recognized names are fixed and case-insensitive, but they are not configurable:

BoundaryRecognized Jira statuses
Work started (begins dev time / total cycle time)In Progress, In Development
QA / testing startedIn Test, In Testing, Testing, In QA, QA, Ready for Test, Ready for Testing, Ready for QA
Completed (ends total cycle time)Done, Closed, Resolved — or any transition that sets a Jira resolution

If your workflow uses different names for the active phase (for example “Doing”, “Development”, or “Started”), no “work started” milestone is detected and the cycle/dev clock falls back to the first commit instead. An issue with a custom active-status name and no linked Git activity will show no cycle time. Likewise, an issue that reaches a custom terminal status without a resolution being set is treated as still in progress.

To get accurate Jira metrics: map your workflow’s active state to a status named “In Progress” or “In Development”, use the listed QA names for any testing column, and ensure your Done transition either uses a Done/Closed/Resolved status or sets a resolution. Where renaming statuses is not an option, rely on the Git-derived phases (dev/review/merge), which do not depend on Jira status names.


AI Analysis

The Analyze with AI button generates a written report by sending the full structured data — issue hierarchy, timelines, metrics, and associated merge requests — to the configured LLM provider.

The analysis runs as a background job, so you are not left waiting on a page that may time out. When you click the button:

  1. The value stream page confirms the analysis is queued and opens the job’s progress page in a new tab. If your browser blocks the new tab, use the View progress link on the value stream page instead. The same card carries a Run again control that queues a second analysis over the identical query.
  2. The progress page shows the job moving through queuedrunningdone, with a Cancel button while it is still in flight.
  3. When the job finishes, the finished report appears on that same page, with the same Export and Share controls described below.

Returning to the value stream page — with the browser’s Back button, by reloading it, or by opening a link to it you saved earlier — brings back the “Value stream analysis queued” card for the analysis you already started, with its View progress and Run again controls. It does not start a second one. Only the buttons queue an analysis, so no link can start one on your behalf, and none of your saved links spends model time when you open it.

If you share such a link with a colleague, they see the same query and the same card, but its View progress link only opens for you and for organization administrators — a job’s progress page is visible to the person who started it. Their Run again queues an analysis of their own.

Large analyses take minutes of model time, which is why they run in the background: a slow provider no longer fails the request, and a timed-out or briefly unavailable provider is retried automatically with a longer allowance on each attempt. Each attempt also has an overall time budget, so that one analysis can never block others indefinitely. A very large report — hundreds of issues against a slow issue tracker — can exhaust it; the job retries with a larger budget, and if it still does not finish it is reported as failed. Narrowing the query, by selecting fewer issues or a shorter period, is the reliable fix. Queued and completed analyses are also listed under Settings > Job Queue (see Job Queue).

Queueing is capped at five analyses per minute for each data source in your organization. This is a shared budget: colleagues queueing analyses against the same source draw on it too. Past the cap the button reports Rate limited with the number of seconds to wait, nothing is queued, and analyses for your other data sources are unaffected. The cap protects the interactive Load button from being starved by a backlog of queued analyses — both draw on the same allowance against the source system.

The AI analysis typically covers:

  • Cycle time breakdown and bottleneck identification — which phases are taking the longest and which issues are most affected.
  • Code review effectiveness — how quickly reviews happen, whether reviews are thorough or rubber-stamped.
  • Development patterns — commit frequency, branch strategies, and collaboration signals.
  • Risk assessment — issues that have been in progress for an unusually long time or are missing expected events.
  • Recommendations — specific, actionable suggestions to improve delivery speed and quality.

An LLM provider (Claude or OpenAI) must be configured in Settings > LLM for this feature to work. If no provider is configured, the button will not be available.

Scale limits — the AI analysis has the following built-in limits to stay within LLM context windows:

  • A per-request item cap: 100 work items for Azure DevOps, 500 issues for Jira, GitHub, and GitLab. Queries returning more are rejected with an error; narrow the query or split it into smaller batches.
  • Up to 500 timeline events per work item are sent to the LLM. Items with very long histories will include a note indicating how many events were omitted.
  • The total formatted input is capped at approximately 100,000 tokens (~400,000 characters). When this limit is reached, later work items in the list are omitted and a truncation notice is appended to the output.
  • The LLM response is capped at 4,096 tokens by default. If the analysis appears cut off mid-sentence, the response limit was hit; this can be increased under Settings > LLM → Max response tokens.

The quality of the analysis depends on the volume and richness of the underlying data. Ensure your data sources are synced and the query covers enough history to give the LLM meaningful patterns to work with.

Customizing the Analysis Prompt

The instructions that frame the AI analysis — what to look for, how to structure the report, which terminology to use — come from a prompt template you can edit under Settings > LLM → Value Stream Prompts.

Each data source has its own prompt, selected with the tabs at the top of the card. They are separate because the systems use different vocabulary — work items and pull requests in Azure DevOps, issues and merge requests in GitLab — and a report written in the wrong system’s language is harder to read and easier to mistrust. Editing one source’s prompt never changes the others.

You only see tabs for the sources your organization actually uses. A source gets a tab when it supports value stream analysis, it is enabled, and its Use as issue management system toggle is on — the same rule that decides whether the source appears in the Value Stream menu. So an organization that only uses GitHub sees one tab, not one for every system ActivityPulse can analyze.

To customize a prompt:

  1. Open Settings > LLM and find the Value Stream Prompts card.
  2. Select the tab for the data source you want to change. The editor starts filled with the built-in prompt for that source, so you can adjust it rather than write one from scratch.
  3. Edit the text and choose Save prompt.

If the card says no Value Stream provider is enabled, no source is currently eligible — configure or enable one under Settings > Data Sources first.

A Using default badge on the editor means that source has no customization and uses the built-in prompt. To go back, choose Reset to default and confirm — this discards your custom prompt for that source only.

A few things worth knowing:

  • Saving a prompt that is identical to the built-in one is treated as “use the default”, so the badge reappears.
  • Disabling a data source, or turning off its Use as issue management system toggle, hides its tab but does not delete the prompt you saved for it. Re-enable the source and the tab returns with your customization intact.
  • The prompt is combined with the value stream data at generation time. A very long prompt eats into the ~100,000 token input budget described above.
  • These prompts apply only to value stream reports. Activity summaries are framed by a separate template under Summary Prompts on the same settings page (see Activity Summaries).

Exporting and Sharing an AI Analysis

Once an AI analysis has finished, these controls appear in the header of the analysis card on the job’s page:

  • Export opens a menu with three formats:

    • PDF — a polished document, best for printing or archiving.
    • HTML — a self-contained page that renders in any browser or email client.
    • Markdown — the source format, easy to edit or paste elsewhere.

    The file downloads immediately. Its name follows the pattern value-stream-analysis[-<label>]-<date>.<ext> — the optional label is the analysis scope label, and <date> is the analysis period as YYYYMMDD-YYYYMMDD (or the generation date as YYYYMMDD when the analysis has no period).

  • Share opens a dialog for emailing the analysis to a colleague. You can:

    • Enter a recipient email address (required) and an optional recipient name.
    • Add an optional short note for the recipient.
    • Choose which formats to attach (PDF, HTML, Markdown — at least one is required). Each selected format is attached as a separate file.
  • The chevron at the far right collapses or expands the analysis card.

To produce a fresh analysis over the same data, use Run again on the “Value stream analysis queued” card on the value stream page. It queues a second job and opens that job’s progress page, exactly like the original run. Clicking Analyze with AI again only starts another job once the query or the Show / Hide parents setting has changed. Either way, earlier reports are never replaced — they stay reachable from Settings > Job Queue.

The job page itself has no re-run control: it shows a finished report with no query behind it, so re-running belongs on the value stream page where the query is still on screen.

Sharing uses the SMTP or Microsoft 365 email transport configured for your organization (see Email Configuration). The analysis text shown on screen is exactly what is rendered into the exported and emailed files.