Skip to content
Merged
5 changes: 5 additions & 0 deletions .changeset/green-kings-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@systemfsoftware/stryker-js": major
---

Every failed run ends in one FailureRecord: printed on stderr, emitted as the terminal stream event, and written to reports/mutation/failure.json. StageError and PrepareError are replaced by RunFailure, exit codes come from the failure catalog (a failing baseline test exits 5), failed baseline tests are named by project-relative file and line, and the cli.run span carries stryker.failure.code.
5 changes: 5 additions & 0 deletions .changeset/moody-snails-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@systemfsoftware/stryker-js-cli-contract": minor
---

RunFailed now carries a typed FailureRecord (catalog code, stage, structured evidence, cause chain, next action, replay capsule, trace id) instead of error/remediation/reason prose; the stream schema is 3.0. The package publishes contract/failure-catalog.json and FailureRecord renderers for terminal, markdown, GitHub annotations and SARIF.
5 changes: 5 additions & 0 deletions .changeset/small-results-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@systemfsoftware/stryker-js-plugin-interface": major
---

FailedTestResult carries an optional project-relative source location and the raw stack; the unused startPosition field is removed.
5 changes: 5 additions & 0 deletions .changeset/upset-chicken-hammer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@systemfsoftware/stryker-js-vitest-runner": minor
---

Failed tests report the first project source frame as their location and keep the raw stack; file-level failures are named and identified by their project-relative path.
288 changes: 288 additions & 0 deletions packages/stryker-js-cli-contract/contract/failure-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
[
{
"id": "ArgumentsInvalid",
"name": "ArgumentsInvalid",
"meaning": "The command line named an option, argument or subcommand the CLI does not accept.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "ConfigInvalid",
"name": "ConfigInvalid",
"meaning": "The configuration could not be read or failed validation.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "PluginNotFound",
"name": "PluginNotFound",
"meaning": "The configuration names a plugin that is not installed or not registered.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "PluginLoadFailed",
"name": "PluginLoadFailed",
"meaning": "A configured plugin refused to load: a peer is missing or unsupported, or its contribution is invalid.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "PluginImportFailed",
"name": "PluginImportFailed",
"meaning": "A configured plugin module threw while it was being imported.",
"exitCode": 4,
"nextAction": {
"primary": "reportToolDefect",
"otherwise": "fixConfiguration"
},
"capsule": "replays"
},
{
"id": "SurvivorsUnavailable",
"name": "SurvivorsUnavailable",
"meaning": "Survivors were requested but no matching mutation report exists.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "NoInputFiles",
"name": "NoInputFiles",
"meaning": "The configured file patterns matched no input files.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "SandboxPreparationFailed",
"name": "SandboxPreparationFailed",
"meaning": "The project could not be read or copied into the sandbox.",
"exitCode": 3,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": "retryInfrastructure"
},
"capsule": "replays"
},
{
"id": "InstrumentationFailed",
"name": "InstrumentationFailed",
"meaning": "The instrumenter could not read or mutate a source file.",
"exitCode": 3,
"nextAction": {
"primary": "reportToolDefect",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "CheckerFailed",
"name": "CheckerFailed",
"meaning": "A checker failed or broke its protocol while checking mutants.",
"exitCode": 3,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": "reportToolDefect"
},
"capsule": "replays"
},
{
"id": "TestRunnerFailed",
"name": "TestRunnerFailed",
"meaning": "The test runner could not be started or failed outside of any test.",
"exitCode": 3,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": "reportToolDefect"
},
"capsule": "replays"
},
{
"id": "BaselineTestsFailed",
"name": "BaselineTestsFailed",
"meaning": "One or more tests failed in the initial test run, before any mutant was applied.",
"exitCode": 5,
"nextAction": {
"primary": "fixCode",
"otherwise": "fixTest"
},
"capsule": "replays"
},
{
"id": "BaselineTimedOut",
"name": "BaselineTimedOut",
"meaning": "The initial test run did not finish within its time limit.",
"exitCode": 5,
"nextAction": {
"primary": "fixTest",
"otherwise": "retryInfrastructure"
},
"capsule": "replays"
},
{
"id": "BaselineErrored",
"name": "BaselineErrored",
"meaning": "The initial test run errored outside of any test.",
"exitCode": 5,
"nextAction": {
"primary": "fixTest",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "BaselineFoundNoTests",
"name": "BaselineFoundNoTests",
"meaning": "The initial test run found no tests to run.",
"exitCode": 2,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "WorkerBootTimedOut",
"name": "WorkerBootTimedOut",
"meaning": "A worker process did not finish booting before its boot window closed.",
"exitCode": 3,
"nextAction": {
"primary": "retryInfrastructure",
"otherwise": "reportToolDefect"
},
"capsule": "replays"
},
{
"id": "WorkerOutOfMemory",
"name": "WorkerOutOfMemory",
"meaning": "A worker process was killed for running out of memory.",
"exitCode": 3,
"nextAction": {
"primary": "retryInfrastructure",
"otherwise": null
},
"capsule": "outOfMemory"
},
{
"id": "WorkerCrashed",
"name": "WorkerCrashed",
"meaning": "A worker process exited unexpectedly.",
"exitCode": 3,
"nextAction": {
"primary": "retryInfrastructure",
"otherwise": "reportToolDefect"
},
"capsule": "workerCrashed"
},
{
"id": "ReporterFailed",
"name": "ReporterFailed",
"meaning": "A reporter could not be started or failed while reporting.",
"exitCode": 3,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "RunInterrupted",
"name": "RunInterrupted",
"meaning": "The run was interrupted by a signal before it finished.",
"exitCode": 130,
"nextAction": {
"primary": "retryInfrastructure",
"otherwise": null
},
"capsule": "interrupted"
},
{
"id": "NewSurvivors",
"name": "NewSurvivors",
"meaning": "Mutants the change can affect survived every test and are absent from the accepted survivor baseline.",
"exitCode": 1,
"nextAction": {
"primary": "killSurvivor",
"otherwise": "refactorAwayEquivalent"
},
"capsule": "replays"
},
{
"id": "InvariantBroken",
"name": "InvariantBroken",
"meaning": "Stryker reached a state its own design rules out; this is a defect in Stryker.",
"exitCode": 4,
"nextAction": {
"primary": "reportToolDefect",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "CatalogGap",
"name": "CatalogGap",
"meaning": "A failure no catalog entry classifies; the record carries its full cause.",
"exitCode": 4,
"nextAction": {
"primary": "reportToolDefect",
"otherwise": null
},
"capsule": "replays"
},
{
"id": "RecordMissing",
"name": "RecordMissing",
"meaning": "A CI job ended without a failure record or a report.",
"exitCode": null,
"nextAction": {
"primary": "reportToolDefect",
"otherwise": null
},
"capsule": "recordMissing"
},
{
"id": "JobTimedOut",
"name": "JobTimedOut",
"meaning": "A CI job was killed for exceeding its time limit.",
"exitCode": null,
"nextAction": {
"primary": "retryInfrastructure",
"otherwise": null
},
"capsule": "jobTimedOut"
},
{
"id": "BinaryMissing",
"name": "BinaryMissing",
"meaning": "A CI job could not find a binary it needs.",
"exitCode": null,
"nextAction": {
"primary": "fixConfiguration",
"otherwise": null
},
"capsule": "binaryMissing"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"stryker.run.exit_code": {
"type": "number"
},
"stryker.run.error": {
"stryker.failure.code": {
"type": "string"
}
}
Expand Down
Loading
Loading