Skip to content

Metric catalog ​

Every metric type exposed by SMM has a stable, namespaced identifier owned by the core package. The same id is used by the CLI, the REST API, the MCP server, and the dashboard, so it is safe to persist, log, or reference across releases.

Identifiers name a metric family (for example cr-review-time), not a single number. Statistical method, aggregation period, and scope are parameters of that family.

Browse the full catalog for a description of every family, or download it as CSV.

Namespaces ​

PrefixArea
cr-Change requests
pl-Pipelines
code-Source code
sq-SonarQube
arch-Architecture
issue-Issues
ehEngineering health (existing unprefixed ids)

Full catalog ​

Every metric family in the catalog, with what it measures, how it is computed (the evidence it reads, the formula applied, and the math notation), its unit and preferred direction, and the CLI, REST, and MCP surfaces that expose it. Use the search box or the namespace filter to narrow the list, and select Download CSV to export the same data for offline analysis.

Download CSV

Showing 86 of 86 metrics

cr-summaryChange request summary
Unit recordDirection neutral

Totals, merged/open/closed counts, comments per change request, unique authors and labels, and time to first comment.

Target: High merge rate

How it is computed

Evidence
Change request records with author, labels, comments, and created/merged/closed timestamps from the git provider.
Formula
Counts records in the selected window, totals comments and unique authors/labels, then derives first/last change request by created date, top comment themes from n-grams, most-commented change requests, top commenter, and average hours to the first comment.
Notation
counts = |{cr ∈ CR}|; comments/CR = Σ comments ÷ |CR|; t_first = mean(t_first_comment − t_created)
CLIchange-requests summary
REST/change-requests/summary
MCPsmm_get_change_request_summary
cr-metricsChange request metrics
Unit recordDirection neutral

Aggregate change request metrics for the selected window: open days, comments, lead time, and label and comment summaries.

How it is computed

Evidence
Change request records with author, labels, comments, and created/merged/closed timestamps.
Formula
Aggregates open days (creation to merge/close, or now when still open), comments per change request, and lead time with the selected statistical method; includes label and comment summaries.
Notation
open_days = days((merged_at ∨ closed_at ∨ now) − created_at); comments = Σ comments; lead_time = open_days
REST/api/metrics/change-requests
MCPsmm_get_change_request_metrics
cr-throughputChange request throughput
Unit countDirection neutral

Change requests opened and closed per day, week, or month.

Target: Opened ≈ Closed

How it is computed

Evidence
Change request records with created, merged, and closed timestamps.
Formula
Counts change requests opened by created date and closed by merge/close date per day, week, or month, and emits one series row per period and kind.
Notation
opened(p) = |{cr: created_at ∈ p}|; closed(p) = |{cr: merged_at ∨ closed_at ∈ p}|
CLIchange-requests through-time
REST/change-requests/through-time
MCPsmm_get_change_request_through_time
cr-volume-by-authorChange request volume by author
Unit countDirection neutral

Change request count grouped by author.

Target: Balanced distribution

How it is computed

Evidence
Change request records and their author login.
Formula
Groups change requests by author, counts each group, and returns the top N authors sorted by count.
Notation
count(author) = |{cr: cr.author = author}|
CLIchange-requests by-author
REST/change-requests/by-author
MCPsmm_get_change_request_by_author
cr-review-timeReview time
Unit daysDirection lower is better

Days from change request creation to review, per author, using the selected statistical method.

Target: < 24 hours

How it is computed

Evidence
Merged or closed change requests with created and merged/closed timestamps, grouped by author.
Formula
Computes days from creation to merge/close per change request, groups the samples by author, and applies the selected method (average/median/p75/p90/p95/min/max).
Notation
review_days = ((merged_at ∨ closed_at) − created_at) ÷ 86 400 000; value(author) = method(review_days)
CLIchange-requests review-time
REST/change-requests/review-time
MCPsmm_get_change_request_review_time
cr-open-timeOpen time
Unit daysDirection lower is better

Days a change request stays open, grouped by day, week, or month, using the selected statistical method.

Target: < 3 days

How it is computed

Evidence
Change request records with created and merged/closed timestamps.
Formula
Computes days open per change request (to merge/close, or now when still open), groups samples by day/week/month, and applies the selected statistical method.
Notation
open_days = ((merged_at ∨ closed_at ∨ now) − created_at) ÷ 86 400 000; value(period) = method(open_days)
CLIchange-requests open-time
REST/change-requests/open-time
MCPsmm_get_change_request_open_time
cr-comments-per-crComments per change request
Unit countDirection higher is better

Number of comments per change request, using the selected statistical method and optional aggregation period.

How it is computed

Evidence
Change request records and their total comment counts.
Formula
Collects comments per change request, optionally groups the samples by period, and applies the selected statistical method to the distribution.
Notation
value(period) = method({cr.comments})
CLIchange-requests comments
REST/change-requests/comments
MCPsmm_get_change_request_comments
cr-comments-by-authorComments by reviewer
Unit countDirection neutral

Comment volume grouped by reviewer.

Target: Inclusive participation

How it is computed

