The README generator read its author URL out of the ## Credits sections it
writes itself. .mailmap now folds every address a person commits under into
their @infinito.nexus one, whose local part names their social profile, and
that profile becomes the single point of truth for an author.
utils/meta/identity.py parses .mailmap rather than shelling out to
git check-mailmap, which refuses the worktree the test container mounts.
Cross-checked against git over all 14 identities in the history: no
disagreement.
A new env handler carries the committing identity into the container, which
mounts the checkout but not the contributor's git configuration. Without it
both new tests would skip exactly where they are meant to fire:
* tests/integration/meta/test_commit_identity.py fails when the configured
address does not fold, and prints the .mailmap line to add.
* tests/external/repository/test_author_profile.py probes that profile
live, behind a canary so an unreachable instance is not reported as a
missing profile.
Both look at the current address only. Probing every declared author would be
red for people who have not created a profile yet, and a suite that is red for
someone else's omission stops being read.
Marko Pjevac is declared as a role author but has no address here, so his
Credits line stays unlinked.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
i18n/names kept a private _sources() that walked the role directories, read
the README heading and added galaxy_info.name. The brand rule needs the same
knowledge, and a second copy is the drift that has already bitten this branch
twice.
The three readers live under utils/meta now. titles also pins the precedence
that was implicit: the README heading wins over galaxy_info.name, because the
documentation is built from the heading. authors stays thin on purpose - the
derivation from the Credits sections belongs to utils/roles/credits, and this
is only the entry point for a reader that wants the names without the URLs.
The titles arrive sorted and deduplicated rather than in read order, which the
alternation built from them does not notice: it sorts by length itself.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>