Dnf history: "C" in the Action(s) column, "Reason Change"


In the Action(s) column of my dnf history output I can see a lot of transactions marked with ‘C’. If I get details on one of those transactions with dnf history info <transaction-number>, one of the packages part of the transaction is marked with “Reason Change”; I would assume this corresponds to that “C” action.

The weird thing is that in tens of transactions, for more than a year now (since upgrading to Fedora 33), there is always the same one and only package marked with this “Reason Change”.

Plus, while the other actions in history have some minimal documentation (in Table.1 inside the Working with Transaction History section of the dnf docs), this C/“Reason Change” is not documented as far as I can tell.
On the DNF readthedocs documentation site for dnf, the only mention about “Reason Change” is in a list of possible values for some rpm Object field, part of the section Stored Transaction JSON Format, but even there it is just mentioned, without any other details. Furthermore, the first paragraph says anyway that “The stored transaction format is considered unstable”.
(sure, a few places using “Reason Change” can be found in the dnf python source code, but it is far from being clear what exactly is the function for that action).

Does anyone have more information/an explanation about this ?
Thank you.

Some investigation progress:
First of all, that same package that shows up every time marked with “Reason Change” happens to be the first in the list of installed packages (as listed by dnf list --installed, which sorts them by package name ASCII-style, like using LC_ALL=C sort ...). So, the package seems to get picked somehow arbitrarily.

Now, about that “Reason Change”, I finally found some information, in the sources for libdnf, in libdnf/transaction/Types.hpp. One comment inside on line 56 indicates that this “Reason Change” action is used when “a package was kept on the system but it’s [sic] reason has changed”. And what exactly is a “reason” then ?

Towards the bottom (line 123) of this header file there is even an entire example/test command for generating such a situation, together with a couple of extra explanations/cases for using this action:

  • new = a brand new reason why a package was installed or removed
  • inherited = a package was installed in the past, re-use it’s [sic] reason in existing transaction

Again, even these details did not bubble up all the way to the higher levels of the user documentation and it’s still not clear who/what sets these “reasons” and ultimately why on my box dnf reports this changed “reason” pretty much every upgrade …