Evidence
Comments attached to change requests with the commenter login.
Formula
Counts comments per commenter, sorts descending, and returns the top N reviewers.
Notation
count(commenter) = |{comment: comment.author = commenter}|
REST/change-requests/comments-by-author
MCPsmm_get_change_request_comments_by_author
cr-first-comment-timeTime to first comment
Unit hoursDirection lower is better

Hours from change request creation to its first comment, per author.

Target: < 4 hours

How it is computed

Evidence
Change requests with comments and timestamps for creation and the first comment.
Formula
Computes hours from creation to the earliest comment, groups samples by change request author, and applies the selected statistical method.
Notation
t_first = (min(comment.created_at) − created_at) ÷ 3 600 000; value(author) = method(t_first)
REST/change-requests/first-comment-time
MCPsmm_get_change_request_first_comment_time
cr-metrics-by-weekChange requests by week
Unit recordDirection neutral

Change request metrics grouped by week: totals, merged/closed/open counts, comments, open days, and lead time.

How it is computed

Evidence
Merged change requests with created/merged timestamps and comments.
Formula
Groups merged change requests by timezone-aware week and computes totals, merged/closed/open counts, open days, comments, and lead time per week.
Notation
week = iso_week(merged_at); value = {count, merged, closed, open, open_days, comments, lead_time}
CLIchange-requests by-week
MCPsmm_get_change_request_metrics_by_week
cr-metrics-by-monthChange requests by month
Unit recordDirection neutral

Change request metrics grouped by month: totals, merged/closed/open counts, comments, open days, and lead time.

How it is computed

Evidence
Change requests with created/merged timestamps and comments.
Formula
Groups change requests by timezone-aware calendar month and computes totals, merged/closed/open counts, open days, comments, and lead time per month.
Notation
month = calendar_month(created_at); value = {count, merged, closed, open, open_days, comments, lead_time}
CLIchange-requests by-month
MCPsmm_get_change_request_metrics_by_month
cr-label-summaryChange request labelsinternal
Unit countDirection neutral

Change request count per label. Embedded in the change request summary.

How it is computed

Evidence
Change request labels attached to each change request.
Formula
Counts change requests per distinct label (case-insensitive), adds average open days per label, and sorts by count.
Notation
count(label) = |{cr: label ∈ cr.labels}|; open_days(label) = mean(open_days(cr))
cr-evaluationChange request bottleneck evaluation
Unit recordDirection neutral

Bottleneck signals covering review time, reviewer workload, open time, throughput, first comment, and comment health.

How it is computed

Evidence
Aggregated change request metrics, review-time distributions, comment counts, and per-author comment volume.
Formula
Runs six threshold-based signal detectors (review_time, reviewer_workload, open_time, throughput, first_comment, comment_health) and returns each signal with severity, metrics, and description.
Notation
signals = {review_time, reviewer_workload, open_time, throughput, first_comment, comment_health}
REST/change-requests/evaluate
MCPsmm_evaluate_change_requests
pl-summaryPipeline summary
Unit recordDirection neutral

Run totals by conclusion, in-progress and queued counts, success rate, and aggregate duration.

How it is computed

Evidence
Pipeline runs with status, conclusion, attempt metadata, and job start/completion timestamps.
Formula
Counts runs by conclusion plus in-progress/queued, computes success rate as successful divided by completed times 100, and aggregates run duration (max job completion minus min job start) with the selected method.
Notation
success_rate = successful ÷ completed × 100; duration = max(job.completed_at) − min(job.started_at); value = method(duration)
CLIpipelines summary
REST/pipelines/summary/pipelines/dashboard/api/metrics/deployment
MCPsmm_get_pipeline_dashboardsmm_get_deployment_metrics
pl-status-countsRuns by status
Unit countDirection neutral

Pipeline run count grouped by conclusion.

How it is computed

Evidence
Pipeline runs and their conclusion values.
Formula
Groups runs by conclusion and counts each group.
Notation
count(conclusion) = |{run: run.conclusion = conclusion}|
CLIpipelines by-status
REST/pipelines/by-status
pl-job-status-countsJobs by status
Unit countDirection neutral

Pipeline job count grouped by status.

Target: > 90%

How it is computed

Evidence
Pipeline jobs and their conclusion/status values.
Formula
Groups jobs by conclusion (falling back to status) and counts each group.
Notation
count(status) = |{job: job.conclusion ∨ job.status = status}|
CLIpipelines jobs-by-status
REST/pipelines/jobs-by-status
pl-run-durationRun duration
Unit minutesDirection lower is better

Pipeline run duration with minimum, maximum, and selected statistical aggregation.

Target: < 10 min

How it is computed

Evidence
Pipeline runs and their job start/completion timestamps, grouped by workflow.
Formula
Computes each run duration as max job completion minus min job start, groups samples by workflow, and returns the minimum, maximum, and selected aggregation.
Notation
duration(run) = max(job.completed_at) − min(job.started_at); value(workflow) = method(duration); min/max = min(duration)/max(duration)
CLIpipelines runs-duration
REST/pipelines/runs-duration
pl-runs-over-timeRuns over time
Unit countDirection neutral

Pipeline run count per period and workflow.

How it is computed

