npx skills add ...
npx skills add momentic-ai/skills --skill momentic-maintain
Diagnose, classify, triage, and repair failing Momentic tests with MCP run tools, the Momentic CLI, and manual run artifacts. Use when a developer asks what happened on a branch, DevX or on-call asks why main is red, or the user wants to inspect classifications, de-flake quarantined or recovered tests, reduce retries, re-classify runs, run AI triage, or repair failures.
npx skills add momentic-ai/skills --skill momentic-maintain
Find the earliest point where a run entered a bad state, classify the cause from
evidence, and repair the test when a durable test change is appropriate. Use MCP
for targeted investigation, momentic ai classify for a fresh classifier
verdict, and momentic ai triage for automated repair and verification.
Do not weaken a test to hide an application bug, missing fixture, invalid credentials, outage, or Momentic defect. Report those causes instead of changing the test to pass.
momentic_list_runs with the exact gitBranchName and bounded start/end. Start without a status filter, then narrow to FAILED, CANCELLED, or recovered=true. Open exact candidates and compare with main only for a concrete cross-branch question.FAILED runs on the actual main branch over the incident window and paginate through every page needed for the claim. Narrow with failureCategory when investigating a known category, but group symptoms only after inspecting representative runs and step evidence. Read each exact run's saved classification before optionally re-classifying it.momentic_quarantine_list for quarantined tests, recovered=true for successful runs that needed recovery, and minAttempts for retry-heavy runs (2 means at least one retry; 3 means at least two). Inspect earlier attempts, prioritize repeated same-intent failures, fix the earliest unstable postcondition, and measure again.Know the discovery limits:
momentic_list_runs filters by test, branch, status, quarantine, recovery, effective failure category, minimum total attempts, and time. failureCategory uses a manual classification when present, otherwise the automated classification.momentic_quarantine_list filters by quarantine date and returns each active quarantine's latest retained failed CLI run. It does not filter by branch or classification.pageCount pages needed before calling an inventory exhaustive.Fetch raw run metadata before MCP investigation when an API key is available:
Do not treat a missing field as proof that no human reviewed the failure until the metadata request succeeds for the exact run and organization. Do not echo, log, or commit the API key. Treat downloaded metadata and signed artifact URLs as sensitive run data.
momentic_get_run intentionally removes prior classification and heal fields
from the evidence it returns so a fresh investigation is not anchored by an old
verdict. Use the metadata endpoint or dashboard for the existing verdict, then
use MCP for the underlying evidence.
momentic_get_run - Return run metadata and a summary of the full result tree.
Use it to identify the attempt, failed section, failing step, and nested parent
chain. If the current run is already loaded, call it again only for a different
attempt or missing data.
momentic_list_runs - List recent runs for the test. Always pass
gitBranchName when it exists on the target run so comparisons are more likely
to use the same test version. Omit it only when cross-branch history answers a
specific question. Pass recovered=true to inspect recovered runs.
Pass failureCategory to select effective manual/automated classifications and
minAttempts: 2 or higher to find retried runs.
momentic_quarantine_list - List active local test quarantines and each test's
latest retained failed CLI run. Use a bounded quarantine-date range.
momentic_get_step_result - Return command details, before/after screenshots,
and optionally the full trace for one step. Pass parentStepIdChain for nested
steps. Request includeTrace=true only when screenshots and normal fields do
not answer the question.
momentic_get_test_steps_for_run - Return the simplified test definition
recorded on a run. Use it when test intent remains unclear or when comparing
whether the authored test changed between runs.
momentic_submit_result_classification - Persist a manual MCP classification.
Call it only after the investigation is complete and only when the user asked to
record the verdict. Do not call it in addition to ai classify --save for the
same conclusion.
Start with the current run before relying on history.
momentic_get_run and identify the failing attempt, section (beforeSteps, main steps, or afterSteps), failing step, and any parentStepIdChain.Before classifying, be able to answer:
Avoid vague root causes such as "setup was unreliable" or "the page was in the wrong state." Name the broken postcondition directly: for example, "the row-level plus button was clicked, but the app stayed on the parent page instead of opening the child-page editor; the following global Add to assertion passed against unrelated page text, so the untargeted type step never entered the child title."
momentic ai classify runs Momentic's result-classification agent over failed
runs. It reads the run artifacts, uses relevant run history and repository
context, and returns a category, recoverability, confidence, reasoning, and
citations. It explains the failure; it does not edit the test.
Use one selector per command:
--save for a diagnostic re-classification. Add --save only when the
new verdict should replace the saved classification on the local archive or
cloud run.--no-cache when the existing cached classifier result is suspected to
be stale and the user explicitly needs a fresh analysis.--skip-classified when resuming a batch without revisiting runs that
already have saved classifications.--output-format json for automation and multi-run bookkeeping.For one run in a real terminal, keep the classifier conversation open:
Use the chat to ask why it chose the category, what evidence it relied on, how the current run differs from a prior run, or what a durable fix would require. Interactive classification is single-run only, requires stdin to be a TTY, and cannot be combined with JSON output.
Treat application readiness as a hard precondition. Triage replays the test in a real browser; it cannot repair a test against an unavailable app, missing fixture, wrong environment, unseeded database, invalid account, or cold compiler.
Before triage:
momentic.config.yaml, the target test and its setup modules, repository
scripts, and the CI workflow that normally runs the test. Use the same URL,
environment, credentials, headers, files, services, and data fixtures.MOMENTIC_API_KEY, project configuration, dependencies, and the
requested browser are available.git status and preserve unrelated work. Decide the repair delivery
before running the command; do not let an unknown dashboard default create a
pull request or commit unexpectedly.--parallel 1. Raise it only when the machine has enough CPU and
memory for one browser and application workload per worker.If the repository exposes a stable server command, either start it separately
or let triage own it with --start and --wait-on:
Do not copy these example commands blindly. Discover the real build, start, and readiness contract from the repository and CI configuration.
momentic ai triage groups failures by shared root cause, decides which ones
are repairable, edits the relevant tests, replays them in a browser, and accepts
only repairs that satisfy its verification. It can leave changes locally,
produce a patch, commit, or open a pull request. It cannot fix an application
bug, external outage, or missing fixture by changing a test.
Run classification first when the user wants an explicit diagnosis, then pass the same target to triage:
For a local run group, pass the results directory instead:
Best practices:
--run-id so the bucketing agent can
group shared causes. Do not launch one competing triage command per run.--on-heal-success explicitly: use nothing for local review, patch
for a portable diff, or a pull-request/commit behavior only when the user
asked for that delivery.--yes only after the environment and delivery choice are confirmed so
dependency prompts do not stall an autonomous run.--dry-run --no-save to inspect bucketing without editing tests or saving
triage metadata. Dry-run is not a repair attempt.--regenerate-heal only when a cached heal is stale or failed and a new
repair should be generated from scratch.Use interactive triage when the user wants to question the repair agent:
Interactive triage requires a TTY, cannot be combined with --json, and is
available only when the command runs the bucketing agent. Use it to ask why a
fix was accepted or rejected, what setup it observed, and what evidence remains
unresolved.
Prefer MCP for ordinary inspection because momentic_get_run downloads and
extracts cloud attempts automatically. Use the API when MCP output is missing,
when raw files must be grepped, or when independently verifying the agent.
The export endpoint returns run metadata plus one short-lived signed ZIP URL per attempt; it does not return one combined run ZIP. Download and extract them without printing the URLs:
Inspect metadata.json, each attempt's metadata.json, screenshots, DOM
snapshots, console logs, HAR logs, video, resource usage, and crash archives.
Keep attempt numbers intact. Do not commit the export response, run artifacts,
signed URLs, credentials, or customer data. Remove the temporary directory when
the investigation is complete.
When momentic tests are run via the CLI, the results are stored in a "run group". The data for this run group is stored in a single directory within the momentic project. By default, the directory is called test-results, but can be changed in momentic project settings or on a single run of a run group. The run group results folder has the following structure:
When unzipped, run directories have the following structure:
When getting run results via the momentic MCP, tools such as momentic_get_run will return links to the MCP working directory (default .momentic-mcp). This directory will contain unzipped run result folders, following the structure above, named run-result-<runId>.
Certain step types that interact with elements have a "target" property, or locator, that specifies which element the step should interact with.
Locators identify elements by sending the page state html/xml to an llm as well as a screenshot. The llm identifies which element on the page the user is referring to. Momentic will attempt to "cache" the answer from the llm so that future runs don't require AI calls. On future runs, the page state is checked against the cached element to determine whether the element is still usable, or the page has changed enough such that another AI call is required.
A locator cache can bust for a variety of reasons:
You can find the cacheBustReason on the trace property in the results for a given step, but only when you explicitly request includeTrace=true. The cache property is also listed on the results, showing the full cache saved for that element.
Sometimes the element that was cached is not the element that the user intended to target. This can cause failures or unexpected behaviors in tests. In these cases, it helps to verify exactly why the wrong cache was saved in the first place. Only request includeTrace=true for these cache-debugging cases or when you suspect incorrect Momentic execution data. Use the runId property of the targetUpdateLoggerTags on the incorrect cache to get the details of the original run, calling momentic_get_run with this runId. This will return the run where the cache target was updated.
Cached modules skip executing their steps when the module cache key and resolved inputs are unchanged, and reuse the cached return value from the module's last step.
Authentication modules can also save and restore browser auth state from the module cache, including cookies, localStorage, and IndexedDB. They may use a page-content check after restoring auth state to decide whether the cache is still valid.
A file upload step prepares one file for the next native file picker, so it must run before the action that opens the picker.
Sources can be remote URLs, file:// references to earlier downloads, CLI-local paths, or uploaded user files. The step can also override the presented filename, and Momentic wires the prepared file into the browser's file chooser handling.
Past runs are comparison evidence, not a substitute for reconstructing the current run. Use them when the current run does not answer:
Use step results and screenshots on past runs to answer these questions. Do NOT rely only on summaries from momentic_get_run or momentic_list_runs to understand what happened in a test run. Look at the specific run details, including step results and screenshots, before citing a past run as evidence.
When looking at past runs, use the following workflow:
momentic_list_runs tool to identify the runs you want more detail on. Always pass gitBranchName when it exists on the run in question. Omit it when you need runs from other branches.momentic_get_run for that specific run to get the run details.momentic_get_step_result for the same step/container or closest equivalent you are comparing, especially for screenshots.When past runs are irrelevant because the current run already proves the root cause, say that briefly instead of forcing historical evidence.
When momentic_list_runs shows a passing run with attempts > 1, treat it as a partial failure worth investigating, not a clean passing run. Use the attemptNumber parameter to retrieve earlier failed attempt results for that run to understand what was going wrong before the retry succeeded.
get_test_steps_for_run to help you determine if the test itself changed between runs, although note that this tool returns a summary of each test step. If you suspect that specific details on certain steps have changed between test runs, full step details are included in the response from momentic_get_step_result; only request includeTrace=true when those fields and screenshots still are not enough.targetUpdateLoggerTags.runId.INFRA. First rule out missing data, wrong page state, changed app flow, bad locator/assertion, and setup failure.INFRA failure into another category.Along with the category, determine one recoverability value:
RECOVERABLE — The failure can be automatically fixed by updating the test itself so that future runs pass.
ONE_TIME_RECOVERABLE — The failure can be recovered for this specific run without persisting a test change.
NON_RECOVERABLE — The failure cannot be automatically addressed and requires manual intervention.
module create-subpage-under-parent-page, the last invocation of module <name>, substep 4 (0-indexed), the failed setup assertion, etc. Tool calls still require exact IDs, but final reasoning should be readable.https://app.momentic.ai/runs/<runId>. Do not shorten UUIDs inside those URLs.Confidence levels:
high — direct evidence, such as a clear screenshot of a label change or crashmedium — strong inference from multiple signals but no single conclusive screenshot or data pointlow — ambiguous evidence; the classification required significant inference or the root cause is unclearUse these strings verbatim:
NO_FAILURE — The run had no failures; all attempts passed.APPLICATION_CHANGE — The test is out of date because the application's flow or UI has changed; updating the test to match the new behavior would permanently fix the failure.BUG — Something clearly went wrong in the application that shouldn't have, such as an error message appearing or expected content failing to render.TEST_AUTHORSHIP — The test can be permanently updated to prevent the failure while still validating its original intent, and you can recommend a specific authorship change such as adding or modifying a step, rewriting a vague assertion, or making a locator description more specific. If you cannot name a concrete change, choose a different category. Timeouts, slow page loads, and any failure whose recommended fix is to "wait longer" or to increase a timeout are NOT authorship issues — those are INFRA, even when the test could technically be edited to wait longer.
TEST_SETUP — Missing test data or files necessary to run the test, where the fix requires user action outside of the test itself.
INFRA — The failure was unrelated to the application or application code and was caused by an infrastructure outage, long load times, or some other issue due to outside factors.
MOMENTIC_ISSUE — Some issue occurred with the execution of the test or Momentic data was incorrect (e.g. cache is wrong, global locator redirect did something weird, AI hallucinations).
OTHER — The failure doesn't fit any of the other categories.npx momentic ai classify --run-id "$RUN_ID" --output-format json
npx momentic ai classify --run-group-id "<run-group-id>"
npx momentic ai classify --git-commit "<commit-sha>"npx momentic ai classify --run-id "$RUN_ID" --interactive# Build first; use the repository's actual commands and readiness URL.
pnpm build
npx momentic ai triage --run-id "$RUN_ID" \
--start "pnpm start" \
--wait-on "http://localhost:3000/health" \
--parallel 1 \
--yes \
--on-heal-success nothingnpx momentic ai classify --run-id "$RUN_ID" --output-format json
npx momentic ai triage --run-id "$RUN_ID" \
--parallel 1 \
--yes \
--on-heal-success nothingnpx momentic ai triage ./test-results \
--parallel 1 \
--yes \
--on-heal-success nothingnpx momentic ai triage --run-id "$RUN_ID" \
--parallel 1 \
--yes \
--on-heal-success nothing \
--interactiveRUN_ID="<run-id>"
MOMENTIC_SERVER_URL="${MOMENTIC_SERVER:-https://api.momentic.ai}"
RUN_INSPECTION_DIR="$(mktemp -d)"
curl --fail --silent --show-error \
-H "Authorization: Bearer ${MOMENTIC_API_KEY:?Set MOMENTIC_API_KEY}" \
"${MOMENTIC_SERVER_URL}/v1/runs/${RUN_ID}/export" \
-o "${RUN_INSPECTION_DIR}/export.json"
jq '.run' "${RUN_INSPECTION_DIR}/export.json" \
> "${RUN_INSPECTION_DIR}/metadata.json"
jq -r '.attemptZipUrls | to_entries[] | select(.value != null) |
[(.key + 1), .value] | @tsv' "${RUN_INSPECTION_DIR}/export.json" |
while IFS=$'\t' read -r attempt url; do
mkdir -p "${RUN_INSPECTION_DIR}/attempts/${attempt}"
curl --fail --silent --show-error "$url" \
-o "${RUN_INSPECTION_DIR}/attempt-${attempt}.zip"
unzip -q "${RUN_INSPECTION_DIR}/attempt-${attempt}.zip" \
-d "${RUN_INSPECTION_DIR}/attempts/${attempt}"
donetest-results/
├── metadata.json data about the run group, including git metadata and timing info.
└── runs/ On zip for each test run in the run group.
├── <runId_1>.zip a zipped run directory containing data about this specific test run. Follows the structure described below.
└── <runId_2>.zip<runId>/
├── metadata.json run-level metadata.
└── attempts/<n>/ one folder per attempt (1-based n).
├── metadata.json attempt outcome and step results.
├── console.json optional browser console output.
└── assets/
├── <snapshotId>.jpeg before/after screenshot for each step (see attempt metadata.json for snapshot ID).
├── <snapshotId>.html before/after DOM snapshot for each step (see attempt metadata.json for snapshot ID).
├── har-pages.log HAR pages (ndjson).
├── har-entries.log HAR network entries (ndjson).
├── resource-usage.ndjson CPU/memory samples taken during the attempt.
├── <videoName> video recording (when video recording is enabled).
└── browser-crash.zip browser crash dump (only present on crash).Reasoning: <a few sentences tied to the earliest divergence, screenshots/traces, past runs if used, and test intent>
Category: <one id from the list>
Recoverable: <RECOVERABLE | ONE_TIME_RECOVERABLE | NON_RECOVERABLE>
Confidence: <high | medium | low>