Score: 63.9% (β -1.5 vs prior)
Per-shard breakdown
| Shard |
Score |
Killed |
Survived |
No cov |
Timeout |
Errors |
Total |
| db |
10.5% |
55 |
412 |
52 |
4 |
412 |
935 |
| hardware-lib |
67.6% |
1518 |
538 |
181 |
7 |
893 |
3161 |
| homekit |
62.1% |
282 |
163 |
9 |
0 |
201 |
681 |
| hooks |
73.5% |
866 |
289 |
23 |
1 |
497 |
1702 |
| server |
59.1% |
1393 |
596 |
368 |
2 |
1679 |
5082 |
| services-scheduler |
73.0% |
548 |
184 |
16 |
3 |
251 |
1004 |
| streaming |
75.5% |
870 |
210 |
61 |
12 |
392 |
1559 |
- HTML reports: attached as
mutation-report-<shard> artifacts on run 28284145339.
- Hit list artifact:
mutation-hitlist on the same run.
- Last updated: 2026-06-27T09:55:43.143Z (commit
9a2418b, trigger: schedule).
This issue is updated automatically by .github/workflows/mutation.yml on each scheduled / manual mutation run. Do not edit the body β it will be overwritten. Comment freely to track work on surviving mutants.
Mutation testing β hit list
Score: 63.9% Β· Total mutants: 14124
| Status |
Count |
| Killed |
5532 |
| Survived |
2392 |
| NoCoverage |
710 |
| Timeout |
29 |
| CompileError |
4324 |
| RuntimeError |
1 |
| Ignored |
1136 |
Surviving mutants by file (82 files, top 50 mutants shown)
For each entry below: the mutator type tells you what Stryker changed, the snippet shows where, and "expected test" is the most likely location to add a killing assertion. A killing test must fail when the mutation is applied.
src/db/schema.ts β 194 surviving
Expected test file: src/db/tests/schema.test.ts
StringLiteral at line 8
7 |
> 8 | export const deviceSettings = sqliteTable('device_settings', {
9 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton
+ (mutation): ""
StringLiteral at line 9
8 | export const deviceSettings = sqliteTable('device_settings', {
> 9 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton
10 | timezone: text('timezone').notNull().default('America/Los_Angeles'),
+ (mutation): ""
StringLiteral at line 10
9 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton
> 10 | timezone: text('timezone').notNull().default('America/Los_Angeles'),
11 | temperatureUnit: text('temperature_unit', { enum: ['F', 'C'] })
+ (mutation): ""
StringLiteral at line 10
9 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton
> 10 | timezone: text('timezone').notNull().default('America/Los_Angeles'),
11 | temperatureUnit: text('temperature_unit', { enum: ['F', 'C'] })
+ (mutation): ""
StringLiteral at line 11
10 | timezone: text('timezone').notNull().default('America/Los_Angeles'),
> 11 | temperatureUnit: text('temperature_unit', { enum: ['F', 'C'] })
12 | .notNull()
+ (mutation): ""
StringLiteral at line 14
13 | .default('F'),
> 14 | rebootDaily: integer('reboot_daily', { mode: 'boolean' })
15 | .notNull()
+ (mutation): ""
BooleanLiteral at line 16
15 | .notNull()
> 16 | .default(false),
17 | rebootTime: text('reboot_time').default('03:00'), // HH:mm format
+ (mutation): true
StringLiteral at line 17
16 | .default(false),
> 17 | rebootTime: text('reboot_time').default('03:00'), // HH:mm format
18 | primePodDaily: integer('prime_pod_daily', { mode: 'boolean' })
+ (mutation): ""
StringLiteral at line 17
16 | .default(false),
> 17 | rebootTime: text('reboot_time').default('03:00'), // HH:mm format
18 | primePodDaily: integer('prime_pod_daily', { mode: 'boolean' })
+ (mutation): ""
StringLiteral at line 18
17 | rebootTime: text('reboot_time').default('03:00'), // HH:mm format
> 18 | primePodDaily: integer('prime_pod_daily', { mode: 'boolean' })
19 | .notNull()
+ (mutation): ""
BooleanLiteral at line 20
19 | .notNull()
> 20 | .default(false),
21 | primePodTime: text('prime_pod_time').default('14:00'), // HH:mm format
+ (mutation): true
StringLiteral at line 21
20 | .default(false),
> 21 | primePodTime: text('prime_pod_time').default('14:00'), // HH:mm format
22 | ledNightModeEnabled: integer('led_night_mode_enabled', { mode: 'boolean' })
+ (mutation): ""
StringLiteral at line 21
20 | .default(false),
> 21 | primePodTime: text('prime_pod_time').default('14:00'), // HH:mm format
22 | ledNightModeEnabled: integer('led_night_mode_enabled', { mode: 'boolean' })
+ (mutation): ""
StringLiteral at line 22
21 | primePodTime: text('prime_pod_time').default('14:00'), // HH:mm format
> 22 | ledNightModeEnabled: integer('led_night_mode_enabled', { mode: 'boolean' })
23 | .notNull()
+ (mutation): ""
BooleanLiteral at line 24
23 | .notNull()
> 24 | .default(false),
25 | ledDayBrightness: integer('led_day_brightness').notNull().default(100), // 0-100
+ (mutation): true
StringLiteral at line 26
25 | ledDayBrightness: integer('led_day_brightness').notNull().default(100), // 0-100
> 26 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100
27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format
+ (mutation): ""
StringLiteral at line 25
24 | .default(false),
> 25 | ledDayBrightness: integer('led_day_brightness').notNull().default(100), // 0-100
26 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100
+ (mutation): ""
StringLiteral at line 27
26 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100
> 27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format
28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format
+ (mutation): ""
StringLiteral at line 27
26 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100
> 27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format
28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format
+ (mutation): ""
StringLiteral at line 28
27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format
> 28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format
29 | // Global wall-clock safety cap: if a side has been powered for this many
+ (mutation): ""
StringLiteral at line 28
27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format
> 28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format
29 | // Global wall-clock safety cap: if a side has been powered for this many
+ (mutation): ""
StringLiteral at line 37
36 | // middleware to gate a hashed-credential round-trip yet.
> 37 | mqttEnabled: integer('mqtt_enabled', { mode: 'boolean' }),
38 | mqttUrl: text('mqtt_url'),
+ (mutation): ""
StringLiteral at line 32
31 | // off. NULL = disabled. Independent of per-side bed-exit auto-off.
> 32 | globalMaxOnHours: integer('global_max_on_hours'),
33 | // MQTT bridge configuration. NULL on every field falls back to the
+ (mutation): ""
StringLiteral at line 38
37 | mqttEnabled: integer('mqtt_enabled', { mode: 'boolean' }),
> 38 | mqttUrl: text('mqtt_url'),
39 | mqttUsername: text('mqtt_username'),
+ (mutation): ""
StringLiteral at line 39
38 | mqttUrl: text('mqtt_url'),
> 39 | mqttUsername: text('mqtt_username'),
40 | mqttPassword: text('mqtt_password'),
+ (mutation): ""
StringLiteral at line 40
39 | mqttUsername: text('mqtt_username'),
> 40 | mqttPassword: text('mqtt_password'),
41 | mqttTopicPrefix: text('mqtt_topic_prefix'),
+ (mutation): ""
StringLiteral at line 41
40 | mqttPassword: text('mqtt_password'),
> 41 | mqttTopicPrefix: text('mqtt_topic_prefix'),
42 | mqttHaDiscovery: integer('mqtt_ha_discovery', { mode: 'boolean' }),
+ (mutation): ""
StringLiteral at line 42
41 | mqttTopicPrefix: text('mqtt_topic_prefix'),
> 42 | mqttHaDiscovery: integer('mqtt_ha_discovery', { mode: 'boolean' }),
43 | mqttTlsEnabled: integer('mqtt_tls_enabled', { mode: 'boolean' }),
+ (mutation): ""
StringLiteral at line 43
42 | mqttHaDiscovery: integer('mqtt_ha_discovery', { mode: 'boolean' }),
> 43 | mqttTlsEnabled: integer('mqtt_tls_enabled', { mode: 'boolean' }),
44 | // When true, accept self-signed broker certs (sets rejectUnauthorized:false).
+ (mutation): ""
StringLiteral at line 47
46 | // per ADR 0019 β tlsEnabled alone keeps strict cert verification.
> 47 | mqttTlsInsecure: integer('mqtt_tls_insecure', { mode: 'boolean' }),
48 | // HomeKit bridge is opt-in. When true, instrumentation publishes the
+ (mutation): ""
StringLiteral at line 50
49 | // hap-nodejs bridge with HeaterCooler/OccupancySensor/Switch accessories.
> 50 | homekitEnabled: integer('homekit_enabled', { mode: 'boolean' })
51 | .notNull()
+ (mutation): ""
BooleanLiteral at line 52
51 | .notNull()
> 52 | .default(false),
53 | // Pump-stall safety guard (ADR 0022): a side whose pump RPM stays under the
+ (mutation): true
StringLiteral at line 58
57 | // on missing data. Auto-recovery is separately opt-in.
> 58 | pumpStallProtectionEnabled: integer('pump_stall_protection_enabled', { mode: 'boolean' })
59 | .notNull()
+ (mutation): ""
BooleanLiteral at line 60
59 | .notNull()
> 60 | .default(false),
61 | pumpStallRpmThreshold: integer('pump_stall_rpm_threshold').notNull().default(500),
+ (mutation): true
StringLiteral at line 62
61 | pumpStallRpmThreshold: integer('pump_stall_rpm_threshold').notNull().default(500),
> 62 | pumpStallDwellSamples: integer('pump_stall_dwell_samples').notNull().default(2),
63 | pumpStallAutoRecoveryEnabled: integer('pump_stall_auto_recovery_enabled', { mode: 'boolean' })
+ (mutation): ""
StringLiteral at line 61
60 | .default(false),
> 61 | pumpStallRpmThreshold: integer('pump_stall_rpm_threshold').notNull().default(500),
62 | pumpStallDwellSamples: integer('pump_stall_dwell_samples').notNull().default(2),
+ (mutation): ""
StringLiteral at line 63
62 | pumpStallDwellSamples: integer('pump_stall_dwell_samples').notNull().default(2),
> 63 | pumpStallAutoRecoveryEnabled: integer('pump_stall_auto_recovery_enabled', { mode: 'boolean' })
64 | .notNull()
+ (mutation): ""
BooleanLiteral at line 65
64 | .notNull()
> 65 | .default(false),
66 | pumpStallRecoveryRpm: integer('pump_stall_recovery_rpm').notNull().default(1500),
+ (mutation): true
StringLiteral at line 66
65 | .default(false),
> 66 | pumpStallRecoveryRpm: integer('pump_stall_recovery_rpm').notNull().default(1500),
67 | pumpStallRecoverySamples: integer('pump_stall_recovery_samples').notNull().default(3),
+ (mutation): ""
StringLiteral at line 67
66 | pumpStallRecoveryRpm: integer('pump_stall_recovery_rpm').notNull().default(1500),
> 67 | pumpStallRecoverySamples: integer('pump_stall_recovery_samples').notNull().default(3),
68 | // Autopilot global kill-switch. When false, the AutomationEngine evaluates
+ (mutation): ""
StringLiteral at line 72
71 | // so the kill-switch survives reboot.
> 72 | autopilotEnabled: integer('autopilot_enabled', { mode: 'boolean' })
73 | .notNull()
+ (mutation): ""
BooleanLiteral at line 74
73 | .notNull()
> 74 | .default(true),
75 | createdAt: integer('created_at', { mode: 'timestamp' })
+ (mutation): false
StringLiteral at line 75
74 | .default(true),
> 75 | createdAt: integer('created_at', { mode: 'timestamp' })
76 | .notNull()
+ (mutation): ""
StringLiteral at line 78
77 | .default(sql`(unixepoch())`),
> 78 | updatedAt: integer('updated_at', { mode: 'timestamp' })
79 | .notNull()
+ (mutation): ""
StringLiteral at line 77
76 | .notNull()
> 77 | .default(sql`(unixepoch())`),
78 | updatedAt: integer('updated_at', { mode: 'timestamp' })
+ (mutation): ``
StringLiteral at line 80
79 | .notNull()
> 80 | .default(sql`(unixepoch())`),
81 | })
+ (mutation): ``
StringLiteral at line 83
82 |
> 83 | export const sideSettings = sqliteTable('side_settings', {
84 | side: text('side', { enum: ['left', 'right'] }).primaryKey(),
+ (mutation): ""
StringLiteral at line 84
83 | export const sideSettings = sqliteTable('side_settings', {
> 84 | side: text('side', { enum: ['left', 'right'] }).primaryKey(),
85 | name: text('name').notNull(), // Must be provided explicitly during insert
+ (mutation): ""
StringLiteral at line 85
84 | side: text('side', { enum: ['left', 'right'] }).primaryKey(),
> 85 | name: text('name').notNull(), // Must be provided explicitly during insert
86 | awayMode: integer('away_mode', { mode: 'boolean' }).notNull().default(false),
+ (mutation): ""
StringLiteral at line 86
85 | name: text('name').notNull(), // Must be provided explicitly during insert
> 86 | awayMode: integer('away_mode', { mode: 'boolean' }).notNull().default(false),
87 | alwaysOn: integer('always_on', { mode: 'boolean' }).notNull().default(false),
+ (mutation): ""
β¦and 2342 more surviving mutants not shown. See the HTML report for the full list.
Score: 63.9% (β -1.5 vs prior)
Per-shard breakdown
mutation-report-<shard>artifacts on run 28284145339.mutation-hitliston the same run.9a2418b, trigger:schedule).Mutation testing β hit list
Score: 63.9% Β· Total mutants: 14124
Surviving mutants by file (82 files, top 50 mutants shown)
For each entry below: the mutator type tells you what Stryker changed, the snippet shows where, and "expected test" is the most likely location to add a killing assertion. A killing test must fail when the mutation is applied.
src/db/schema.tsβ 194 survivingExpected test file:
src/db/tests/schema.test.tsStringLiteralat line 8StringLiteralat line 98 | export const deviceSettings = sqliteTable('device_settings', { > 9 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton 10 | timezone: text('timezone').notNull().default('America/Los_Angeles'), + (mutation): ""StringLiteralat line 109 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton > 10 | timezone: text('timezone').notNull().default('America/Los_Angeles'), 11 | temperatureUnit: text('temperature_unit', { enum: ['F', 'C'] }) + (mutation): ""StringLiteralat line 109 | id: integer('id').primaryKey().$defaultFn(() => 1), // Singleton > 10 | timezone: text('timezone').notNull().default('America/Los_Angeles'), 11 | temperatureUnit: text('temperature_unit', { enum: ['F', 'C'] }) + (mutation): ""StringLiteralat line 1110 | timezone: text('timezone').notNull().default('America/Los_Angeles'), > 11 | temperatureUnit: text('temperature_unit', { enum: ['F', 'C'] }) 12 | .notNull() + (mutation): ""StringLiteralat line 1413 | .default('F'), > 14 | rebootDaily: integer('reboot_daily', { mode: 'boolean' }) 15 | .notNull() + (mutation): ""BooleanLiteralat line 16StringLiteralat line 17StringLiteralat line 17StringLiteralat line 1817 | rebootTime: text('reboot_time').default('03:00'), // HH:mm format > 18 | primePodDaily: integer('prime_pod_daily', { mode: 'boolean' }) 19 | .notNull() + (mutation): ""BooleanLiteralat line 20StringLiteralat line 21StringLiteralat line 21StringLiteralat line 2221 | primePodTime: text('prime_pod_time').default('14:00'), // HH:mm format > 22 | ledNightModeEnabled: integer('led_night_mode_enabled', { mode: 'boolean' }) 23 | .notNull() + (mutation): ""BooleanLiteralat line 24StringLiteralat line 2625 | ledDayBrightness: integer('led_day_brightness').notNull().default(100), // 0-100 > 26 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100 27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format + (mutation): ""StringLiteralat line 25StringLiteralat line 2726 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100 > 27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format 28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format + (mutation): ""StringLiteralat line 2726 | ledNightBrightness: integer('led_night_brightness').notNull().default(0), // 0-100 > 27 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format 28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format + (mutation): ""StringLiteralat line 2827 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format > 28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format 29 | // Global wall-clock safety cap: if a side has been powered for this many + (mutation): ""StringLiteralat line 2827 | ledNightStartTime: text('led_night_start_time').default('22:00'), // HH:mm format > 28 | ledNightEndTime: text('led_night_end_time').default('07:00'), // HH:mm format 29 | // Global wall-clock safety cap: if a side has been powered for this many + (mutation): ""StringLiteralat line 37StringLiteralat line 32StringLiteralat line 3837 | mqttEnabled: integer('mqtt_enabled', { mode: 'boolean' }), > 38 | mqttUrl: text('mqtt_url'), 39 | mqttUsername: text('mqtt_username'), + (mutation): ""StringLiteralat line 3938 | mqttUrl: text('mqtt_url'), > 39 | mqttUsername: text('mqtt_username'), 40 | mqttPassword: text('mqtt_password'), + (mutation): ""StringLiteralat line 4039 | mqttUsername: text('mqtt_username'), > 40 | mqttPassword: text('mqtt_password'), 41 | mqttTopicPrefix: text('mqtt_topic_prefix'), + (mutation): ""StringLiteralat line 4140 | mqttPassword: text('mqtt_password'), > 41 | mqttTopicPrefix: text('mqtt_topic_prefix'), 42 | mqttHaDiscovery: integer('mqtt_ha_discovery', { mode: 'boolean' }), + (mutation): ""StringLiteralat line 4241 | mqttTopicPrefix: text('mqtt_topic_prefix'), > 42 | mqttHaDiscovery: integer('mqtt_ha_discovery', { mode: 'boolean' }), 43 | mqttTlsEnabled: integer('mqtt_tls_enabled', { mode: 'boolean' }), + (mutation): ""StringLiteralat line 4342 | mqttHaDiscovery: integer('mqtt_ha_discovery', { mode: 'boolean' }), > 43 | mqttTlsEnabled: integer('mqtt_tls_enabled', { mode: 'boolean' }), 44 | // When true, accept self-signed broker certs (sets rejectUnauthorized:false). + (mutation): ""StringLiteralat line 47StringLiteralat line 50BooleanLiteralat line 52StringLiteralat line 58BooleanLiteralat line 60StringLiteralat line 6261 | pumpStallRpmThreshold: integer('pump_stall_rpm_threshold').notNull().default(500), > 62 | pumpStallDwellSamples: integer('pump_stall_dwell_samples').notNull().default(2), 63 | pumpStallAutoRecoveryEnabled: integer('pump_stall_auto_recovery_enabled', { mode: 'boolean' }) + (mutation): ""StringLiteralat line 61StringLiteralat line 6362 | pumpStallDwellSamples: integer('pump_stall_dwell_samples').notNull().default(2), > 63 | pumpStallAutoRecoveryEnabled: integer('pump_stall_auto_recovery_enabled', { mode: 'boolean' }) 64 | .notNull() + (mutation): ""BooleanLiteralat line 65StringLiteralat line 66StringLiteralat line 6766 | pumpStallRecoveryRpm: integer('pump_stall_recovery_rpm').notNull().default(1500), > 67 | pumpStallRecoverySamples: integer('pump_stall_recovery_samples').notNull().default(3), 68 | // Autopilot global kill-switch. When false, the AutomationEngine evaluates + (mutation): ""StringLiteralat line 72BooleanLiteralat line 74StringLiteralat line 75StringLiteralat line 78StringLiteralat line 77StringLiteralat line 80StringLiteralat line 83StringLiteralat line 8483 | export const sideSettings = sqliteTable('side_settings', { > 84 | side: text('side', { enum: ['left', 'right'] }).primaryKey(), 85 | name: text('name').notNull(), // Must be provided explicitly during insert + (mutation): ""StringLiteralat line 8584 | side: text('side', { enum: ['left', 'right'] }).primaryKey(), > 85 | name: text('name').notNull(), // Must be provided explicitly during insert 86 | awayMode: integer('away_mode', { mode: 'boolean' }).notNull().default(false), + (mutation): ""StringLiteralat line 8685 | name: text('name').notNull(), // Must be provided explicitly during insert > 86 | awayMode: integer('away_mode', { mode: 'boolean' }).notNull().default(false), 87 | alwaysOn: integer('always_on', { mode: 'boolean' }).notNull().default(false), + (mutation): ""β¦and 2342 more surviving mutants not shown. See the HTML report for the full list.