Evidence
Pipeline runs with completion/creation timestamps and workflow path.
Formula
Groups runs by day and workflow and counts them per period.
Notation
runs(day, workflow) = |{run: date(run) = day ∧ run.path = workflow}|
CLIpipelines runs-by
REST/pipelines/runs-by
pl-jobs-summaryJob summary
Unit recordDirection neutral

Per-job run counts, success and failure rates, rerun counts, and duration statistics.

Target: 0 reruns

How it is computed

Evidence
Pipeline jobs with conclusion, run attempt, and start/completion timestamps.
Formula
Groups jobs by workflow and normalized job name, counts runs and successes/failures, sums reruns as attempt minus one, applies the selected duration aggregation, and derives success/failure rates.
Notation
success_rate = success ÷ total × 100; failure_rate = failure ÷ total × 100; reruns = Σ max(run_attempt − 1, 0); value = method(job_duration)
CLIpipelines jobs-summary
REST/pipelines/jobs-summary/api/metrics/deployment
MCPsmm_get_deployment_metrics
pl-job-durationJob execution time
Unit minutesDirection lower is better

Pipeline job execution duration using the selected statistical method.

Target: < 5 min

How it is computed

Evidence
Pipeline jobs with start and completion timestamps.
Formula
Computes each job duration in minutes, groups samples by normalized job name, and applies the selected statistical method.
Notation
job_duration = (job.completed_at − job.started_at) ÷ 60 000; value(job) = method(job_duration)
CLIpipelines jobs-time-execution
REST/pipelines/jobs-time-execution
pl-job-duration-by-dayJob time by day
Unit minutesDirection lower is better

Daily pipeline job execution duration series.

How it is computed

Evidence
Pipeline jobs with start/completion timestamps and the run completion/creation date.
Formula
Computes job durations in minutes, groups samples by run day, and applies the selected statistical method per day.
Notation
day = date(run); value(day, job) = method(job_duration)
REST/pipelines/jobs-time-execution-by-day
pl-job-steps-durationJob step execution time
Unit minutesDirection lower is better

Pipeline job step duration using the selected statistical method.

How it is computed

Evidence
Pipeline job steps with name and start/completion timestamps.
Formula
Computes each step duration in minutes, groups samples by step name, and applies the selected statistical method.
Notation
step_duration = (step.completed_at − step.started_at) ÷ 60 000; value(step) = method(step_duration)
CLIpipelines jobs-steps-time
REST/pipelines/jobs-steps-time
pl-job-steps-duration-by-dayJob step time by day
Unit minutesDirection lower is better

Daily pipeline job step duration series.

How it is computed

Evidence
Pipeline job steps with name and start/completion timestamps, plus the run date.
Formula
Computes step durations in minutes, groups samples by run day and step name, and applies the selected statistical method per group.
Notation
day = date(run); value(day, step) = method(step_duration)
REST/pipelines/jobs-steps-time-by-day
pl-reruns-by-dayReruns by day
Unit countDirection lower is better

Daily pipeline job rerun count.

How it is computed

Evidence
Pipeline runs with attempt number and completion/creation date.
Formula
Computes reruns per run as max(attempt minus 1, 0) and sums reruns per day.
Notation
reruns(run) = max(run_attempt − 1, 0); reruns(day) = Σ reruns(run)
REST/pipelines/jobs-reruns-by-day
pl-jobs-duration-by-workflowJob duration by workflow
Unit minutesDirection lower is better

Pipeline job duration grouped by workflow.

How it is computed

Evidence
Pipeline jobs with workflow path and start/completion timestamps.
Formula
Computes job durations in minutes and returns the arithmetic mean per job, grouped by workflow.
Notation
value(workflow, job) = Σ job_duration ÷ n
REST/pipelines/jobs-duration-by-workflow
pl-deployment-frequencyDeployment frequency
Unit deployments/periodDirection higher is better

DORA deployment frequency measured per day, week, and month.

Target: Daily (Elite)

How it is computed

Evidence
Successful pipeline runs and successful jobs matching each configured deployment target (pipeline plus job).
Formula
Counts successful target jobs per day/week/month, zero-fills missing intervals, and returns the latest period count per target.
Notation
frequency(p, target) = |{job: target ∧ job.conclusion = success ∧ completed_at ∈ p}|
CLIpipelines deployment-frequency
REST/dora/deployment-frequency/api/metrics/deployment
MCPsmm_get_dora_metricssmm_get_deployment_metrics
pl-lead-timeLead time for changes
Unit minutesDirection lower is better

DORA lead time for changes, in minutes.

How it is computed

Evidence
Pipeline dashboard summary for the selected window and deployment target.
Formula
Returns the dashboard summary aggregate value in minutes (the same run-duration aggregation used by the pipeline dashboard).
Notation
lead_time = summary.duration = method(max(job.completed_at) − min(job.started_at))
CLIpipelines lead-time
MCPsmm_get_dora_metrics
pl-evaluationPipeline bottleneck evaluation
Unit recordDirection neutral

Bottleneck signals covering job duration, stability, reruns, slowest workflow, and job overview.

How it is computed

