AgentStack
SKILL verified Apache-2.0 Self-run

Flow Metrics

skill-eugenelim-agent-ready-repo-flow-metrics · by eugenelim

Use this skill when the user asks for DORA / Flow Framework metrics over a Jira scope -- "what's our cycle time this quarter for PROJ", "give me throughput and WIP for the Foo team", "compare flow efficiency before/after the AI-pairing rollout via a cohort split", "rollup flow metrics across program 42". Computes cycle time, lead time, throughput, WIP, flow load, rework rate, flow efficiency, flo…

No reviews yet
0 installs
14 views
0.0% view→install

Install

$ agentstack add skill-eugenelim-agent-ready-repo-flow-metrics

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Flow Metrics? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Skill: flow-metrics

This skill is the one place to compute Flow Framework / DORA-style metrics over a Jira scope. It composes two upstream skills and emits a canonical JSON / CSV / JSONL block; it does not invent new tracker verbs or replicate them inline.

  • jira skill (sibling in this pack) — every Jira read: check,

whoami, get-issue, search, get-project, plus a tightly- allowlisted set of raw GET paths for the custom-field catalog, project-status enumeration, and per-issue changelog pagination.

  • jira-align skill (sibling in this pack) — used only for

--program-id / --portfolio-id scope, and only for the four team / program / portfolio enumeration paths. Time-in-state numbers always come from Jira's changelog.

The pipeline (config validation, scope JQL, changelog walk, per-issue derivation, aggregation, cohort split, per-team rollup, notes, meta, output rendering, caching) lives in scripts/flow_metrics/. This SKILL.md tells the agent how to invoke the CLI for common flows; for design details, read the inline module docstrings.

Cross-skill invocation — name, not path

This skill names sibling skills (jira, jira-align) by their name: field, never by path. Install locations vary by IDE and scope, and skills can be renamed at install time. The agent's harness resolves the name to whatever location the user picked. If you find yourself writing a hardcoded skill path, stop — look up the skill by name instead.

Install guidance for the named dependencies lives in manifest.json under deps.skills — that's a where to get them hint, not a runtime path.

Prerequisites

Before computing metrics, confirm:

  1. The jira skill is installed and authenticated. Invoke it:

jira: check. Exit 0 → proceed. Exit 2 → tell the user to run credential-setup skill themselves; do not attempt to read ~/.agentbundle/credentials.env from this skill.

  1. For program / portfolio scope, the jira-align skill is installed

and authenticated. If --program-id or --portfolio-id is in play and jira-align: check fails, exit 3 and surface upstream stderr verbatim.

  1. The Jira team_field.id you've configured (default

customfield_10001 in the shipped state config) exists in this instance's field catalog. If it doesn't, the skill exits 2 at startup naming the missing field.

Invocation

The skill ships one CLI. Two equivalent forms (both call the same flow_metrics.main):

# Installed package — exposes a `flow-metrics` shim on PATH:
flow-metrics --project PROJ

# Or any environment where the package is on PYTHONPATH:
python -m flow_metrics --project PROJ

The spec's examples use the bare flow-metrics form. From a working copy of this pack, add the package to PYTHONPATH first:

export PYTHONPATH="$(pwd)/scripts:$PYTHONPATH"
python -m flow_metrics --help

Every example below uses the bare form; substitute python -m flow_metrics if you're invoking from a clone.

CLI flags

The full flag surface:

  • --project KEY — Jira project key. Mutually exclusive with

--program-id / --portfolio-id.

  • --team NAME — Optional sub-scope within a project. Resolution

rule depends on team_field.kind (single_value or array). Only valid with --project.

  • --program-id ID — Jira Align program ID. Triggers a Jira Align

join for team mapping.

  • --portfolio-id ID — Jira Align portfolio ID. Triggers a rollup

across constituent programs / teams.

  • --from ISO, --to ISO — Window bounds, YYYY-MM-DD. Both

inclusive of the named day. Default: --to = today (UTC), --from = today − 90 days.

  • --jql "" — Extra JQL ANDed into the scope query. Always

wrapped as () AND () — your expression is parenthesised verbatim.

  • --align-filter "" — Extra OData ANDed into Jira Align

queries with the same parenthesisation rule.

  • --cohort-jql "" — Issues matching this JQL are marked

cohort: true in the output. Aggregate mode emits a cohort_breakdown block; per-issue mode tags each row.

  • --metrics LIST — Comma list. Default: all ten. Names:

cycle_time, lead_time, throughput, wip, flow_load, rework_rate, flow_time, flow_efficiency, flow_distribution, defect_ratio. Unrequested metrics are omitted from aggregates (not emitted as null); meta.metrics_requested records the resolved list.

  • --state-config FILE — JSON file mapping raw statuses to

