@fairfox/polly 0.91.0 → 0.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/cli/polly.js +3 -3
  2. package/dist/cli/polly.js.map +3 -3
  3. package/dist/gallery/gallery.css +2 -2
  4. package/dist/gallery/gallery.js +248 -241
  5. package/dist/src/background/index.js +27 -11
  6. package/dist/src/background/index.js.map +2 -2
  7. package/dist/src/background/message-router.js +27 -11
  8. package/dist/src/background/message-router.js.map +2 -2
  9. package/dist/src/client/index.js +56 -56
  10. package/dist/src/client/index.js.map +4 -4
  11. package/dist/src/elysia/index.js +6 -6
  12. package/dist/src/elysia/index.js.map +3 -3
  13. package/dist/src/index.js +27 -11
  14. package/dist/src/index.js.map +2 -2
  15. package/dist/src/mesh.js +2 -2
  16. package/dist/src/mesh.js.map +3 -3
  17. package/dist/src/peer.js +6 -6
  18. package/dist/src/peer.js.map +3 -3
  19. package/dist/src/polly-ui/index.css +2 -2
  20. package/dist/src/polly-ui/markdown.js +1844 -1010
  21. package/dist/src/polly-ui/markdown.js.map +5 -5
  22. package/dist/src/polly-ui/styles.css +2 -2
  23. package/dist/src/shared/adapters/index.js +27 -11
  24. package/dist/src/shared/adapters/index.js.map +2 -2
  25. package/dist/src/shared/lib/context-helpers.js +27 -11
  26. package/dist/src/shared/lib/context-helpers.js.map +2 -2
  27. package/dist/src/shared/lib/message-bus.js +27 -11
  28. package/dist/src/shared/lib/message-bus.js.map +2 -2
  29. package/dist/src/shared/lib/resource.js +17 -1
  30. package/dist/src/shared/lib/resource.js.map +2 -2
  31. package/dist/src/shared/lib/state.js +17 -1
  32. package/dist/src/shared/lib/state.js.map +2 -2
  33. package/dist/src/shared/state/app-state.js +17 -1
  34. package/dist/src/shared/state/app-state.js.map +2 -2
  35. package/dist/tools/bdd/src/cli.js +20 -2
  36. package/dist/tools/bdd/src/cli.js.map +4 -4
  37. package/dist/tools/bdd/src/index.js +20 -2
  38. package/dist/tools/bdd/src/index.js.map +3 -3
  39. package/dist/tools/init/templates/pwa/package.json.template +2 -3
  40. package/dist/tools/mutate/src/args.d.ts +25 -3
  41. package/dist/tools/mutate/src/cli.js +3234 -312
  42. package/dist/tools/mutate/src/cli.js.map +32 -12
  43. package/dist/tools/mutate/src/config.d.ts +13 -2
  44. package/dist/tools/mutate/src/define.d.ts +76 -0
  45. package/dist/tools/mutate/src/engine/ast.d.ts +13 -0
  46. package/dist/tools/mutate/src/engine/baseline.d.ts +20 -0
  47. package/dist/tools/mutate/src/engine/cache.d.ts +32 -0
  48. package/dist/tools/mutate/src/engine/coverage.d.ts +60 -0
  49. package/dist/tools/mutate/src/engine/generate.d.ts +23 -0
  50. package/dist/tools/mutate/src/engine/graph.d.ts +11 -0
  51. package/dist/tools/mutate/src/engine/index.d.ts +16 -0
  52. package/dist/tools/mutate/src/engine/junit.d.ts +38 -0
  53. package/dist/tools/mutate/src/engine/operators.d.ts +14 -0
  54. package/dist/tools/mutate/src/engine/preload.d.ts +10 -0
  55. package/dist/tools/mutate/src/engine/preload.js +180 -0
  56. package/dist/tools/mutate/src/engine/preload.js.map +10 -0
  57. package/dist/tools/mutate/src/engine/probes.d.ts +12 -0
  58. package/dist/tools/mutate/src/engine/report-writer.d.ts +44 -0
  59. package/dist/tools/mutate/src/engine/runner.d.ts +31 -0
  60. package/dist/tools/mutate/src/engine/stray-writes.d.ts +25 -0
  61. package/dist/tools/mutate/src/engine/typecheck.d.ts +37 -0
  62. package/dist/tools/mutate/src/engine/types.d.ts +191 -0
  63. package/dist/tools/mutate/src/engine/verify-callsites.d.ts +9 -0
  64. package/dist/tools/mutate/src/engine/workdir.d.ts +16 -0
  65. package/dist/tools/mutate/src/engine-config.d.ts +7 -0
  66. package/dist/tools/mutate/src/index.d.ts +7 -3
  67. package/dist/tools/mutate/src/index.js +2701 -77
  68. package/dist/tools/mutate/src/index.js.map +26 -7
  69. package/dist/tools/mutate/src/ingest.d.ts +30 -1
  70. package/dist/tools/mutate/src/init.d.ts +2 -1
  71. package/dist/tools/mutate/src/migrate.d.ts +32 -0
  72. package/dist/tools/mutate/src/report.d.ts +3 -0
  73. package/dist/tools/mutate/src/run.d.ts +17 -8
  74. package/dist/tools/mutate/src/verify-matrix.d.ts +12 -15
  75. package/dist/tools/quality/src/cli.js +9 -9
  76. package/dist/tools/quality/src/cli.js.map +4 -4
  77. package/dist/tools/quality/src/index.js +9 -9
  78. package/dist/tools/quality/src/index.js.map +4 -4
  79. package/dist/tools/quality/src/no-tautology-ensures.d.ts +2 -2
  80. package/dist/tools/quality/src/plugins/import-checks.d.ts +1 -1
  81. package/dist/tools/test/src/adapters/index.js +3 -2
  82. package/dist/tools/test/src/adapters/index.js.map +3 -3
  83. package/dist/tools/test/src/coverage-policy/cli.d.ts +2 -2
  84. package/dist/tools/test/src/coverage-policy/cli.js +217 -17
  85. package/dist/tools/test/src/coverage-policy/cli.js.map +7 -5
  86. package/dist/tools/test/src/coverage-policy/index.d.ts +1 -1
  87. package/dist/tools/test/src/coverage-policy/index.js +213 -12
  88. package/dist/tools/test/src/coverage-policy/index.js.map +7 -5
  89. package/dist/tools/test/src/coverage-policy/mutate-targets.d.ts +29 -12
  90. package/dist/tools/test/src/e2e-mesh/index.js +6 -6
  91. package/dist/tools/test/src/e2e-mesh/index.js.map +4 -4
  92. package/dist/tools/test/src/e2e-relay/index.js +230 -226
  93. package/dist/tools/test/src/e2e-relay/index.js.map +7 -7
  94. package/dist/tools/test/src/index.js +3 -2
  95. package/dist/tools/test/src/index.js.map +3 -3
  96. package/dist/tools/test/src/visual/index.js +684 -511
  97. package/dist/tools/test/src/visual/index.js.map +11 -11
  98. package/dist/tools/verify/src/cli.js +2 -2
  99. package/dist/tools/verify/src/cli.js.map +3 -3
  100. package/dist/tools/verify/src/config.d.ts +1 -1
  101. package/dist/tools/verify/src/config.js +68 -3
  102. package/dist/tools/verify/src/config.js.map +4 -4
  103. package/dist/tools/verify/src/primitives/index.d.ts +34 -0
  104. package/package.json +29 -39
  105. package/dist/tools/verify/src/stryker/index.d.ts +0 -32
  106. package/dist/tools/verify/src/stryker/index.js +0 -86
  107. package/dist/tools/verify/src/stryker/index.js.map +0 -10
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Stray-write detection. Mutant runs share the project's working tree (no
3
+ * sandbox copy), so a mutant that redirects a write — a storage path, a temp
4
+ * dir — leaves a file in the repo. Polly's own storage-adapter.ts did exactly
5
+ * this (`st/orage-adapter-id` in the repo root after every full run).
6
+ *
7
+ * The engine snapshots `git status` before the run, after the baselines and
8
+ * after the mutants, and reports each new entry. It never deletes: a path that
9
+ * is new to git may still be the user's own work in progress.
10
+ *
11
+ * Untracked files are listed one by one (`--untracked-files=all`), so a new
12
+ * file inside an already-untracked directory still shows. Ignored paths are
13
+ * listed as their matching pattern (`--ignored=matching`): a write to a new
14
+ * `*.log` shows, a write inside an existing `node_modules/` does not.
15
+ */
16
+ export interface WorktreeSnapshot {
17
+ /** Absolute repo root; entry paths are relative to it. */
18
+ root: string;
19
+ /** `XY path` lines, so a clean → modified change counts as new. */
20
+ entries: Set<string>;
21
+ }
22
+ /** Null when `cwd` is not inside a git worktree (or git is not installed). */
23
+ export declare function snapshotWorktree(cwd: string): WorktreeSnapshot | null;
24
+ /** Paths (relative to the repo root) whose `git status` entry is in `after` but not `before`. */
25
+ export declare function newPaths(before: WorktreeSnapshot | null, after: WorktreeSnapshot | null): string[];
@@ -0,0 +1,37 @@
1
+ import type { Mutant } from "./types.ts";
2
+ /** Relaxed in the virtual config: mutants make code unreachable and bindings unused by design. */
3
+ export declare const TYPECHECK_OVERRIDES: {
4
+ allowUnreachableCode: boolean;
5
+ noUnusedLocals: boolean;
6
+ noUnusedParameters: boolean;
7
+ };
8
+ export declare const TYPECHECK_CONFIG_NAME = "tsconfig.polly-mutate.json";
9
+ export interface TypecheckTarget {
10
+ /** Absolute, symlink-resolved. */
11
+ file: string;
12
+ mutants: readonly Mutant[];
13
+ }
14
+ export interface TypecheckOutcome {
15
+ /** Mutant id → `TS<code>: <text>` of the first error the unmutated file does not have. */
16
+ invalid: Map<string, string>;
17
+ /** Targets the filter could not check, each with why. Their mutants run as usual. */
18
+ skipped: {
19
+ file: string;
20
+ reason: string;
21
+ }[];
22
+ /** Mutants that were checked (skipped targets excluded). */
23
+ checked: number;
24
+ wallMs: number;
25
+ }
26
+ export interface TypecheckOptions {
27
+ /** For log lines: paths print relative to it. */
28
+ cwd: string;
29
+ log?: (line: string) => void;
30
+ }
31
+ /** `tsconfig.json` paths from the file's directory upward, nearest first. */
32
+ export declare function tsconfigCandidates(file: string): string[];
33
+ /**
34
+ * Type-check every mutant of every target. Null when `typescript-7` is not
35
+ * installed (logged; the engine then runs every mutant).
36
+ */
37
+ export declare function typecheckMutants(targets: readonly TypecheckTarget[], opts: TypecheckOptions): Promise<TypecheckOutcome | null>;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Shared types for the Bun-native mutation engine (`polly mutate --engine bun`).
3
+ *
4
+ * Mutator names are Stryker's, on purpose: the report keeps the
5
+ * mutation-testing-report-schema shape, so ingest/report/decisions and any
6
+ * existing decisions.jsonl read the engine's output exactly as they read
7
+ * Stryker's.
8
+ */
9
+ export type MutatorName = "ArithmeticOperator" | "ArrayDeclaration" | "ArrowFunction" | "AssignmentOperator" | "BlockStatement" | "BooleanLiteral" | "ConditionalExpression" | "EqualityOperator" | "LogicalOperator" | "MethodExpression" | "ObjectLiteral" | "OptionalChaining" | "Regex" | "StringLiteral" | "UnaryOperator" | "UpdateOperator";
10
+ /** One source edit: replace `[start, end)` of the target file's text with `replacement`. */
11
+ export interface Mutant {
12
+ id: string;
13
+ /** Absolute, symlink-resolved path of the mutated file. */
14
+ file: string;
15
+ mutatorName: MutatorName;
16
+ start: number;
17
+ end: number;
18
+ replacement: string;
19
+ /** 1-based, as mutation-testing-report-schema expects. */
20
+ location: {
21
+ start: Position;
22
+ end: Position;
23
+ };
24
+ /** Set when the mutant sits inside a polly verify primitive (polly#143). */
25
+ ignoredReason?: string;
26
+ }
27
+ export interface Position {
28
+ line: number;
29
+ column: number;
30
+ }
31
+ export type MutantStatus = "Killed" | "Survived" | "Timeout" | "NoCoverage" | "CompileError" | "RuntimeError" | "Ignored";
32
+ export interface MutantResult {
33
+ mutant: Mutant;
34
+ status: MutantStatus;
35
+ statusReason?: string;
36
+ durationMs?: number;
37
+ /** Matrix mode: ids (see junit.ts `testId`) of every test that failed under the mutant. */
38
+ killedBy?: string[];
39
+ /** Dynamic coverage: ids of every test that ran the mutant's code (coverage.ts). */
40
+ coveredBy?: string[];
41
+ /**
42
+ * Matrix mode with contracts on: ids (`<file relative to cwd>:<line>`) of
43
+ * every requires/ensures whose violation a killing test reported.
44
+ */
45
+ killedByContract?: string[];
46
+ /** Every killing test failed through a contract violation: no assertion caught it. */
47
+ contractOnly?: boolean;
48
+ }
49
+ /**
50
+ * POLLY_CONTRACTS for every test process the engine starts: off keeps
51
+ * requires/ensures as no-ops; ensures makes a false postcondition throw;
52
+ * all makes a false precondition throw too.
53
+ */
54
+ export type ContractsMode = "off" | "ensures" | "all";
55
+ /** A `requires` / `ensures` call in a target (generate.ts). */
56
+ export interface ContractSite {
57
+ /** Absolute, symlink-resolved path, as `Mutant.file`. */
58
+ file: string;
59
+ /** 1-based line of the call. */
60
+ line: number;
61
+ primitive: "requires" | "ensures";
62
+ /** The author's message, when it is a string literal. */
63
+ message?: string;
64
+ /** Lines of the enclosing `bus.on(...)` call, else the enclosing function. */
65
+ handler?: {
66
+ from: number;
67
+ to: number;
68
+ };
69
+ }
70
+ /** A baseline test (or the command) that fails only because a contract is false. */
71
+ export interface ContractViolationRecord {
72
+ /** Absolute path of the target whose baseline reported it. */
73
+ target: string;
74
+ /** Test id (junit.ts `testId`), or "(command)" for the command runner. */
75
+ test: string;
76
+ /** Contract ids, `<file relative to cwd>:<line>`; empty for the command runner. */
77
+ contracts: string[];
78
+ }
79
+ /** One test the baseline ran (matrix mode). */
80
+ export interface TestRef {
81
+ id: string;
82
+ /** Absolute path of the test file. */
83
+ file: string;
84
+ name: string;
85
+ line: number;
86
+ }
87
+ /**
88
+ * fast `--bail`: stop at the first failing test; status only.
89
+ * matrix no bail, junit per run: every killing test, for the redundancy analysis.
90
+ */
91
+ export type EngineMode = "fast" | "matrix";
92
+ /** A target file, optionally narrowed to a line range (Stryker's `file.ts:10-20`). */
93
+ export interface MutateTarget {
94
+ file: string;
95
+ lines?: {
96
+ from: number;
97
+ to: number;
98
+ };
99
+ }
100
+ export type EngineRunner = {
101
+ kind: "bun-test";
102
+ } | {
103
+ kind: "command";
104
+ argv: string[];
105
+ };
106
+ /**
107
+ * dynamic one probed pass over every test file decides, per mutant, which
108
+ * tests run it (coverage.ts); a mutant no test runs is NoCoverage
109
+ * static every test file whose import closure reaches the target (graph.ts)
110
+ */
111
+ export type CoverageMode = "dynamic" | "static";
112
+ export interface EngineConfig {
113
+ /** Directory `bun test` runs from; test globs and report paths are relative to it. */
114
+ cwd: string;
115
+ targets: MutateTarget[];
116
+ /**
117
+ * bun-test `bun test` on the test files that reach each target.
118
+ * command the argv, whole, for every mutant (polly.mutate.ts `runner`).
119
+ */
120
+ runner: EngineRunner;
121
+ /** Test-file globs (relative to cwd) the import graph starts from. */
122
+ testInclude: string[];
123
+ /**
124
+ * The project's own test preloads (absolute), passed before the mutant
125
+ * preload. Needed because a subset of test files can depend on a preload
126
+ * the full suite happens to load some other way (polly's CSS-module shim).
127
+ */
128
+ testPreload: string[];
129
+ mode: EngineMode;
130
+ /**
131
+ * Report mutants the project's TypeScript config rejects as CompileError
132
+ * without running them (typecheck.ts). Needs `typescript-7`.
133
+ */
134
+ typecheck: boolean;
135
+ /** Test selection. The command runner selects nothing, so it is always static. */
136
+ coverage: CoverageMode;
137
+ concurrency: number;
138
+ timeout: {
139
+ factor: number;
140
+ extraMs: number;
141
+ };
142
+ /** Mutators that generate nothing. */
143
+ excludeMutators: MutatorName[];
144
+ /** Mark mutants inside requires/ensures/… as Ignored instead of running them. */
145
+ ignoreVerifyCallsites: boolean;
146
+ /** POLLY_CONTRACTS for every test process (baseline, coverage pass, mutant runs). */
147
+ contracts: ContractsMode;
148
+ /**
149
+ * Run each test process in a fresh scratch cwd (workdir.ts), so a mutant's
150
+ * relative writes miss the repo. False runs everything in `cwd`.
151
+ */
152
+ scratchCwd: boolean;
153
+ /** Result cache directory (cache.ts); null runs everything. */
154
+ cacheDir: string | null;
155
+ reportPath: string;
156
+ }
157
+ export interface TargetSummary {
158
+ file: string;
159
+ coveringTests: string[];
160
+ baselineMs: number | null;
161
+ /** Its mutants ran in the project cwd (scratch off, or its tests need the cwd). */
162
+ inTree: boolean;
163
+ /** Results came from the cache; nothing ran. */
164
+ cached: boolean;
165
+ /** Matrix mode: every test the baseline ran, plus any load-failure stand-in a mutant named. */
166
+ tests: TestRef[];
167
+ results: MutantResult[];
168
+ /** Every requires/ensures call in the target, whatever the contracts mode. */
169
+ contracts: ContractSite[];
170
+ }
171
+ export interface EngineResult {
172
+ targets: TargetSummary[];
173
+ wallMs: number;
174
+ /**
175
+ * Paths new to `git status` (relative to `root`), split by phase: written by
176
+ * the unmutated baselines (the tests' own side effects) or by mutant runs
177
+ * (a mutant redirected a write into the tree). Null outside a git worktree.
178
+ * The report is written after the last snapshot, so it never appears here.
179
+ */
180
+ strayWrites: {
181
+ root: string;
182
+ baseline: string[];
183
+ mutants: string[];
184
+ } | null;
185
+ /**
186
+ * Baselines that failed through a contract: a test drives a handler outside
187
+ * its declared precondition, or a handler breaks its own postcondition.
188
+ * Those targets' mutants are RuntimeError; `run` exits 1 and names them.
189
+ */
190
+ contractViolations: ContractViolationRecord[];
191
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The polly verify primitives whose argument expressions are runtime no-ops.
3
+ * A mutation anywhere inside a call to one of these cannot be killed by a test,
4
+ * so its mutants are excluded from scoring (polly#143).
5
+ *
6
+ * The single source: generate.ts marks mutants inside these calls Ignored.
7
+ */
8
+ export declare const VERIFY_PRIMITIVES: ReadonlySet<string>;
9
+ export declare function verifyCallsiteReason(name: string): string;
@@ -0,0 +1,16 @@
1
+ export interface Workdirs {
2
+ root: string;
3
+ /** A fresh cwd holding the project's tsconfig and bunfig. */
4
+ create(): string;
5
+ /** Remove one directory from `create()`. */
6
+ release(dir: string): void;
7
+ /** Remove every scratch directory. */
8
+ remove(): void;
9
+ }
10
+ /** Resolve top-level `preload` and `[test].preload` (a string or a list) against the project. */
11
+ export declare function absolutiseBunfig(config: Record<string, unknown>, projectCwd: string): Record<string, unknown>;
12
+ /** TOML for the plain shapes a bunfig holds: scalars, arrays and nested tables. */
13
+ export declare function renderToml(config: Record<string, unknown>, prefix?: string[]): string;
14
+ export declare function createWorkdirs(projectCwd: string): Workdirs;
15
+ /** Run `fn` in a fresh scratch cwd, or in `projectCwd` when `workdirs` is null. */
16
+ export declare function inCwd<R>(workdirs: Workdirs | null, projectCwd: string, fn: (cwd: string) => Promise<R>): Promise<R>;
@@ -0,0 +1,7 @@
1
+ import type { MutateArgs } from "./args.ts";
2
+ import type { MutateConfig } from "./config.ts";
3
+ import type { EngineConfig, MutateTarget } from "./engine/types.ts";
4
+ /** Expand Stryker `mutate` entries: globs, `!` exclusions, and `file.ts:10-20` ranges. */
5
+ export declare function expandMutateEntries(cwd: string, entries: string[]): Promise<MutateTarget[]>;
6
+ /** The engine's config from the loaded mutation config plus CLI flags (flags win). */
7
+ export declare function engineConfigFor(cfg: MutateConfig, args: MutateArgs): Promise<EngineConfig>;
@@ -1,13 +1,17 @@
1
1
  /**
2
2
  * @fairfox/polly/mutate — programmatic surface for mutation-testing analysis.
3
3
  *
4
- * The CLI (`polly mutate`) is the primary entry point; this barrel exposes the
5
- * reusable pieces for consumers who want to drive the analysis themselves:
4
+ * The CLI (`polly mutate`) is the primary entry point; `defineMutation` types a
5
+ * project's `polly.mutate.ts`. The rest is for consumers who want to drive the
6
+ * engine or the analysis themselves:
6
7
  * ingest a mutation report into the kill matrix, derive the useless-test signals,
7
8
  * and assert the matrix contract.
8
9
  */
9
10
  export { decide, type FileSignal, fileSignals, status } from "./decisions.ts";
10
- export { buildDb, type MutationReport } from "./ingest.ts";
11
+ export { type CommandRunner, defineMutation, loadMutationConfig, MUTATION_CONFIG_FILE, type MutationConfig, type MutationTests, parseMutationConfig, } from "./define.ts";
12
+ export { applyMutant, buildImportGraph, type ContractSite, type ContractsMode, type ContractViolationRecord, coveringTests, type EngineConfig, type EngineHooks, type EngineResult, findTestFiles, generateMutants, type Mutant, type MutantResult, type MutantStatus, type MutateTarget, type MutatorName, mutationScore, runEngine, VERIFY_PRIMITIVES, } from "./engine/index.ts";
13
+ export { buildDb, type MutationReport, type ReportContracts } from "./ingest.ts";
11
14
  export { type InitResult, initConfig } from "./init.ts";
15
+ export { type Migration, migrateConfig, strykerToMutation } from "./migrate.ts";
12
16
  export { report } from "./report.ts";
13
17
  export { isMatrixComplete, type MatrixCheck, verifyMatrix } from "./verify-matrix.ts";