Evidence
Pipeline dashboard data: job durations, job summaries, reruns, workflows, and job counts.
Formula
Runs five signal detectors (duration_top_job, stability_worst_job, rerun_analysis, slowest_workflow, job_overview) and returns each signal with severity, metrics, and description.
Notation
signals = {duration_top_job, stability_worst_job, rerun_analysis, slowest_workflow, job_overview}
REST/pipelines/evaluate
MCPsmm_evaluate_pipelines
code-big-oBig O complexity
Unit classificationDirection lower is better

Per-file algorithmic complexity classification, score, and whether the file needs performance attention.

Target: Review O(n^2+) hotspots

How it is computed

Evidence
Source files in the configured repository, scanned line by line for loops, sort calls, binary searches, and iteration helpers.
Formula
Classifies the highest-weight signal per file as O(1) through O(n^3+), scores it as min(100, topWeight times 12 plus signalCount times 2), and flags needsHelp when the score is 60 or more.
Notation
classification = argmax(weight[signal]); score = min(100, weight[top] × 12 + |signals| × 2); needs_help = score ≥ 60
CLIcode big-o
REST/code/big-o/code/big-o/file
MCPsmm_list_big_o_filessmm_analyze_big_o_file
code-summaryCode summary
Unit recordDirection neutral

Code overview with developer pairing insights.

How it is computed

Evidence
Git commits with author, co-authors, changed files, and timestamps.
Formula
Uses the pairing index (paired commits divided by analyzed commits times 100) as the summary core and exposes paired commit counts and top pairs.
Notation
pairing_index = paired_commits ÷ total_commits × 100
CLIcode summary
REST/api/metrics/code
MCPsmm_get_code_metrics
code-churnCode churn
Unit linesDirection neutral

Commits, lines added, lines deleted, and total churn over time.

Target: Consistent, moderate churn

How it is computed

Evidence
Git commits in the selected window with lines added and deleted.
Formula
Aggregates additions, deletions, commit counts, and total churn (added plus deleted) per day; the series projects one churn type.
Notation
churn(day) = Σ added(day) + Σ deleted(day); value = {added, deleted, commits, churn}
CLIcode churn
REST/code/code-churn/api/metrics/code
MCPsmm_get_code_churnsmm_get_code_metrics
code-author-churnChurn by author
Unit linesDirection neutral

Lines added, lines deleted, and commit count per author.

How it is computed

Evidence
Git commits with author and line-level churn.
Formula
Groups additions, deletions, and commit counts by author.
Notation
churn(author) = {Σ added, Σ deleted, Σ commits}
CLIcode churn
code-couplingFile coupling
Unit ratioDirection lower is better

Coupling degree and average revisions between file pairs.

Target: < 30% degree

How it is computed

Evidence
CodeMaat file-coupling output: pairs of files that change in the same commits.
Formula
Returns the coupling degree (shared revisions divided by revisions of the entity) and average revisions per pair, optionally filtered by minimum coupling and path patterns.
Notation
degree = shared_revisions ÷ entity_revisions × 100; avg_revs = mean(revisions)
CLIcode coupling
REST/code/coupling/api/metrics/code
MCPsmm_get_code_couplingsmm_get_code_metrics
code-layered-couplingLayered coupling
Unit ratioDirection lower is better

Coupling between architectural layers.

Target: < 30% degree across layers

How it is computed

Evidence
CodeMaat layered-coupling output aggregated by file path group.
Formula
Returns coupling degree and average revisions between architectural layers derived from path groups.
Notation
degree(layer_a, layer_b) = shared_revisions ÷ layer_revisions × 100
REST/code/layered-coupling
MCPsmm_get_code_layered_coupling
code-entity-churnEntity churn
Unit linesDirection neutral

Lines added, lines deleted, and commit count per entity.

Target: Monitor hotspots

How it is computed

Evidence
CodeMaat entity-churn output with per-file added/deleted lines and commit counts.
Formula
Returns added, deleted, and commit totals per entity, with optional path filters and top-N.
Notation
churn(entity) = {Σ added, Σ deleted, Σ commits}
CLIcode entity-churn
REST/code/entity-churn
MCPsmm_get_code_entity_churn
code-entity-effortEntity effort
Unit revisionsDirection neutral

Revision count per entity, used as an effort proxy.

Target: Distributed effort

How it is computed

Evidence
CodeMaat entity-effort output with revision counts per file.
Formula
Returns total revisions per entity as the effort proxy, with optional path filters and top-N.
Notation
effort(entity) = total_revs(entity)
CLIcode entity-effort
REST/code/entity-effort
MCPsmm_get_code_entity_effort
code-entity-ownershipEntity ownership
Unit linesDirection neutral

Lines added and deleted per author for each entity.

Target: Shared ownership (< 80% single owner)

How it is computed

Evidence
CodeMaat entity-ownership output with author, file, additions, and deletions.
Formula
Returns lines added and deleted per author per entity, with optional author/path filters and top-N.
Notation
ownership(entity, author) = {Σ added, Σ deleted}
CLIcode entity-ownership
REST/code/entity-ownership
MCPsmm_get_code_entity_ownership
code-pairing-indexPairing index
Unit percentDirection higher is better

Percentage of commits with co-authors, paired commit count, and the most frequent pairs.

Target: > 30%

How it is computed

