npx skills add ...
npx skills add codeceptjs/skills --skill ci-fix-tests
Use on CI in non-interactive mode after a failed CodeceptJS run — attempts safe fixes only (locator drift, missing waits), reruns failing scenarios, rolls back edits that didn't help, reports at `output/ci-fix.md`. No refactors, no config edits, no flake-masking. Trigger on \"ci fix tests\", \"auto-fix failing tests\", \"attempt repair on CI\", or as a CI step after a failed run.
npx skills add codeceptjs/skills --skill ci-fix-tests
A non-interactive auto-repair loop. Reads the failed-tests baseline from output/ (where aiTrace left trace artifacts), attempts a small set of safe fixes, reruns only the failing scenarios, compares, and writes a report at output/ci-fix.md. Rolls back any edit that didn't help.
Conservative by design. CI is not the place to restructure tests, change abstractions, or fix anything that needs human judgement. The goal is "pass the run". Anything riskier is escalated through the report.
This skill assumes a working git checkout — rollback uses git checkout -- <file> to restore originals.
Use the codeceptjs-run-analysis skill against the existing output/trace_*/ artifacts to enumerate every failing scenario. Record:
Save this as the baseline — count, failing_set, clusters.
Only attempt fixes from this allowed list:
I.click('Save', '.toolbar') — in this order: visible text / accessible name → ARIA { role, name } → $name (customLocator) → composed CSS. Replace the locator at the failing step only.I.waitFor* immediately before the failing step.I.wait(N) replacement — when a hardcoded sleep is the only thing between a failing assertion and a passing one and the gating element is identifiable, replace the sleep with a specific waitFor*.Do not attempt:
--grep and pipelines reference them.retries: N to a Scenario — masking flake is a human decision.codecept.conf.*, no helper, no PO edits).If a failure doesn't match any allowed-fix pattern, skip it and record it as unresolved for the report.
Track every modification: file path, line number, before/after snippet, fix kind. Then rerun only the failing scenarios under the same config CI used:
Find the right config via package.json scripts or the CI workflow file. Match the worker count if run-workers was used originally.
Use codeceptjs-run-analysis again to enumerate the failing set after the fix.
| New failing-set vs baseline | Status |
|---|---|
| Empty (zero failures) | SUCCESS_FULL |
| Strict subset of the baseline | SUCCESS_PARTIAL |
| Identical set | NO_IMPROVEMENT |
| Larger, or contains a test not in baseline | REGRESSED |
SUCCESS_FULL / SUCCESS_PARTIAL → keep the edits.NO_IMPROVEMENT / REGRESSED → roll back every edit with git checkout -- <files>. The on-disk state at the end of the skill must be identical to what it was at the start.A regression is treated the same as no improvement — the attempt didn't work, the working state is what was on disk before. Don't try to "undo only the bad ones" — the whole batch goes.
Write output/ci-fix.md regardless of outcome — CI reads it to surface results.
The first line of Status: is the machine-parseable signal. The rest is for the human reading the failed CI build.
retries: N to mask flakiness — human decision.NO_IMPROVEMENT. Even no-op edits can confuse the next run or the next reviewer.output/ci-fix.md. CI depends on it; the absence of a report is itself a failure mode.codeceptjs-run-analysis — baseline, clustering, post-fix comparisoncodeceptjs-exploration — replacement locators for driftcodeceptjs-fundamentals — config, helper, CI environment# CI Fix Report — <ISO timestamp>
**Status:** SUCCESS_FULL | SUCCESS_PARTIAL | NO_IMPROVEMENT | REGRESSED
## Baseline
Failing scenarios: N
- `tests/foo_test.js` — "user can log in"
- `tests/bar_test.js` — "checkout flow"
- ...
## Attempted fixes
- `tests/foo_test.js:42` — locator drift: `I.click('Save')` → `I.click('Save', '.toolbar')`
- `tests/bar_test.js:15` — added `I.waitForInvisible('.spinner')` before checkout click
- `tests/baz_test.js:7` — replaced `I.wait(3)` with `I.waitForVisible('.confirmation-dialog', 10)`
## Result
Failing scenarios after fix: M (was N)
- Resolved: `tests/foo_test.js` — "user can log in"
- Still failing: `tests/bar_test.js` — "checkout flow"
- New failures (REGRESSED only): `tests/baz_test.js` — "edit profile"
## Failure clusters (NO_IMPROVEMENT / REGRESSED only)
- **Cluster A (3 scenarios)** — `Element not found: button.btn-primary`. Likely a deploy regression or design change.
- **Cluster B (1 scenario)** — `Navigation timeout to /checkout`. Possible backend issue.
## Discarded changes (NO_IMPROVEMENT / REGRESSED only)
- `tests/foo_test.js` — restored
- `tests/bar_test.js` — restored
- `tests/baz_test.js` — restored