canonical states. Defaults to the shipped references/states.default.json.

  • --issuetype-config FILE — JSON file mapping issuetypes to Flow

Distribution buckets. Defaults to references/issuetypes.default.json.

  • --team-field-override ID — Override team_field.id from the

state config for this run.

  • --align-join-field NAME — Override the Jira ↔ Jira Align join

field. Defaults to the align_join_field entry in the state config; if neither is set and Jira Align scope is requested, exit 2.

  • --align-teams-path PATH — Override the Jira Align endpoint

used to enumerate teams in a program. Must match one of the four allowlisted jira-align raw GET patterns.

  • --include-subtasks — Include subtasks in throughput, cycle

time, lead time, flow efficiency, rework rate. Default: false. Flow Distribution is always insensitive to this flag.

  • --format json|csv — Output format. Default: json.
  • --output FILE — Write to file instead of stdout. Required for

--per-issue. Path is rejected if it lands under a system root.

  • --per-issue — Emit one JSONL row per issue with all derived

fields, instead of aggregates. Requires --output.

  • --no-cache — Bypass the on-disk cache at

.context/flow-metrics/cache/.jsonl.

  • --verbose — Debug logging (state-transition walks, cache hits,

upstream skill invocations).

  • --yes — Overwrite --output FILE without prompting.

Exactly one of --project, --program-id, --portfolio-id must be provided. --team is only valid with --project.

Common flows

Each example is a literal command line the agent can run.

Project-scope, default 90-day window

flow-metrics --project PROJ

JSON to stdout. The shipped default state config maps the common Jira workflow ("To Do" / "In Progress" / "Done" / "Won't Do") out of the box.

Project-scope with a specific window and JQL filter

flow-metrics \
  --project PROJ \
  --from 2026-02-01 --to 2026-04-30 \
  --jql 'labels = ai-assisted AND component = checkout'

Jira Align program scope (joins via Jira Align)

flow-metrics \
  --program-id 42 \
  --align-join-field "Program ID" \
  --from 2026-02-01 --to 2026-04-30

--align-join-field is required for Align scope unless the state config provides it.

Cohort split (A/B comparison)

flow-metrics \
  --project PROJ \
  --cohort-jql 'labels = ai-assisted' \
  --format json

Output gains a cohort_breakdown block with cohort and control sides. Cohort-jql matching zero issues produces an empty cohort with throughput: 0 and null percentiles — exit 0.

Filter to a subset of metrics

flow-metrics \
  --project PROJ \
  --metrics throughput,cycle_time,defect_ratio

Only the requested metrics appear in aggregates. meta.metrics_requested records the resolved list. flow_distribution and defect_ratio are separate keys — requesting one does not auto-include the other.

Bypass the on-disk cache

flow-metrics --project PROJ --no-cache

Use when the underlying Jira data has changed and you suspect cache staleness. Cache lives at .context/flow-metrics/cache/.jsonl.

Per-issue dump (downstream consumer input)

flow-metrics \
  --project PROJ \
  --per-issue \
  --output .context/flow-metrics/per-issue.jsonl

JSONL on disk, one row per in-scope issue. Downstream consumers (notably ai-adoption-report) MUST filter on delivered_in_window: true before computing delivery-based metrics.

Don't

  • Don't bypass the upstream-skill allowlist. This skill invokes

only the allowlisted verbs and raw GET paths. Any other invocation is a regression. If a verb is missing, extend the jira or jira-align skill — don't shim around it here.

  • Don't read credentials.env from this skill. Credentials live

in the jira / jira-align skills and are isolated from this one. Authentication failures surface as upstream exit 3; the fix is to run the upstream skill's setup_credentials.sh, not to read its config file from here.

  • Don't issue write verbs. This skill is read-only. No

create-issue, update-issue, delete-issue, transition, comment, attach — and no raw POST / PUT / PATCH / DELETE to any upstream skill. A contract test wraps the upstream skills and fails on any out-of-allowlist call.

  • Don't add numpy or any other pip dependency. v1 is stdlib

only — percentiles use statistics.quantiles(..., method="exclusive") at indices 49 / 74 / 89 for p50 / p75 / p90. The schema validator used by the contract test is the same stdlib-only posture; do not add jsonschema to satisfy it.

  • Don't infer the align_join_field. Instances vary; silently

picking customfield_10001 is a wrong-answer risk. If neither --align-join-field nor the state config sets it and Align scope is requested, exit 2 with a clear message.

  • Don't normalise JQL semantically in v1. normalize_jql only