Evidence
Git commits with author, co-authors, changed files, and timestamps.
Formula
Computes (commits with co-authors divided by total analyzed commits) times 100, plus the paired commit count and top author pairs.
Notation
pairing_index = |{commit: co_authors ≠ ∅}| ÷ |commits| × 100
CLIcode pairing-index
REST/code/pairing-index
MCPsmm_get_code_pairing_index
code-crapCRAP scoreinternal
Unit scoreDirection lower is better

Change risk anti-pattern score derived from complexity and coverage per file.

Target: <= 30

How it is computed

Evidence
Per-file cyclomatic complexity and test coverage from SonarQube component data.
Formula
CRAP equals complexity squared times (1 minus coverage divided by 100) cubed, plus complexity, rounded to one decimal.
Notation
CRAP = complexity² × (1 − coverage ÷ 100)³ + complexity
code-churn-historyCode churn history
Unit seriesDirection neutral

Timestamped code churn series.

How it is computed

Evidence
Timestamped CodeMaat churn entries.
Formula
Returns the stored churn series (date, added, deleted, commits) in chronological order.
Notation
series = {(date, added, deleted, commits)}
REST/code/code-churn/history
MCPsmm_get_code_churn_history
code-coupling-historyFile coupling history
Unit seriesDirection lower is better

Timestamped file coupling series.

How it is computed

Evidence
Timestamped CodeMaat file-coupling entries.
Formula
Returns the stored coupling series with degree and average revisions per snapshot.
Notation
series = {(snapshot, entity, coupled, degree, avg_revs)}
REST/code/coupling/history
MCPsmm_get_code_coupling_history
code-layered-coupling-historyLayered coupling history
Unit seriesDirection lower is better

Timestamped layered coupling series.

How it is computed

Evidence
Timestamped CodeMaat layered-coupling entries.
Formula
Returns the stored layered-coupling series per snapshot.
Notation
series = {(snapshot, layer, coupled, degree, avg_revs)}
REST/code/layered-coupling/history
MCPsmm_get_code_layered_coupling_history
code-entity-churn-historyEntity churn history
Unit seriesDirection neutral

Timestamped entity churn series.

How it is computed

Evidence
Timestamped CodeMaat entity-churn entries.
Formula
Returns the stored per-entity added/deleted/commit series.
Notation
series = {(snapshot, entity, added, deleted, commits)}
REST/code/entity-churn/history
MCPsmm_get_code_entity_churn_history
code-entity-effort-historyEntity effort history
Unit seriesDirection neutral

Timestamped entity effort series.

How it is computed

Evidence
Timestamped CodeMaat entity-effort entries.
Formula
Returns the stored per-entity revision series.
Notation
series = {(snapshot, entity, total_revs)}
REST/code/entity-effort/history
MCPsmm_get_code_entity_effort_history
code-entity-ownership-historyEntity ownership history
Unit seriesDirection neutral

Timestamped entity ownership series.

How it is computed

Evidence
Timestamped CodeMaat entity-ownership entries.
Formula
Returns the stored per-author and per-entity added/deleted series.
Notation
series = {(snapshot, entity, author, added, deleted)}
REST/code/entity-ownership/history
MCPsmm_get_code_entity_ownership_history
code-evaluationCode evaluation
Unit recordDirection neutral

Code signals covering churn hotspots, churn trend, coupling, ownership concentration, complexity, Big O, and pairing.

How it is computed

Evidence
Code dashboard data: entity churn, daily churn, coupling, ownership, CRAP, Big O, and pairing.
Formula
Runs ten threshold-based signal detectors (churn_hotspot, churn_trend, coupling_top, coupling_burst, ownership_concentration, ownership_unknown, complexity_hotspot, complexity_big_o, pairing_index, pairing_concentration) and returns severity, metrics, and description.
Notation
signals = {churn_hotspot, churn_trend, coupling_top, coupling_burst, ownership_concentration, ownership_unknown, complexity_hotspot, complexity_big_o, pairing_index, pairing_concentration}
REST/code/evaluate
MCPsmm_evaluate_code
sq-coverageCoverage
Unit percentDirection higher is better

Line coverage measured by SonarQube. Embedded in the change request summary.

Target: > 80%

How it is computed

Evidence
SonarQube coverage measure for the project.
Formula
Returns the stored line-coverage percentage.
Notation
coverage = sonar.coverage
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-maintainability-ratingMaintainability rating
Unit ratingDirection higher is better

SonarQube maintainability rating (sqale_rating).

Target: A (Rating 1)

How it is computed

Evidence
SonarQube sqale_rating measure.
Formula
Returns the 1-to-5 maintainability rating.
Notation
rating = sonar.sqale_rating
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-reliability-ratingReliability rating
Unit ratingDirection higher is better

SonarQube reliability rating.

Target: A (Rating 1)

How it is computed

Evidence
SonarQube reliability_rating measure.
Formula
Returns the 1-to-5 reliability rating consumed by the quality evaluation.
Notation
rating = sonar.reliability_rating
REST/sonarqube/evaluate
MCPsmm_evaluate_quality
sq-security-ratingSecurity rating
Unit ratingDirection higher is better

SonarQube security rating.

Target: A (Rating 1)

How it is computed

