Whether a fix needs a stable tag, and which releases it should reach, is
decided by hand and is often missed or left too broad. Add a read-only
procedure that decides whether a change is stable material using the
criteria the stable trees apply in practice, finds the first release
containing each introducing commit with git tag --contains, checks that
the fix applies to the oldest affected release, and returns the stable
tag lines with supporting evidence.

Keep the skill entry point and procedure together under
agents/skills/stable-tag/. Connect it to the coding-assistant guidance so
bug fixes get a stable decision after Fixes attribution and before
finalization.

If the decision cannot be made, return no tag and keep the fix as a
draft. Applying the tag and writing the commit message remain outside the
skill.

Assisted-by: LLM
Signed-off-by: Sasha Levin <[email protected]>
---
 Documentation/process/coding-assistants.rst |  25 ++-
 agents/skills/find-fixes/guide.rst          |   5 +-
 agents/skills/stable-tag/SKILL.md           |  25 +++
 agents/skills/stable-tag/guide.rst          | 228 ++++++++++++++++++++
 4 files changed, 276 insertions(+), 7 deletions(-)
 create mode 100644 agents/skills/stable-tag/SKILL.md
 create mode 100644 agents/skills/stable-tag/guide.rst

diff --git a/Documentation/process/coding-assistants.rst 
b/Documentation/process/coding-assistants.rst
index 8d42d3c10f9ce..0eb8dc91575bf 100644
--- a/Documentation/process/coding-assistants.rst
+++ b/Documentation/process/coding-assistants.rst
@@ -85,6 +85,21 @@ commit. If the origin remains unresolved, report the missing 
evidence and
 keep the fix as a draft. The calling workflow must hold finalization until
 the attribution is resolved.
 
+Determining stable tags
+=======================
+
+Once the Fixes tag is determined, an assistant must follow
+agents/skills/stable-tag/guide.rst to decide whether the fix should be
+backported to stable kernels and to generate the stable tag. This also
+applies to checking an existing stable tag during review. The skill entry
+point is agents/skills/stable-tag/SKILL.md. Tell the skill whether the fix
+addresses an unpublished vulnerability, as described in
+Documentation/process/threat-model.rst.
+
+The skill returns a decision only. It does not modify files or commit
+messages. If the decision remains unresolved, report the missing evidence
+and keep the fix as a draft.
+
 Procedure for finding and fixing bugs
 =====================================
 
@@ -108,11 +123,11 @@ these steps:
    re-running a complete analysis; drop any fix that doesn't work and try
    another one. The fix must not add build warnings and must pass the
    checkpatch.pl checks (see submitting-patches.rst).
-6. Determine the Fixes tag as described above. Once attribution is resolved,
-   commit the working fix with a detailed message describing the problem,
-   the solution and the verified Fixes tag. This commit is part of the
-   fix-preparation workflow, not the attribution skill. Do not add a
-   Signed-off-by tag, and add an Assisted-by tag, as described above.
+6. Determine the Fixes tag and the stable tag as described above. Once both
+   are resolved, commit the working fix with a detailed message describing
+   the problem, the solution, the verified Fixes tag and any stable tag. This
+   commit is part of the fix-preparation workflow, not the skills. Do not add
+   a Signed-off-by tag, and add an Assisted-by tag, as described above.
 7. Identify the maintainers and lists using scripts/get_maintainer.pl.
    Documentation/process/security-bugs.rst shows how to do that.
 8. Indicate what could not be done. If the fix could not be built or tested, or
diff --git a/agents/skills/find-fixes/guide.rst 
b/agents/skills/find-fixes/guide.rst
index 7b58c526f3149..c1e66a5d1d29b 100644
--- a/agents/skills/find-fixes/guide.rst
+++ b/agents/skills/find-fixes/guide.rst
@@ -173,5 +173,6 @@ trailer or placeholder. The calling bug-fix workflow must 
hold finalization
 and surface the unresolved origin instead of fabricating a tag or silently
 treating the investigation as complete.
 
