create(); $schedule = BackupSchedule::create([ 'tenant_id' => $tenant->id, 'name' => 'Daily', 'is_enabled' => true, 'timezone' => 'UTC', 'frequency' => 'daily', 'time_of_day' => '10:00:00', 'days_of_week' => null, 'policy_types' => ['deviceConfiguration'], 'include_foundations' => true, 'retention_keep_last' => 30, 'last_run_at' => null, 'last_run_status' => null, 'next_run_at' => null, ]); $startedAt = CarbonImmutable::parse('2026-01-01 00:00:00', 'UTC'); $operationRun = OperationRun::create([ 'workspace_id' => (int) $tenant->workspace_id, 'tenant_id' => $tenant->id, 'user_id' => null, 'initiator_name' => 'System', 'type' => 'backup_schedule_run', 'status' => 'running', 'outcome' => 'pending', 'run_identity_hash' => hash('sha256', 'backup_schedule_run:'.$schedule->id), 'summary_counts' => [], 'failure_summary' => [], 'context' => [ 'backup_schedule_id' => (int) $schedule->id, ], 'started_at' => $startedAt, 'created_at' => $startedAt, 'updated_at' => $startedAt, ]); $this->artisan('tenantpilot:operation-runs:reconcile-backup-schedules', [ '--tenant' => [$tenant->id], '--older-than' => 0, ])->assertSuccessful(); $operationRun->refresh(); expect($operationRun->status)->toBe('completed'); expect($operationRun->outcome)->toBe('failed'); expect($operationRun->failure_summary)->toMatchArray([ [ 'code' => 'backup_schedule.stalled', 'message' => 'Backup schedule run exceeded reconciliation timeout and was marked failed.', 'reason_code' => 'unknown_error', ], ]); expect($operationRun->context)->toMatchArray([ 'backup_schedule_id' => (int) $schedule->id, ]); });