Evidence
SonarQube security_rating measure.
Formula
Returns the 1-to-5 security rating consumed by the quality evaluation.
Notation
rating = sonar.security_rating
REST/sonarqube/evaluate
MCPsmm_evaluate_quality
sq-complexityComplexity
Unit scoreDirection lower is better

Total cyclomatic complexity measured by SonarQube.

Target: < 15 per component

How it is computed

Evidence
SonarQube complexity measure.
Formula
Returns the total cyclomatic complexity.
Notation
complexity = Σ cyclomatic_complexity
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-cognitive-complexityCognitive complexity
Unit scoreDirection lower is better

Per-component cognitive complexity from the SonarQube component tree.

How it is computed

Evidence
SonarQube component tree with cognitive_complexity measures per component.
Formula
Returns the per-component cognitive-complexity rows from the latest component tree.
Notation
cognitive_complexity(component) = measure
CLIsonarqube fetch-component-tree
REST/sonarqube/component-tree
MCPsmm_get_sonarqube_component_tree
sq-duplication-densityDuplication density
Unit percentDirection lower is better

Percentage of duplicated lines measured by SonarQube.

Target: < 3%

How it is computed

Evidence
SonarQube duplicated_lines_density measure.
Formula
Returns the duplicated-lines percentage.
Notation
duplication = duplicated_lines ÷ lines × 100
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-nclocNon-commenting lines of code
Unit linesDirection neutral

Non-commenting lines of code measured by SonarQube.

How it is computed

Evidence
SonarQube ncloc measure.
Formula
Returns non-commenting lines of code.
Notation
ncloc = non_commenting_lines
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-code-smellsCode smells
Unit countDirection lower is better

Code smell count measured by SonarQube.

How it is computed

Evidence
SonarQube code_smells measure.
Formula
Returns the code-smell count.
Notation
code_smells = count
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-bugsBugs
Unit countDirection lower is better

Bug count measured by SonarQube.

How it is computed

Evidence
SonarQube bugs measure.
Formula
Returns the bug count.
Notation
bugs = count
CLIsonarqube fetch-measures
REST/sonarqube/quality
MCPsmm_get_quality_metrics
sq-component-treeComponent tree
Unit recordDirection neutral

Per-component SonarQube measures including complexity, size, rating, and coverage.

How it is computed

Evidence
SonarQube component-tree response with per-component measures.
Formula
Maps each component to its complexity, ncloc, rating, coverage, duplication, and cognitive-complexity fields.
Notation
component = {complexity, ncloc, rating, coverage, duplication, cognitive_complexity}
CLIsonarqube fetch-component-tree
REST/sonarqube/component-tree
MCPsmm_get_sonarqube_component_tree
sq-component-tree-historyComponent tree history
Unit seriesDirection neutral

Timestamped SonarQube component tree entries.

How it is computed

Evidence
Stored SonarQube component-tree snapshots.
Formula
Returns each timestamped component-tree entry in chronological order.
Notation
series = {(timestamp, component, measures)}
REST/sonarqube/component-tree/history
MCPsmm_get_sonarqube_component_tree_history
sq-measurementsSonarQube measurements
Unit recordDirection neutral

Raw SonarQube measure set for the project.

Target: Improving trends

How it is computed

Evidence
Raw SonarQube measure set for the project.
Formula
Returns the stored measures without aggregation.
Notation
measures = {(metric, value)}
REST/sonarqube/measurements/api/metrics/quality
MCPsmm_get_sonarqube_measurements
sq-measurements-historyMeasurements history
Unit seriesDirection neutral

Timestamped SonarQube measure entries.

How it is computed

Evidence
Stored SonarQube measurement entries.
Formula
Returns the stored time series per metric.
Notation
series = {(timestamp, metric, value)}
CLIsonarqube fetch-historical-measures
REST/sonarqube/measurements/history
MCPsmm_get_sonarqube_measurements_history
sq-evaluationQuality evaluation
Unit recordDirection neutral

Quality signals covering reliability, security, maintainability, duplication, coverage, and complexity outliers.

How it is computed

Evidence
SonarQube quality metrics and component tree.
Formula
Runs seven threshold-based signal detectors (reliability_rating, security_rating, maintainability_rating, duplication_density, coverage_health, complexity_outlier, coverage_outlier) and returns severity, metrics, and description.
Notation
signals = {reliability_rating, security_rating, maintainability_rating, duplication_density, coverage_health, complexity_outlier, coverage_outlier}
REST/sonarqube/evaluate
MCPsmm_evaluate_quality
arch-snapshotArchitecture snapshot
Unit recordDirection neutral

Persisted architecture snapshot metadata.

How it is computed

Evidence
Persisted architecture snapshots with id, timestamp, project, branch, commit count, and available views.
Formula
Lists snapshot headers; each snapshot is generated from package.json discovery plus git commit history.
Notation
snapshot = {id, generated_at, project, branch, commit_count, views}
CLIarchitecture generatearchitecture list-snapshots
REST/architecture/snapshots
MCPsmm_list_architecture_snapshots
arch-summaryArchitecture summary
Unit recordDirection neutral

Container, edge, confidence, orphan, and hub summaries for a snapshot.

How it is computed

