bug#81520: Add pre-receive hook to Savannah to reject LLM-encumbered commits

Eli Zaretskii <[email protected]> Sun, 02 Aug 2026 08:32:59 +0300
Newsgroups gmane.emacs.bugs
Message-ID <[email protected]>
> Date: Sat, 1 Aug 2026 11:37:27 -0700
> Cc: [email protected], [email protected]
> From: Jim Porter <[email protected]>
> 
> On 7/31/2026 11:22 PM, Eli Zaretskii wrote:
> >>
> >> Yeah, I think regexps would make sense here. The email addresses are
> >> still probably the most accurate indicator though. We want to disallow
> >> an address like "[email protected]", but not
> >> disallow the word "copilot" entirely.
> > 
> > Why not disallow "copilot" entirely?
> 
> I suppose we could, but it's an ordinary dictionary word, and we have a 
> more-specific identifier we could use (the email). While disallowing the 
> word "copilot" could hypothetically catch more cases, I'm not sure those 
> cases actually exist.

"Copilot" in today's software-related prose is a reference to
Microsoft Copilot with high enough probability to treat it as suspect,
IME.

> The easiest checks are for the Assisted-By and AI-Assisted fields, which 
> we can always reject. I *definitely* think we should reject these, since 
> they're a clear indication of LLM assistance that isn't specific to any 
> one model.

Agreed.  In addition, we don't want such headings in commit log
messages regardless of whether they name LLM-generated text.

> The remaining cases I'm aware of are when an LLM-associated email 
> address (possibly with display name) appears as the author or committer, 
> or in the Co-Authored-By/Co-Developed-By fields. We could just check the 
> whole commit message for any LLM-ish words if we wanted though. In 
> practice, I doubt it will make much difference.

I think we should check both headings like Co-Authored-By and the rest
of the body of the log message.

> > It is not a separate job, because the description of what is
> > disallowed is tightly coupled to what the hook actually does.
> 
> Should be document the exact implementation we use for detecting 
> LLM-assisted commits, or is it enough to state that our policies don't 
> permit them?

Not the implementation, but the headings and the references to
LLM-based agents that are not allowed.

> I'm not sure people need to know ahead of time that (for example), we 
> don't allow commits with the word "copilot" in them.

Why not?  And CONTRIBUTE can be read not "ahead of time", but as
result of a commit being rejected.

> >> The problem is that when the LLM initiates the "git commit", it will get
> >> back the result of that command. Most LLMs are designed to try different
> >> things if a command fails, including things we humans might consider
> >> malicious. If the commit-msg hook causes "git commit" to fail with a
> >> message saying we reject commits with a "Co-Authored-By: Some LLM"
> >> field, there's a good chance the LLM will remove that line and retry the
> >> commit. The user might not even realize it happened unless they look
> >> carefully at the LLM's logs.
> > 
> > My suggestion is to search the entire log message _and_ the
> > author/committer for the relevant patterns.  Thus, whether there is or
> > isn't Co-Authored-By is not relevant in a push hook more than it is
> > relevant in a commit hook.  Or what am I missing?
> 
> If we reject LLM-assisted commits (no matter what precise logic we use), 
> there's a reasonable chance that an agentic LLM will simply rewrite the 
> commit message to pass our check, effectively lying by omission. Since 
> this can happen in the background, a well-intentioned user running an 
> LLM might not even see the error message unless they look at the full logs.

I think we are arguing about something we already agreed upon: I'm not
opposed to a pre-push hook.  I just want us to also have a pre-commit
hook, for the benefit of those who will not rewrite the commit message
in malicious and misleading ways.  Let's not follow the lead of TSA
and other similar agencies in punishing the masses of the innocent
because of the few guilty ones.

> >> We could also do an applypatch-msg (or pre-applypatch) hook. If I'm
> >> understanding your concern Eli, this should make your life easier
> >> without running into the above problems with a commit-msg hook. This
> >> hypothetical hook would run when you call "git am foo.patch" and reject
> >> it immediately so that you don't have to remove the commit later when
> >> preparing to push.
> > 
> > "git am" also commits, so a pre-commit hook should cover this, right?
> > And "git apply" will be followed by a commit, so again a pre-commit
> > hook should do.
> 
> According to the Git documentation[1], "git am" only runs the various 
> applypatch hooks

???  "git am" results ins a commit, so it must run 'commit'.  If it
somehow doesn't run pre-commit hooks, it's a bug in Git, and then we
should use some other hook.  Because "git am" must be subject to these
tests.

By contrast, "git apply" should NOT be tested, because it doesn't
produce a commit.  One should be able to try applying LLM-generated
code to the local repository; as long as the changes are not
committed, we don't care.

> The benefit of doing this in applypatch-msg instead of commit-msg is 
> simply to avoid giving an agentic LLM all the feedback it needs to hide 
> its use from us when it generates the commit.

I don't understand the difference, but in any case, please change the
focus of your attention to be on the user who does this, not on the
LLMs that you want to defeat.  This feature is supposed to help us,
the Emacs developers, in detecting potential references to
LLM-generated stuff.  It is not for defeating the evil SkyNet.

> (After checking to be sure, pre-commit runs too early; it's before the 
> user enters the commit message, so we need commit-msg and/or 
> applypatch-msg.)

OK, but these are just details.  The important part is that we need to
run these when a patch is being committed, not when it is applied.
Btw, we should also check merge-commits.