collapses whitespace; two semantically equivalent JQL expressions with different clause order produce different cache files. That's the documented v1 trade.

  • Don't paraphrase the metric definitions. They are pinned

and tested. If a metric "feels wrong", read the module docstrings before changing anything.

Security rules

This skill operates under a read-only contract with credential isolation:

  • Read-only contract: the upstream-skill allowlist names every

verb and raw GET path this skill is permitted to invoke. Any other upstream invocation, including the raw POST / PUT / PATCH / DELETE escape hatches, is forbidden and enforced by a contract test that wraps the upstream skills.

  • Credential isolation: this skill **never reads

credentials.env** or any other secret file directly. Credentials belong to the jira / jira-align skills; this skill invokes them by name and lets them load their own credentials. If jira: check fails, surface the error and tell the user to run the upstream skill's setup — do not attempt to authenticate on its behalf.

  • No write verbs: this skill emits no POST / PUT / PATCH /

DELETE HTTP requests, and invokes no write-class verbs (transition, comment, create, update, delete, attach) on any upstream skill. The output is metrics; it never mutates Jira state.

  • Path safety: --output, --state-config, --issuetype-config

are rejected if they resolve under a privileged system root (POSIX: /etc, /sys, /proc, /dev, /boot; Windows: the system drive's Windows, Program Files, and Program Files (x86) directories), or if they contain a null byte. Exit 2.

Edge cases

The key edge cases to know about:

  • Cancelled issues. An issue transitioning into a

terminal_non_delivery_states canonical state (default: cancelled) in-window with no first-ever delivery in-window is cancelled-in-window. Excluded from throughput, cycle time, lead time, flow efficiency, and Flow Distribution; counted in notes. A cancel-then-reopen-still-active-at---to issue is also in WIP — both signals are reported simultaneously.

  • Empty cohort. --cohort-jql matching zero issues produces an

empty cohort sub-object with throughput: 0 and percentile fields null. The skill exits 0.

  • Permission undercounting. Jira silently omits issues the caller

lacks browse permission on. For project scope, the skill compares the JQL count against jira: get-project and emits a notes entry recording the delta. Field-level permission undercount on the team_field is also detected and reported as a synthetic (no team) row in per_team. The skill does not retry as a different user or escalate. meta.caller records the calling account so downstream consumers can spot cross-account discrepancies.

  • Changelog pagination (Cloud regression). Cloud Jira's

/search/jql endpoint returns at most ~100 inline changelog entries per issue. The skill detects "more pages exist" via isLast, nextPageToken, or histories.length /changelog. Long-lived issues silently lose cycle-time math without this, so the pagination contract is required, not optional.

  • Unmapped raw status. Any raw status not listed under any

canonical_states entry causes exit 2 at startup with the offending name. The shipped default config maps "Won't Do" / "Cancelled" / "Duplicate" to cancelled deliberately so first-run users on a normal Jira workflow get accurate throughput out of the box.

  • Issue with no commitment_state transition (closed directly from

backlog). Delivered-in-window = true; cycle-eligible = false. Contributes to throughput and lead time. Excluded from cycle time.

  • --per-issue without --output. Exit 2 — JSONL must go to a

file.

Output contract

The canonical wire format is pinned by references/output.schema.json (JSON Schema draft 2020-12). The shape:

  • meta — caller, scope, window, sources, metrics_requested,

schemaversion, generatedat, stateconfigsha, issuetypeconfigsha, perteamdouble_counted, and optionally cohort_jql (omitted when --cohort-jql was not provided).

  • aggregates — one key per requested metric. Unrequested metrics

are absent, not null. additionalProperties: false in the schema pins this.

  • cohort_breakdown — optional. Emitted only when --cohort-jql is

set AND --per-issue is not set. Carries cohort and control sub-objects with the same metric shape as aggregates.

  • per_team — optional array of per-team rows. Emitted when scope is

--program-id / --portfolio-id, or when scope is --project and the resolved issue set spans more than one distinct team value.

  • notes — array of descriptive strings, lex-sorted.

Output is canonicalised at serialisation: codepoint-sorted object keys (except flow_distribution which uses a fixed bucket order), floats rounded to 4 decimal places, per_team sorted by team name codepoint. The schema does not re-validate canonicalisation rules — those are enforced by the renderer's contract tests.

Further reading

The module docstrings in scripts/flow_metrics/ cover:

  • metric definitions and core population predicates (predicates.py, aggregate.py),
  • the upstream-skill allowlist and verbs (upstream.py),
  • state-config and issuetype-config schemas (config.py),
  • canonicalisation rules and output rendering (output.py),
  • cache-key derivation (cache.py),
  • edge-case handling (per_issue.py, notes.py).

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.