Evidence
Latest architecture snapshot's selected C4 view with nodes and relationships.
Formula
Counts containers, edges, orphan nodes, average edge confidence, most-connected node, and hub node.
Notation
summary = {containers = |nodes|, edges = |edges|, avg_confidence = mean(confidence), orphans, most_connected = argmax(in_degree), hub = argmax(out_degree)}
REST/architecture/summary
MCPsmm_get_architecture_summary
arch-viewArchitecture view
Unit graphDirection neutral

C4 context, container, component, or code view with nodes and relationships.

How it is computed

Evidence
Latest architecture snapshot's context, container, component, or code view.
Formula
Returns the selected view's nodes and edges, filtered by include/ignore path patterns when provided.
Notation
view = {nodes, edges} filtered by path patterns
CLIarchitecture export
REST/architecture/view
MCPsmm_get_architecture_viewsmm_export_architecture_view
arch-container-countContainer countinternal
Unit countDirection neutral

Number of containers in the architecture snapshot.

How it is computed

Evidence
Architecture snapshot nodes of kind container or component.
Formula
Counts matching nodes; severity is warning at 12 and critical at 20.
Notation
count = |{node: kind ∈ {container, component}}|
arch-dependency-concentrationDependency concentrationinternal
Unit ratioDirection lower is better

Concentration of relationships around a small set of dependencies.

How it is computed

Evidence
Architecture relationships with incoming edges per node.
Formula
Computes the highest incoming-edge count divided by the average incoming edges per node; severity is warning at 1.5 and critical at 3.
Notation
ratio = max(in_degree) ÷ mean(in_degree)
arch-hub-dependencyHub dependencyinternal
Unit nodeDirection neutral

The architecture node with the most incoming dependencies.

How it is computed

Evidence
Architecture relationships with outgoing edges per node.
Formula
Computes the highest outgoing-edge count divided by the average outgoing edges per node; severity is warning at 1.5 and critical at 3.
Notation
ratio = max(out_degree) ÷ mean(out_degree)
arch-orphan-nodesOrphan nodesinternal
Unit countDirection lower is better

Architecture nodes that have no relationships.

How it is computed

Evidence
Architecture nodes and the source/target ids of all relationships.
Formula
Counts nodes with no incident edge and divides by total nodes; severity is warning at 2 orphans and critical at 5.
Notation
orphans = |{node: in_degree + out_degree = 0}|; share = orphans ÷ |nodes| × 100
arch-confidence-healthRelationship confidenceinternal
Unit ratioDirection higher is better

Average confidence of detected architecture relationships.

How it is computed

Evidence
Architecture relationships and their confidence scores.
Formula
Averages edge confidence and counts edges below 0.5; severity is warning below 0.7 and critical below 0.5 average confidence.
Notation
avg_confidence = mean(edge.confidence); low = |{edge: confidence < 0.5}| ÷ |edges| × 100
arch-evaluationArchitecture evaluation
Unit recordDirection neutral

Architecture signals covering container count, dependency concentration, hub dependency, orphan nodes, and confidence.

How it is computed

Evidence
Architecture snapshot view plus the summary signals.
Formula
Runs container_count, dependency_concentration, hub_dependency, orphan_nodes, and confidence_health detectors and returns severity, metrics, and description.
Notation
signals = {container_count, dependency_concentration, hub_dependency, orphan_nodes, confidence_health}
REST/architecture/evaluate
MCPsmm_evaluate_architecture
issue-totalIssue count
Unit countDirection neutral

Total issues from the configured issue tracker (Jira, GitHub, or a Jira CSV export) for the selected window and status filter.

How it is computed

Evidence
Issues from the configured issue tracker (Jira, GitHub, or a Jira CSV export) matching the selected project, window, status and label filters.
Formula
Counts the matching issue records.
Notation
count = |{issue: filter(issue)}|
CLIissues fetch
REST/api/metrics/issues
MCPsmm_get_issue_metrics
issue-listIssue recordsinternal
Unit rowsDirection neutral

Raw issue records from the configured issue tracker backing the issue count.

How it is computed

Evidence
Issue records from the configured issue tracker matching the selected filter.
Formula
Returns the raw issue rows that back the count.
Notation
rows = {issue: filter(issue)}
deployment-frequencyDeployment frequency
Unit deployments/periodDirection higher is better

Successful deployments per selected period for each configured deployment target.

How it is computed

Evidence
Successful deployment-target jobs (configured pipeline plus job) per day/week/month.
Formula
Counts successful target jobs per period and returns the latest period count per target; missing intervals are zero-filled.
Notation
frequency(p, target) = |{job: target ∧ success ∧ completed_at ∈ p}|
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
lead-timeLead time
Unit minutesDirection lower is better

Time from change creation to deployment.

How it is computed

Evidence
Pipeline dashboard summary for the selected window and deployment target.
Formula
Returns the summary aggregate value in minutes, using the same run-duration aggregation as the pipeline dashboard.
Notation
lead_time = summary.duration
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
pipeline-durationPipeline duration
Unit minutesDirection lower is better

Average pipeline run duration.

How it is computed

Evidence
Pipeline runs with job start/completion timestamps.
Formula
Aggregates run duration (max job completion minus min job start) with the selected method and returns the value in minutes.
Notation
duration = method(max(job.completed_at) − min(job.started_at))
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
failure-rateFailure rate
Unit percentDirection lower is better

