get_health gives your agent the Code Health
layer directly: a 1 to 10 score per file across three signals (defect risk,
maintainability, performance), the marker findings behind it, repo-level
KPIs, refactoring and performance queues, and trend alerts. Zero LLM calls; it
reads precomputed metrics. Which finding types it lists by default is on
Findings and triage, and the other tools are on
MCP tools.
It never recomputes. To refresh the numbers, commit and run
repowise update. Calling get_health again on a dirty working tree
returns the same stored analysis.
When to call
- Self-check before a PR. Read the same signals a code-health merge-gate judges the change on. Pass the files you touched and confirm you are not regressing the worst files.
- Before a refactor. Find the lowest-scoring files and the specific markers dragging them down.
- Triage. Dashboard mode returns the repo's worst files ranked, plus the "does the score find the bugs?" stat so the agent knows the score is trustworthy on this repo before acting on it.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
targets | string[] | — | File paths, or a "module:foo" target that expands to the module's file set. Empty -> dashboard mode (repo KPIs + lowest-scoring files). |
include | string[] | — | Opt-in blocks (the default response stays lean): "biomarkers" (findings in dashboard mode), "refactoring" (the refactoring queue), "trend" (snapshot diff + alerts), "coverage", "accuracy" (does-the-score-find-the-bugs stat, dashboard mode), "signals" (per-file process/people/topology, targeted mode), "churn_complexity" (churn x complexity points, dashboard mode), "doc_drift" (documentation drift findings), "what_if" (the points each fix recovers), and a dimension name ("performance" / "defect" / "maintainability" / "advisory") to filter findings to that pillar. "advisory" holds markers that never change a score, such as assertion_free_test and mock_saturated_test. "performance" and "refactoring" also add their queues. |
only | string[] | — | Keep just these top-level keys. include adds blocks, only subtracts them. mode, _meta, unresolved, known_modules, and each kept list's *_total sibling always survive. The include block names work as aliases: biomarkers -> findings, accuracy -> defect_accuracy, refactoring -> refactoring_plans. The dimension names do not resolve to a key and land in unknown_only_keys; neither does signals, which merges into metrics[].signals. |
repo | string | — | Repository alias. Usually omitted: in a workspace, targets route to the repo that owns them, one repo per call. "all" is not supported. |
limit | number | 20 | Max rows in every ranked list (capped at 50). 0 means no rows; the *_total siblings still report the true counts. |
cursor | number | 0 | Zero-based offset into a ranked collection. The recovery block names the exact next call. |
fix_id | string | — | Open one fix_first item (fix1_...) in full, or one get_overview next_actions action (act_...) with its details and commands. |
finding_id | string | — | Resolve one emitted health-finding id directly in one call. |
plan_id | string | — | Resolve one emitted refactoring-plan id directly in one call. |
opportunity_id | string | — | Resolve one opportunity id. The prefix picks the pillar: "perf..." is a performance cause, "refop..." a composed refactoring. Mutually exclusive with finding_id and plan_id; passing more than one returns mode: "conflict" naming them. |
refactoring_view | string | diversified | Ordering for refactoring_opportunities: "diversified" (default, round-robins the rank order over cause, type and area), "canonical" (the published rank order verbatim), or "file_spread" (resolves onto the diversified order). |
refactoring_type | string | — | Queue filter over the refactoring read model. An unrecognized value is reported in ignored_arguments instead of silently narrowing to nothing. |
refactoring_confidence | string | — | Queue filter on the plan's confidence. Same unrecognized-value handling. |
refactoring_effort | string | — | Queue filter on the plan's effort bucket. Same unrecognized-value handling. |
performance_view | string | — | "detail" (default) or "summary". summary keeps identity, counts and plan state and drops the explanatory fields. |
performance_context | string | — | "production" (default) / "tooling" / "test" / "unknown" / "all". repository_total stays the count over every context. |
performance_boundary | string | — | "db" / "network" / "filesystem" / "subprocess" / "lock" / "none". |
performance_confidence | string | — | Evidence confidence: "high" / "medium" / "low". Fix safety and actionability are separate facets. |
performance_actionability | string | — | Queue filter: "plan_ready" / "advisory" / "investigate" / "expected" (repetition with no batch operation to point at, or a loop already chunked). |
performance_sort | string | — | "rank" (default) / "leverage" / "observations". |
scope | string | all | Which files every figure describes: "all" (default) or "production". Tests score higher than production code, so production lowers the number without a defect having been found. |
counts | string | everything | What the score counts: "everything" (default, the calibrated number) or "code_shape", which removes the git-derived half. Files with no stored split land in unscored_files instead of being counted. |
An unrecognized scope or counts falls back to the default and is
named in ignored_arguments, so a misspelling never answers a different
question under the name you asked for. A value that belongs to the other
control (scope="code_shape") also gets ignored_arguments_hint naming the
right one. Both are echoed on the response.
Returns
Dashboard mode (no targets) leads with fix_first, one ranked queue
across defect, maintainability and performance, then repo-level KPIs:
| Field | Meaning |
|---|---|
fix_first | The queue: lead (the first item, with its first_step and verify when due), up to five items, items_total, counts, and detail_call, the get_health(fix_id=...) call that opens the lead in full. only=["fix_first"] with limit pages up to 25 items. Read this first |
kpis.average_health | NLOC-weighted average over all files |
kpis.average_health_unweighted | The plain file mean, for comparison against the NLOC-weighted headline |
kpis.maintainability_average / kpis.performance_average | The maintainability and performance pillar headlines (null until measured) |
kpis.worst_performer_path / kpis.worst_performer_score | Single lowest-scoring file and its score |
kpis.production_average | Production code alone, present while tests are part of average_health |
gap_analysis | Net weighted points the average must recover to reach the Healthy floor (8.0), how many files sit below it, and files_to_reach_target / files_for_half_gap |
high_leverage_files | Top files ranked by weighted_deficit (score gap x NLOC), distinct from worst_files, which sorts by raw score alone |
worst_files | Ranked worst files by raw score |
modules | Per-module NLOC-weighted health rollup, worst-first, capped by limit; modules_total is the uncapped count |
unresolved | Any targets entry that matched nothing, with a reason (not_indexed, no_such_path, excluded, not_measured, no_such_module) |
share_of_repo_gap_pct is measured against the gross deficit of all
below-target files, not the net gap, so per-file shares are bounded by
100% and sum to 100% across high_leverage_files.
There is no kpis.hotspot_health on the dashboard KPIs; the hotspot-only
NLOC-weighted average only exists inside the opt-in trend block, as
current_hotspot_health / previous_hotspot_health (see below).
Targeted mode (targets given) returns mode, targets, metrics
(one row per file: file_path, score, maintainability_score,
performance_score, weighted_deficit, is_test, complexity/coverage
stats, the dominant-finding lead, and structure_deduction and
history_deduction: the score is 10 minus both, before the 1.0 floor; a
file with fewer than 5 recorded commits carries history: "short"),
metrics_total, findings (type,
severity, line span, reason, and a dimension), and findings_total.
Depending on what matched, it also carries unresolved, known_modules
(after an unresolved module: target), trends (per-file score history,
silent when a file has fewer than 2 snapshots), and modules (when the
target list includes a module: target). There is no per-file "score
breakdown by category" field, and no defect_score field: it was set
from the same value as score on every row, so score is the one to
read. The field to rank files on is neither score nor
maintainability_score / performance_score, but weighted_deficit.
Test material is bucketed, not hidden
Every metric row carries is_test, which is distinct from
has_test_file: "is this file a test" versus "is this file tested". In
dashboard mode the ranked finding lists are split. top_findings and
findings carry production findings, test_findings carries the test
half, and top_findings_total + test_findings_total is the whole open
set. Defect risk in a test asks a different question from defect risk in
the code it covers, and at the default limit a quarter of the headline
list was describing the test suite.
Targeted mode is never split: you named the files, so you get their
findings. kpis deliberately still include test files, because
excluding them would move the repo's headline score, which is a scoring
change and not a display one. worst_files and high_leverage_files are
production files; tests rank in test_worst_files.
Opt-in enrichments
biomarkersreturns the full (uncapped) findings set in dashboard mode. Pair with a dimension name, e.g.include=["biomarkers", "performance"], to narrow to one pillar.what_iftakes up to 10 worst files (or the targets) and gives each aceiling(the most an edit can reach, with no structure deduction left),target_out_of_reachwhen that is below 8.0, the gain from fixing all its structure findings, and its top 3findings.top_fixesranks single fixes across them, each withpointsand itsgainto the file, the headline average and, for a hotspot, hotspot health.trendadds atrendblock:current_hotspot_health/previous_hotspot_health(the NLOC-weighted average over hotspot files only),current_average_health/previous_average_health,hotspot_delta,average_delta,alerts, andrecent(up to 10 past snapshots).accuracyadds adefect_accuracyblock: of the K least-healthy files, how many were recently bug-fixed vs the repo-wide base rate (precision@K +lift), with a per-K table and the flagged files.nullon repos with too little history to be honest (fewer than 25 scored files or fewer than 5 recently-fixed files).signalsadds asignalsobject on each targeted metric: prior-defect count, change scatter, 90-day churn, primary / recent owner, and graph in / out degree. Honestnullper field when the underlying row is absent, never an imputed zero.churn_complexityaddschurn_complexitypoints (one per recently-changed file: 90-day commits, max CCN, NLOC, score, churn percentile).- dimension filter narrows findings to one pillar; pair with
"biomarkers"for the full set, e.g.include=["biomarkers", "performance"].
Refactoring: the composed unit, then the raw plans
include=["refactoring"] leads with refactoring_opportunities: one
composed unit per file, carrying the diagnosis it leads with
(lead_biomarker), whether it actually addresses that diagnosis
(addresses_primary_problem, tri-state, where null means no dominant
finding was recorded and is not false), its ordered steps with a
mechanical or judgment applicability each, and counts for the
evidence behind it. refactoring_view orders the list. A step carrying
relocated_by names an earlier step that moves its symbol to another
file, so locate the symbol again before applying it.
refactoring_plans, the raw per-detector list, is opt-in: name it in
only to get it. Emitting both would ship two representations of the
same work in one response. Each plan keeps its evidence,
impact_delta, effort_bucket, blast_radius and an id for
generate_refactoring_code, and
is addressable by plan_id. The four kinds are extract_class (the
cohesion groups to split into), extract_helper (clone occurrences
plus suggested_site), move_method and break_cycle (the import
cut_edges).
get_health(opportunity_id="refop...") returns the full ordered steps,
the member plan payloads, the validation profile and structured
next_actions. only=["refactoring_evidence"] plus cursor pages the
evidence. only=["refactoring_summary"] is the rollup by type, effort,
confidence and lifecycle, with facets.
include=["refactoring"] also emits suggestion_legend, a
biomarker_type to prose-suggestion lookup emitted once per response
instead of per finding. Join on biomarker_type. It explains the
findings, not the plans it ships beside; the two sets differ.
Performance: one lead, then drill down
Performance findings carry health_impact: 0 by construction, because
the pillar is deliberately never blended into the score. They therefore
reach fix_first through their own queue rank. only=["performance_opportunities"]
lists the ranked causes, and opportunity_id opens one.
Performance rows rank on an integer perf_rank, absent on defect and
maintainability rows, which rank on weighted_deficit. It is an ordering
key and not a score, and it reads three signals the row already carries,
so you can re-rank on your own weights from the same payload: the marker
(biomarker_type), the boundary (details.boundary_kind, where a
subprocess spawn in a loop outranks a stat in a loop), and the call
shape (details.cross_function).
Ids are stable within a performance model version and are never
translated across one. An id from an older model resolves to
model_state.state: "stale_model" with refresh_required, instead of
failing to match and reading as "no plan".
Example
get_health(only=["fix_first"]) # cheapest useful call: what to fix first
get_health(fix_id="fix1_...") # open one fix_first item in full
get_health() # fix_first, kpis, gap_analysis, worst + high-impact files
get_health(include=["accuracy", "churn_complexity"]) # is the score trustworthy + danger zone
get_health(include=["biomarkers", "performance"]) # only performance-pillar findings
get_health(targets=["src/api/server.py"], include=["signals"]) # self-check one file
get_health(include=["refactoring"], only=["refactoring_opportunities"], limit=6)
get_health(opportunity_id="refop2_...")
get_health(include=["performance"], only=["performance_opportunities"], performance_context="all")
get_health(only=["kpis"], limit=0) # headline numbers, no rows at all
get_health(targets=["src/api/server.py"], include=["what_if"]) # what each fix is worthThings worth knowing
- Deterministic and offline. The markers run off tree-sitter + git data with calibrated weights: no model calls, reproducible scores.
- Three signals, never blended.
scoreis the defect-calibrated headline; maintainability and performance are co-equal companion views with their own per-file scores anddimension-tagged findings. - Coverage is opt-in. The coverage markers
(
untested_hotspot,coverage_gap,coverage_gradient) only fire once you've ingested a report viarepowise coverage add.include=["coverage"]also carrieshistory, the newest 10 ingests, for a trend. - Module targets (
module:foo) expand to every file under the module, so one call covers a whole package. primary_biomarkerprefers a discrete cause over a continuous one.coverage_gradientfires on every file with coverage data at all, so on a well-covered repo it would headline every entry with "N% of lines uncovered", true of the file and equally true of its neighbours. The gradient still counts in full toward the score.- Every language is served, some in preview. On a language whose
layer is still measured below the precision bar, rows carry one
compact
_meta.previewentry with the latest hand-judged measurement. Health findings ship normally on Java, C# and C. Git-history-only markers on production files are counted underhistory, outside the default defect lists, andinclude=["unverified"]shows held rows. - Pair
includewithonly.includeonly adds blocks, and the dashboard's ranked lists compose.include=["refactoring"]on a mid-size repo lands near the host's tool-result cap, past which the host rejects the whole result and you get nothing. Anything shed carriestruncated: true, the*_total/*_emitted/*_reduced_reasonsiblings, and_meta.omittedrefs that restore the dropped rows. _meta.health_analysislabels the result as stored analysis and states that the call did not recompute it. Itsstatusisavailable,provenance_unknown(metrics exist but no row recorded the commit they were computed against), orunavailable._meta.health_analyzed_atand_meta.health_analyzed_commitdate the health pass, which is separate from indexing and can lag it. The incremental update path rescores only changed files, so when the table holds rows from several passes_meta.health_analyzed_commits_distinctsays how many.
For the full marker reference, the three-signal model, the
defect-prediction benchmark, and the head-to-head against the leading
commercial tool, see the
Code Health layer page. For the structured
plans behind include=["refactoring"], see
Refactoring intelligence.