Commit cb46beb292 for wordpress.org

commit cb46beb2925fe42d2c717310322ca7e324e36ca6
Author: gziolo <gziolo@git.wordpress.org>
Date:   Fri Nov 6 13:10:54 2026 +0000

    Abilities API: Require a registered category for abilities

    Partially reverts [63343]. Abilities that omit a category are no longer assigned to the built-in `uncategorized` category, which is removed. Registration fails with a `_doing_it_wrong()` notice instead. Updates the docs to explain why categories are required and how to reuse existing ones.

    Developed in https://github.com/WordPress/wordpress-develop/pull/15462.

    Props gziolo, jason_the_adams, jorgefilipecosta.
    Fixes #65569.




    Built from https://develop.svn.wordpress.org/trunk@65308


    git-svn-id: http://core.svn.wordpress.org/trunk@64448 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/abilities-api.php b/wp-includes/abilities-api.php
index f50531e5b5..6647aa7c2b 100644
--- a/wp-includes/abilities-api.php
+++ b/wp-includes/abilities-api.php
@@ -52,10 +52,9 @@
  *     }
  *     add_action( 'wp_abilities_api_init', 'my_plugin_register_abilities' );
  *
- * Use a category to group related abilities and improve discoverability. The
- * `data-export` category must be registered first with `wp_register_ability_category()`
+ * Every ability requires a category to group related abilities and improve discoverability.
+ * The `data-export` category must be registered first with `wp_register_ability_category()`
  * on `wp_abilities_api_categories_init`, or the ability registration fails.
- * Abilities that omit `category` fall back to the built-in `uncategorized` category.
  *
  * Once registered, abilities can be checked, retrieved, and managed:
  *
@@ -148,9 +147,11 @@ declare( strict_types = 1 );
  *
  * ### Categories
  *