Percentage of failed pipeline runs.

How it is computed

Evidence
Pipeline runs with conclusion values.
Formula
Failure rate equals failed runs divided by total runs times 100, rounded to two decimals.
Notation
failure_rate = failed ÷ total × 100
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
complexityComplexity
Unit scoreDirection lower is better

Total complexity reported by SonarQube.

How it is computed

Evidence
SonarQube complexity measure.
Formula
Returns the total complexity value.
Notation
complexity = sonar.complexity
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
duplicationDuplication
Unit percentDirection lower is better

Duplicated lines density reported by SonarQube.

How it is computed

Evidence
SonarQube duplicated_lines_density measure.
Formula
Returns the duplicated-lines percentage.
Notation
duplication = duplicated_lines ÷ lines × 100
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
coverageCoverage
Unit percentDirection higher is better

Line coverage reported by SonarQube.

How it is computed

Evidence
SonarQube coverage measure.
Formula
Returns line coverage percentage.
Notation
coverage = sonar.coverage
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
review-timeReview time
Unit daysDirection lower is better

Average time from change request creation to review.

How it is computed

Evidence
Merged or closed change requests with created and merged/closed timestamps, grouped by author.
Formula
Computes each author's average review days, then averages those author values into one score, rounded to two decimals.
Notation
value = mean(review_days(author))
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
review-participationReview participation
Unit reviewersDirection higher is better

Number of unique reviewers participating in the window.

How it is computed

Evidence
Comments on change requests with the commenter login.
Formula
Counts unique commenters (reviewers) in the selected window.
Notation
reviewers = |{comment.author}|
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
pair-programmingPair programming
Unit percentDirection higher is better

Pairing index across analyzed commits.

How it is computed

Evidence
Git commits with co-authors and changed files.
Formula
Pairing index equals paired commits divided by total analyzed commits times 100.
Notation
pairing_index = paired_commits ÷ total_commits × 100
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
knowledge-distributionKnowledge distribution
Unit percentDirection higher is better

Share of touched lines not owned by the top contributor.

How it is computed

Evidence
CodeMaat entity ownership with author, added, and deleted lines.
Formula
100 minus the top contributor's touched lines divided by total touched lines times 100, where touched equals added plus deleted.
Notation
distribution = 100 − (top_owner_touched ÷ total_touched) × 100
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
couplingCoupling
Unit degreeDirection lower is better

Average file coupling degree.

How it is computed

Evidence
CodeMaat file-coupling pairs and their degree.
Formula
Arithmetic mean of all coupling degrees, rounded to two decimals.
Notation
coupling = mean(degree)
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
ownershipOwnership
Unit percentDirection lower is better

Share of touched lines owned by the top contributor.

How it is computed

Evidence
CodeMaat entity ownership with author, added, and deleted lines.
Formula
Top contributor's touched lines divided by total touched lines times 100, rounded to two decimals.
Notation
ownership = top_owner_touched ÷ total_touched × 100
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health
componentsComponents
Unit componentsDirection neutral

Number of components in the architecture component view.

How it is computed

Evidence
Architecture component-view nodes.
Formula
Counts nodes whose kind is component.
Notation
count = |{node: node.kind = component}|
CLIengineering-health evaluate
REST/engineering-health/evaluate
MCPsmm_get_engineering_health

The catalog and the CSV file are generated from packages/core/src/domain/metrics/ with pnpm docs:metrics. pnpm docs:metrics:check fails when the committed artifacts drift from the catalog, and the core test suite checks the same files.

Inspect the catalog ​

bash
# Every catalogued metric
smm metrics list

# Only one namespace
smm metrics list --namespace cr

# Include internal metrics (omitted by default on public filters)
smm metrics list --visibility internal

# Machine-readable output, including evidence, formula, and notation
smm metrics list --output json
text
GET /metrics
GET /metrics?namespace=eh&visibility=public
text
MCP tool:     smm_list_metrics

Where to see it in the dashboard ​

Open References & Sources (/dashboard/references, book icon in the top bar). The page reads GET /metrics and shows every catalogued metric that carries a documented target, grouped by namespace. Each card shows the stable id, the target, the description, and the external papers, reports, and books behind it.

The summary chips at the top of the page are clickable and reveal what they count:

  • Documented metrics — every metric that has a published target or source, linked to its card.
  • Sources — the consolidated source index with the metrics that cite each work.
  • Catalogued metrics — the full catalog, flagging entries that have no published reference yet.

Dashboard cards use the same catalog entries for their info popover, so a target or source is defined once in packages/core/src/domain/metrics/.

Stability ​

  • Ids are public API. Renaming one is a breaking change; mark the entry deprecated and point replacedBy at its successor instead.
  • Published targets and sources live in metric-references.ts, keyed by CatalogMetricId, so evidence cannot reference an unknown metric id.
  • Every entry defines computation.evidence (the records and fields identified as input), computation.formula (how that input becomes the reported value), and computation.notation (the compact mathematical form). All three are exposed by the CLI, REST API, MCP server, dashboard cards, and the generated CSV.
  • The CLI, REST, and MCP surfaces are checked against the catalog by coverage tests in their owning apps.

Released under the MIT License.