mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] scripts/checkpatch: add Assisted-by: tag validation
@ 2026-03-26 21:05 Harry Wentland
  2026-03-26 23:59 ` Joe Perches
  0 siblings, 1 reply; 3+ messages in thread
From: Harry Wentland @ 2026-03-26 21:05 UTC (permalink / raw)
  To: apw, joe, linux-kernel
  Cc: dwaipayanray1, lukas.bulwahn, Harry Wentland, Jonathan Corbet,
	Jani Nikula

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, followed by optional tool names which may themselves
carry a colon-separated version. MODEL_VERSION containing dots triggers
a warning suggesting hyphens per convention.

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 scripts/checkpatch.pl | 146 +++++++++++++++++++++++-------------------
 1 file changed, 79 insertions(+), 67 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index e56374662ff7..3d0688f50b7c 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -641,6 +641,7 @@ our $signature_tags = qr{(?xi:
 	Reviewed-by:|
 	Reported-by:|
 	Suggested-by:|
+	Assisted-by:|
 	To:|
 	Cc:
 )};
@@ -737,7 +738,7 @@ sub find_standard_signature {
 	my ($sign_off) = @_;
 	my @standard_signature_tags = (
 		'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:',
-		'Reviewed-by:', 'Reported-by:', 'Suggested-by:'
+		'Reviewed-by:', 'Reported-by:', 'Suggested-by:', 'Assisted-by:'
 	);
 	foreach my $signature (@standard_signature_tags) {
 		return $signature if (get_edit_distance($sign_off, $signature) <= 2);
@@ -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 {
-				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@vger.kernel.org or stable@kernel.org 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@vger.kernel.org or stable@kernel.org 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/;
-					}
 				}
 			}
 
-- 
2.53.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-03-27 13:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-26 21:05 [PATCH] scripts/checkpatch: add Assisted-by: tag validation Harry Wentland
2026-03-26 23:59 ` Joe Perches
2026-03-27 13:30   ` Harry Wentland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox