Re: [PATCH] scripts/checkpatch: add Assisted-by: tag validation
From: Joe Perches
Date: Thu Mar 26 2026 - 20:02:55 EST
On Thu, 2026-03-26 at 17:05 -0400, Harry Wentland wrote:
> ```
> The coding-assistants.rst documentation defines the Assisted-by: tag
> format for AI-assisted contributions as:
>
> Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
>
> This format does not use an email address, so checkpatch currently
> reports a false positive about an invalid email when encountering this
> tag.
>
> Add Assisted-by: to the recognized signature tags and standard signature
> list. When an Assisted-by: tag is found, validate it instead of checking
> for an email address. The validation accepts AGENT_NAME with an optional
> :MODEL_VERSION,
If the documented form is as shown above, the MODEL_VERSION should
not be optional and should at least emit a warning.
> followed by optional tool names which may themselves
> carry a colon-separated version. MODEL_VERSION containing dots triggers
> a warning suggesting hyphens per convention.
Why?
Assisted-by: FOO:BAR.baz
seems reasonable to me. What's already in the logs can be ignored.
> Assisted-by: Claude:claude-opus-4-6
Why was anything assisting this?
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
[]
> @@ -3105,88 +3106,99 @@ sub process {
> }
> }
>
> - my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
> - my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment));
> - if ($suggested_email eq "") {
> - ERROR("BAD_SIGN_OFF",
> - "Unrecognized email address: '$email'\n" . $herecurr);
> +# Assisted-by: uses format AGENT_NAME[:MODEL_VERSION] [TOOL1[:VER]] [TOOL2[:VER]] instead of email
> + if ($sign_off =~ /^assisted-by:$/i) {
> + if ($email !~ /^\S+(\s+\S+)*$/) {
> + WARN("BAD_ASSISTED_BY",
> + "Assisted-by: should use format: 'Assisted-by: AGENT_NAME[:MODEL_VERSION] [TOOL1[:VER]] [TOOL2[:VER]]'\n" . $herecurr);
> + } elsif ($email =~ /^[^:\s]+:(\S+)/ && $1 =~ /\./) {
> + WARN("BAD_ASSISTED_BY",
> + "Assisted-by: MODEL_VERSION should use hyphens instead of dots: '$email'\n" . $herecurr);
> + }
> } else {
Perhaps all of the changes below should be removed and next used above
> - my $dequoted = $suggested_email;
> - $dequoted =~ s/^"//;
> - $dequoted =~ s/" </ </;
> - # Don't force email to have quotes
> - # Allow just an angle bracketed address
> - if (!same_email_addresses($email, $suggested_email)) {
> - if (WARN("BAD_SIGN_OFF",
> - "email address '$email' might be better as '$suggested_email'\n" . $herecurr) &&
> - $fix) {
> - $fixed[$fixlinenr] =~ s/\Q$email\E/$suggested_email/;
> + my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
> + my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment));
> + if ($suggested_email eq "") {
> + ERROR("BAD_SIGN_OFF",
> + "Unrecognized email address: '$email'\n" . $herecurr);
> + } else {
> + my $dequoted = $suggested_email;
> + $dequoted =~ s/^"//;
> + $dequoted =~ s/" </ </;
> + # Don't force email to have quotes
> + # Allow just an angle bracketed address
> + if (!same_email_addresses($email, $suggested_email)) {
> + if (WARN("BAD_SIGN_OFF",
> + "email address '$email' might be better as '$suggested_email'\n" . $herecurr) &&
> + $fix) {
> + $fixed[$fixlinenr] =~ s/\Q$email\E/$suggested_email/;
> + }
> }
> - }
>
> - # Address part shouldn't have comments
> - my $stripped_address = $email_address;
> - $stripped_address =~ s/\([^\(\)]*\)//g;
> - if ($email_address ne $stripped_address) {
> - if (WARN("BAD_SIGN_OFF",
> - "address part of email should not have comments: '$email_address'\n" . $herecurr) &&
> - $fix) {
> - $fixed[$fixlinenr] =~ s/\Q$email_address\E/$stripped_address/;
> + # Address part shouldn't have comments
> + my $stripped_address = $email_address;
> + $stripped_address =~ s/\([^\(\)]*\)//g;
> + if ($email_address ne $stripped_address) {
> + if (WARN("BAD_SIGN_OFF",
> + "address part of email should not have comments: '$email_address'\n" . $herecurr) &&
> + $fix) {
> + $fixed[$fixlinenr] =~ s/\Q$email_address\E/$stripped_address/;
> + }
> }
> - }
>
> - # Only one name comment should be allowed
> - my $comment_count = () = $name_comment =~ /\([^\)]+\)/g;
> - if ($comment_count > 1) {
> - WARN("BAD_SIGN_OFF",
> - "Use a single name comment in email: '$email'\n" . $herecurr);
> - }
> + # Only one name comment should be allowed
> + my $comment_count = () = $name_comment =~ /\([^\)]+\)/g;
> + if ($comment_count > 1) {
> + WARN("BAD_SIGN_OFF",
> + "Use a single name comment in email: '$email'\n" . $herecurr);
> + }
>
>
> - # [stable@xxxxxxxxxxxxxxx](mailto:stable@xxxxxxxxxxxxxxx) or [stable@xxxxxxxxxx](mailto:stable@xxxxxxxxxx) shouldn't
> - # have an email name. In addition comments should strictly
> - # begin with a #
> - if ($email =~ /^.*stable\@(?:vger\.)?kernel\.org/i) {
> - if (($comment ne "" && $comment !~ /^#.+/) ||
> - ($email_name ne "")) {
> - my $cur_name = $email_name;
> + # [stable@xxxxxxxxxxxxxxx](mailto:stable@xxxxxxxxxxxxxxx) or [stable@xxxxxxxxxx](mailto:stable@xxxxxxxxxx) shouldn't
> + # have an email name. In addition comments should strictly
> + # begin with a #
> + if ($email =~ /^.*stable\@(?:vger\.)?kernel\.org/i) {
> + if (($comment ne "" && $comment !~ /^#.+/) ||
> + ($email_name ne "")) {
> + my $cur_name = $email_name;
> + my $new_comment = $comment;
> + $cur_name =~ s/[a-zA-Z\s\-\"]+//g;
> +
> + # Remove brackets enclosing comment text
> + # and # from start of comments to get comment text
> + $new_comment =~ s/^\((.*)\)$/$1/;
> + $new_comment =~ s/^\[(.*)\]$/$1/;
> + $new_comment =~ s/^[\s\#]+|\s+$//g;
> +
> + $new_comment = trim("$new_comment $cur_name") if ($cur_name ne $new_comment);
> + $new_comment = " # $new_comment" if ($new_comment ne "");
> + my $new_email = "$email_address$new_comment";
> +
> + if (WARN("BAD_STABLE_ADDRESS_STYLE",
> + "Invalid email format for stable: '$email', prefer '$new_email'\n" . $herecurr) &&
> + $fix) {
> + $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
> + }
> + }
> + } elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) {
> my $new_comment = $comment;
> - $cur_name =~ s/[a-zA-Z\s\-\"]+//g;
>
> - # Remove brackets enclosing comment text
> - # and # from start of comments to get comment text
> - $new_comment =~ s/^\((.*)\)$/$1/;
> + # Extract comment text from within brackets or
> + # c89 style /*...*/ comments
> $new_comment =~ s/^\[(.*)\]$/$1/;
> - $new_comment =~ s/^[\s\#]+|\s+$//g;
> + $new_comment =~ s/^\/\*(.*)\*\/$/$1/;
>
> - $new_comment = trim("$new_comment $cur_name") if ($cur_name ne $new_comment);
> - $new_comment = " # $new_comment" if ($new_comment ne "");
> - my $new_email = "$email_address$new_comment";
> + $new_comment = trim($new_comment);
> + $new_comment =~ s/^[^\w]$//; # Single lettered comment with non word character is usually a typo
> + $new_comment = "($new_comment)" if ($new_comment ne "");
> + my $new_email = format_email($email_name, $name_comment, $email_address, $new_comment);
>
> - if (WARN("BAD_STABLE_ADDRESS_STYLE",
> - "Invalid email format for stable: '$email', prefer '$new_email'\n" . $herecurr) &&
> + if (WARN("BAD_SIGN_OFF",
> + "Unexpected content after email: '$email', should be: '$new_email'\n" . $herecurr) &&
> $fix) {
> $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
> }
> }
> - } elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) {
> - my $new_comment = $comment;
> -
> - # Extract comment text from within brackets or
> - # c89 style /*...*/ comments
> - $new_comment =~ s/^\[(.*)\]$/$1/;
> - $new_comment =~ s/^\/\*(.*)\*\/$/$1/;
> -
> - $new_comment = trim($new_comment);
> - $new_comment =~ s/^[^\w]$//; # Single lettered comment with non word character is usually a typo
> - $new_comment = "($new_comment)" if ($new_comment ne "");
> - my $new_email = format_email($email_name, $name_comment, $email_address, $new_comment);
> -
> - if (WARN("BAD_SIGN_OFF",
> - "Unexpected content after email: '$email', should be: '$new_email'\n" . $herecurr) &&
> - $fix) {
> - $fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
> - }
> }
> }
>
>
> ```