Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/law-credit-label.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/oracles': patch
---

The gap report's per-law table is now titled "First law to reject, by law". It says that each count credits only the first law that rejected a history, because a check returns its first violation and a later law on the same history is not checked. A law with no count is not shown to reject nothing. The section's next step tells the author to add a history that varies the input the law judges.
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ function model(h) {
// sentence after its directive.
const boundaryLine = `Add a boundary history with -0 and 0.`
// The kills-by-law section's one next step for a law that rejects no mutant.
const killsDirective = `To find a law that rejects no mutant, add a history that varies the input the law judges, and run the check again.`
const killsDirective = `Each count credits only the first law that rejected a history: a later law on the same history is not checked. To test a law with no count, add a history that varies the input the law judges, and run the check again.`
const exits =
/equivalen|maintainer|approv|allowance|either|whether|\bor\b|\bif no\b|limit|accept|\?|\bsay\b/i
const directives = {
Expand Down Expand Up @@ -1295,7 +1295,9 @@ async function driver(h, observe) {
streamed: printer
? [...report.gapsOf(results)].reverse().map((r) => printer.gapLine(r))
: undefined,
killsSection: summary.slice(summary.indexOf(`## Kills by law`)),
killsSection: summary.slice(
summary.indexOf(`## First law to reject, by law`),
),
// What results.json keeps of each mutant's change, after the printing.
kept: results.map((r) =>
r.authored ? r.intent : [String(r.original), String(r.replacement)],
Expand Down
9 changes: 6 additions & 3 deletions packages/oracles/oracle-gaps/report.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ const placeholders = {
const legendOf = (kind) => directive[kind]({ ...placeholders, outcome: kind })

// What the author does about a law that rejects no mutant: one next step.
const killsDirective = `To find a law that rejects no mutant, add a history that varies the input the law judges, and run the check again.`
// The table credits each history's first rejecting law only: a check returns
// its first violation, so a later law on the same history is never judged.
// The count says which law rejected first, not which laws can reject.
const killsDirective = `Each count credits only the first law that rejected a history: a later law on the same history is not checked. To test a law with no count, add a history that varies the input the law judges, and run the check again.`

export function gapsOf(results) {
return results.filter(
Expand Down Expand Up @@ -290,11 +293,11 @@ export function renderReport({ results, run, excluded }) {
for (const law of result.laws ?? [])
byLaw.set(law, (byLaw.get(law) ?? 0) + 1)
lines.push(
`## Kills by law`,
`## First law to reject, by law`,
``,
killsDirective,
``,
`| Law | Mutants it rejected |`,
`| Law | Mutants it rejected first |`,
`|---|---|`,
...[...byLaw]
.sort((a, b) => b[1] - a[1])
Expand Down
Loading