-Determining a Fixes tag does not establish stable eligibility or replace the
-requirements in Documentation/process/stable-kernel-rules.rst.
+Determining a Fixes tag does not establish stable eligibility. Follow
+agents/skills/stable-tag/guide.rst to decide whether the fix needs a stable
+tag.
diff --git a/agents/skills/stable-tag/SKILL.md 
b/agents/skills/stable-tag/SKILL.md
new file mode 100644
index 0000000000000..5fcad4eed6027
--- /dev/null
+++ b/agents/skills/stable-tag/SKILL.md
@@ -0,0 +1,25 @@
+---
+# SPDX-License-Identifier: GPL-2.0-only
+name: stable-tag
+description: >-
+  Decide whether a Linux kernel fix should be backported to stable kernels
+  and return verified Cc: stable tag lines. Use when preparing or reviewing
+  bug-fix patches, drafting their commit messages, or checking an existing
+  stable tag.
+---
+
+# Determine a stable tag
+
+Read and follow [the decision procedure](guide.rst), relative to this
+skill directory. The canonical path in the kernel repository is
+`agents/skills/stable-tag/guide.rst`. If necessary, locate the
+repository root with `git rev-parse --show-toplevel`.
+
+Perform the stable decision only. Return the tag lines and their supporting
+evidence, a no-tag decision with its reasons, or an unresolved result
+explaining the missing evidence. Return no other trailers or commit-message
+draft as part of the skill. Do not change files, the index, refs, or commit
+messages, do not send mail, and do not apply the tag or create a commit. An
+unresolved result must contain no stable tag or placeholder; it tells the
+calling workflow to hold finalization. Applying the tag belongs to that
+workflow.
diff --git a/agents/skills/stable-tag/guide.rst 
b/agents/skills/stable-tag/guide.rst
new file mode 100644
index 0000000000000..ad6c0fc14f24b
--- /dev/null
+++ b/agents/skills/stable-tag/guide.rst
@@ -0,0 +1,228 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+.. _stable_tag:
+
+Deciding whether a fix needs a stable tag
+=========================================
+
+A stable tag in the sign-off area asks the stable team to backport a commit to
+the stable and longterm trees once it is merged in mainline. The tag syntax is
+described in Documentation/process/stable-kernel-rules.rst. Deciding on a tag
+requires knowing whether the change is stable material, which released kernels
+contain the bug, and whether the fix applies to them.
+
+This procedure applies to fixes being prepared for mainline and to reviews of
+existing stable tags. It decides using read-only inspection. It does not
+authorize changing files, applying patches, checking out revisions, fetching
+history, sending mail, or creating or amending commits.
+
+Establish the change and its inputs
+-----------------------------------
+
+Record the change being decided:
+
+* For a commit, resolve its full object ID and inspect its message, diff, and
+  parent. For a patch, identify its base revision. For uncommitted changes,
+  inspect ``git diff --cached`` and ``git diff`` separately and record the base
+  commit.
+* For a patch series, note the other patches, their order, and which of them
+  are being tagged for stable.
+* Obtain the verified Fixes tags for the change. If the change fixes a bug and
+  attribution has not been done, follow agents/skills/find-fixes/guide.rst
+  first. If attribution is unresolved, the stable decision is unresolved too,
+  unless attribution established that the bug predates the available history.
+* Determine from the calling workflow whether the change fixes an unpublished
+  vulnerability. See Documentation/process/security-bugs.rst.
+
+Decide whether the change is stable material
+--------------------------------------------
+
+Judge the change by what it does, not by how its message describes it. Many
+fixes are described as cleanups or improvements. A change that frees
+resources on an error path, initializes data, balances reference counts,
+corrects locking, or adds a missing check fixes a bug. The absence of Fixes
+or Reported-by tags is not a reason to leave a fix untagged.
+
+Tag the following:
+
+* Fixes for crashes, oopses, BUG and WARN splats, hangs, soft and hard
+  lockups, RCU stalls, deadlocks, data corruption, and security issues.
+* Fixes for use-after-free, double free, NULL pointer dereference,
+  out-of-bounds access, integer overflow, uninitialized data, reference
+  counting errors, and memory or resource leaks.
+* Fixes for races, including data races.
+* Fixes for incorrect behavior, such as wrong results, wrong hardware
+  programming, or endianness and type errors.
+* Fixes for problems reported by syzbot, other fuzzers, or the KASAN, KMSAN,
+  KCSAN, and UBSAN sanitizers.
+* Build fixes, including Kconfig dependency and missing include fixes, other
+  than for code that depends on ``CONFIG_BROKEN``.
+* New device IDs for drivers that exist in the affected releases, and quirks
+  or workarounds for broken hardware.
+* Device tree fixes, and device tree additions for hardware that existing
+  drivers support.
+* Corrections to documentation that is wrong.
+* Performance fixes that prevent lockups, stalls, or hangs.
+* Reverts of commits that are in a released kernel.
+* Fixes for bugs introduced by commits that were backported to stable.
+
+Do not tag the following:
+
+* New features, new user-visible interfaces or behavior, new drivers, and new
+  module parameters or sysfs attributes.
+* Refactoring, code movement, and preparation patches that fix nothing on
+  their own. If a tagged fix depends on such a patch, handle it as a
+  prerequisite, as described below.
+* Optimizations that do not prevent lockups, stalls, or hangs.
+* Cleanups that do not change behavior, such as style, whitespace, renames,
+  and comment rewording.
+* Changes to ``drivers/staging/``.
+* Changes to code that no released kernel contains.
+
+When a change is a borderline case, decide it and record the reasoning that
+settled it, so that the author and maintainers can review it.
+
+Find the affected releases
+--------------------------
+
+For each Fixes tag, find the first mainline release that contains the
+introducing commit. With ``introducer`` set to its full commit ID::
+
+    git tag --contains "$introducer" --list 'v[0-9]*' |
+        grep -v -- -rc | sort -V | head -n 1
+
+Use tag containment as shown; do not derive the release from ``git describe``
+output. Check that the repository has the release tags (``git tag --list
+'v[0-9]*'``). Missing tags are a limit to report, not evidence that no release
+contains the commit.
+
+* The oldest release found across all Fixes tags is the oldest affected
+  release.
+* If no release contains an introducer, the bug exists only in the current
+  development cycle, and the fix needs no stable tag for it. The exception is
+  an introducer that was itself backported to stable: tag the fix if the
+  introducer carries a stable tag or a Fixes tag that points into a released
+  kernel::
+
+      git log -1 --format=%B "$introducer" | grep -i -E '^(cc: 
*<?stable@|fixes:)'
+
+  If a stable repository is available, also look for a backport of the
+  introducer in the stable branches, whose messages record the upstream
+  commit ID.
+* If the change has no Fixes tag, as with device IDs, quirks, build fixes, and
+  bugs that predate the available history, the affected releases are those
+  containing the code it changes. Find them with the checks in the next
+  section.
+
+Check that the fix applies to the affected releases
+---------------------------------------------------
+
+With ``oldest`` set to the oldest affected release tag, check that every file,
+function, macro, structure field, and Kconfig symbol that the fix uses or
+modifies exists there with compatible semantics. For example::
+
+    git show "$oldest:$path"
+    git grep -n -w 'symbol' "$oldest" -- "$path"
+    git log --oneline --follow "$oldest..$base" -- "$path"
+
+Follow renames: a file that moved since the release does not mean the code is
+absent. Conversely, a file with the same name in an older release can hold
+different code, so compare the relevant code rather than paths.
+
+If something the fix needs is missing from the oldest affected release,
+identify the commit that added it, and then either:
+
+* list that commit as a prerequisite, if it is small, self-contained, and
+  suitable for stable on its own terms; or
+* set the floor to the first release that contains it, so that the tag covers
+  only the releases where the fix applies, and describe what older releases
+  need in the commit message.
+
+A shared file, membership in the same series, or an existing dependency note
+is not evidence that a prerequisite is needed. Establish that the fix fails to
+build or behaves incorrectly without it.
+
+For a series, a patch that the fix depends on and that is part of the same
+series does not need to be listed as a prerequisite, but it needs its own
+stable tag with the same floor.
+
+Check subsystem policy
+----------------------
+
+Find the maintainer profiles for the files the change touches::
+
+    scripts/get_maintainer.pl --sections -f "$path"
+
+Read each ``P:`` document listed and follow its instructions on stable tags.
+Some subsystems require an explicit stable tag even when a Fixes tag is
+present. Others prefer that maintainers add stable tags themselves; for those,
+return the tag as a suggestion for the patch notes below the ``---`` line
+instead of as a trailer.
+
+Return the decision
+-------------------
+
+Return the stable decision to the caller. Drafting a commit message or adding
+other trailers is outside this procedure.
+
+For a tag, provide:
+
+* The change and base revisions analyzed.
+* Why the change is stable material, including the failure and how it is
+  triggered.
+* The first release containing each introducer, and how backports of the
+  introducers were checked.
+* The applicability checks, prerequisites, and floor, with the evidence for
+  each.
+* The subsystem policy consulted, and any limitations such as missing tags or
+  history.
+* The tag lines.
+
+Render the tag lines as follows:
+
+* Use a plain tag when the Fixes tags identify the affected releases and the
+  fix applies to all of them::
+
+      Cc: [email protected]
+
+* Add a floor when the change has no Fixes tag and older releases are not
+  affected, or when the fix applies only from a later release than the Fixes
+  tags imply. The floor names the first release to receive the fix::
+
+      Cc: [email protected] # 6.1.x
+
+* List prerequisites in cherry-pick order before the tag for the fix itself,
+  all with the same floor. With ``floor`` set to the floor and ``prereq`` to
+  the prerequisite's full commit ID::
+
+      git show --no-patch --abbrev=12 \
+          --format="Cc: [email protected] # $floor: %h: %s" "$prereq"
+
+  This produces lines of the following form::
+
+      Cc: [email protected] # 6.1.x: 0123456789ab: subsys: Prerequisite 
subject
+      Cc: [email protected] # 6.1.x
+
+* For an unpublished vulnerability, use ``[email protected]`` instead of
+  ``[email protected]`` in every line.
+
+Give every stable line in a commit the same floor: a line without a version
+asks for every tree and cancels the floor of the others. Stable tooling reads
+the first version number in a line as its floor, so put notes about older
+releases in the commit message rather than in the tag comment. Do not add a
+display name, and start any comment with ``#``; ``scripts/checkpatch.pl``
+warns about both. The tag belongs in the sign-off area and is not a mail
+recipient. ``git send-email`` adds Cc trailers as recipients by default, which
+the submission workflow must account for.
+
+For no tag, give the reasons: the change is not stable material, or no
+released kernel contains the bug. A Fixes tag is still useful when the
+introducer is in the current development cycle.
+
+For an unresolved result, give the missing information and the next
+investigation that could settle it. Do not emit a stable tag or placeholder.
+The calling workflow must hold finalization and surface the open question
+instead of guessing.
+
+When reviewing an existing stable tag, apply the same procedure and report
+any difference from the existing tag with its evidence.
-- 
2.53.0


Reply via email to