- * Abilities can be organized into categories. If no category is provided, the ability is
- * assigned to the built-in `uncategorized` category. Custom categories must be registered
- * before the abilities that reference them:
+ * Every ability must specify a registered category. Categories group related abilities
+ * so clients can discover and retrieve relevant subsets. Plugins can reuse an existing
+ * category when appropriate, including categories registered by core. Custom categories must be
+ * registered on `wp_abilities_api_categories_init` before abilities that reference them
+ * are registered on `wp_abilities_api_init`:
  *
  *     function my_plugin_register_categories(): void {
  *         wp_register_ability_category(
@@ -286,7 +287,6 @@ declare( strict_types = 1 );
  *
  * @since 6.9.0
  * @since 7.1.0 Added the `public` meta argument.
- * @since 7.2.0 The `category` argument is now optional and defaults to `uncategorized`.
  * @since 7.2.0 Added the `required_capabilities` argument.
  *
  * @see WP_Abilities_Registry::register()
@@ -304,9 +304,9 @@ declare( strict_types = 1 );
  *     @type string               $label                 Required. The human-readable label for the ability.
  *     @type string               $description           Required. A detailed description of what the ability does
  *                                                       and when it should be used.
- *     @type string               $category              Optional. The ability category slug this ability belongs to.
- *                                                       Defaults to `uncategorized`. Custom categories must be registered
- *                                                       via `wp_register_ability_category()` before registering the ability.
+ *     @type string               $category              Required. The registered ability category slug this ability belongs to.
+ *                                                       Custom categories must be registered via
+ *                                                       `wp_register_ability_category()` before registering the ability.
  *     @type callable             $execute_callback      Required. A callback function to execute when the ability is invoked.
  *                                                       Receives optional mixed input data and must return either a result
  *                                                       value (any type) or a `WP_Error` object on failure.
@@ -707,10 +707,8 @@ function _wp_get_abilities_match_meta( array $meta, array $conditions ): bool {
  * Registers a new ability category.
  *
  * Ability categories provide a way to organize and group related abilities for better
- * discoverability and management. Custom categories must be registered before abilities
- * that reference them. Abilities that omit a category are assigned to the built-in
- * `uncategorized` category, which is intended as an escape hatch for simple or transitional
- * registrations.
+ * discoverability and management. Every ability requires a registered category.
+ * Custom categories must be registered before abilities that reference them.
  *
  * Ability categories must be registered on the `wp_abilities_api_categories_init` action hook.
  *
diff --git a/wp-includes/abilities-api/class-wp-abilities-registry.php b/wp-includes/abilities-api/class-wp-abilities-registry.php
index fe41f8e0f6..dc0b30835d 100644
--- a/wp-includes/abilities-api/class-wp-abilities-registry.php
+++ b/wp-includes/abilities-api/class-wp-abilities-registry.php
@@ -41,7 +41,6 @@ final class WP_Abilities_Registry {
 	 *
 	 * @since 6.9.0
 	 * @since 7.1.0 Added the `public` meta argument.
-	 * @since 7.2.0 The `category` argument is now optional and defaults to `uncategorized`.
 	 * @since 7.2.0 Added the `required_capabilities` argument.
 	 *
 	 * @see wp_register_ability()
@@ -54,8 +53,7 @@ final class WP_Abilities_Registry {
 	 *
 	 *     @type string               $label                 The human-readable label for the ability.
 	 *     @type string               $description           A detailed description of what the ability does.
-	 *     @type string               $category              Optional. The ability category slug this ability belongs to.
-	 *                                                       Defaults to `uncategorized`.
+	 *     @type string               $category              The registered ability category slug this ability belongs to.
 	 *     @type callable             $execute_callback      A callback function to execute when the ability is invoked.
 	 *                                                       Receives optional mixed input and returns mixed result or WP_Error.
 	 *     @type callable             $permission_callback   A callback function to check permissions before execution.
@@ -119,7 +117,6 @@ final class WP_Abilities_Registry {
 		 *
 		 * @since 6.9.0
 		 * @since 7.1.0 Added the `public` meta argument.
-		 * @since 7.2.0 The `category` argument is now optional and defaults to `uncategorized`.
 		 * @since 7.2.0 Added the `required_capabilities` argument.
 		 *
 		 * @param array<string, mixed> $args {
@@ -127,8 +124,7 @@ final class WP_Abilities_Registry {
 		 *
 		 *     @type string               $label                 The human-readable label for the ability.
 		 *     @type string               $description           A detailed description of what the ability does.
-		 *     @type string               $category              Optional. The ability category slug this ability belongs to.
-		 *                                                       Defaults to `uncategorized`.
+		 *     @type string               $category              The registered ability category slug this ability belongs to.
 		 *     @type callable             $execute_callback      A callback function to execute when the ability is invoked.
 		 *                                                       Receives optional mixed input and returns mixed result or WP_Error.
 		 *     @type callable             $permission_callback   A callback function to check permissions before execution.
@@ -156,14 +152,10 @@ final class WP_Abilities_Registry {
 		 */
 		$args = apply_filters( 'wp_register_ability_args', $args, $name );

-		if ( ! array_key_exists( 'category', $args ) ) {
-			$args['category'] = 'uncategorized';
-		}
-
-		if ( ! is_string( $args['category'] ) ) {
+		if ( ! isset( $args['category'] ) || ! is_string( $args['category'] ) ) {
 			_doing_it_wrong(
 				__METHOD__,
-				__( 'Ability category must be a string.' ),
+				__( 'The ability properties must contain a `category` string.' ),
 				'6.9.0'
 			);
 			return null;
diff --git a/wp-includes/abilities.php b/wp-includes/abilities.php
index c4489f7e36..835c19e04f 100644
--- a/wp-includes/abilities.php
+++ b/wp-includes/abilities.php
@@ -17,7 +17,7 @@ require_once __DIR__ . '/abilities/class-wp-abilities-users.php';
  * Registers the core ability categories.
  *
  * @since 6.9.0
- * @since 7.2.0 Added the `content` and `uncategorized` categories.
+ * @since 7.2.0 Added the `content` category.
  */
 function wp_register_core_ability_categories(): void {
 	wp_register_ability_category(
@@ -43,14 +43,6 @@ function wp_register_core_ability_categories(): void {
 			'description' => __( 'Abilities that retrieve or manage posts and other content.' ),
 		)
 	);
-
-	wp_register_ability_category(
-		'uncategorized',
-		array(
-			'label'       => __( 'Uncategorized' ),
-			'description' => __( 'Abilities that have not been assigned to a specific category.' ),
-		)
-	);
 }

 /**
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 114b4cddb2..afbcefa7a4 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-beta4-65307';
+$wp_version = '7.2-beta4-65308';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.