Remove the MfgSpecificPing command from Darwin API. (#24139)

* Remove the MfgSpecificPing command from Darwin API.

Except for the backwards-compat shims, of course.

The template refactorings are to reduce repetition and to enable
handling for removal and renaming of commands.

* Fix darwin-framework-tool compile.
diff --git a/.github/workflows/zap_regeneration.yaml b/.github/workflows/zap_regeneration.yaml
index b329059..7db5b25 100644
--- a/.github/workflows/zap_regeneration.yaml
+++ b/.github/workflows/zap_regeneration.yaml
@@ -28,7 +28,7 @@
 
         runs-on: ubuntu-20.04
         container:
-            image: connectedhomeip/chip-build:0.6.23
+            image: connectedhomeip/chip-build:0.6.24
         defaults:
             run:
                 shell: sh
diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml
index d6367a9..d59598b 100644
--- a/.github/workflows/zap_templates.yaml
+++ b/.github/workflows/zap_templates.yaml
@@ -29,7 +29,7 @@
 
         runs-on: ubuntu-20.04
         container:
-            image: connectedhomeip/chip-build:0.6.23
+            image: connectedhomeip/chip-build:0.6.24
         defaults:
             run:
                 shell: sh
diff --git a/examples/darwin-framework-tool/templates/commands.zapt b/examples/darwin-framework-tool/templates/commands.zapt
index 2d39ca2..6a96907 100644
--- a/examples/darwin-framework-tool/templates/commands.zapt
+++ b/examples/darwin-framework-tool/templates/commands.zapt
@@ -21,6 +21,7 @@
 {{> cluster_header}}
 
 {{#chip_cluster_commands}}
+{{#unless (wasRemoved (asUpperCamelCase clusterName preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
 /*
  * Command {{asUpperCamelCase name}}
  */
@@ -87,6 +88,7 @@
     {{/chip_cluster_command_arguments}}
 };
 
+{{/unless}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
@@ -257,7 +259,9 @@
     commands_list clusterCommands = {
         make_unique<ClusterCommand>(Id), //
         {{#chip_cluster_commands}}
+        {{#unless (wasRemoved (asUpperCamelCase clusterName preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
         make_unique<{{asUpperCamelCase clusterName}}{{asUpperCamelCase name}}>(), //
+        {{/unless}}
         {{/chip_cluster_commands}}
         {{#chip_server_cluster_attributes}}
         {{#first}}
diff --git a/examples/darwin-framework-tool/templates/templates.json b/examples/darwin-framework-tool/templates/templates.json
index a571ccb..8fa73b9 100644
--- a/examples/darwin-framework-tool/templates/templates.json
+++ b/examples/darwin-framework-tool/templates/templates.json
@@ -13,7 +13,8 @@
     "resources": {
         "pics-metafile": "../../../src/app/tests/suites/certification/PICS.yaml",
         "certification-metadir": "../../../src/app/tests/suites/certification",
-        "test-metadir": "../../../src/app/tests/suites"
+        "test-metadir": "../../../src/app/tests/suites",
+        "availability-data": "../../../src/darwin/Framework/CHIP/templates/availability.yaml"
     },
     "override": "../../../src/app/zap-templates/common/override.js",
     "partials": [
diff --git a/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt b/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt
index f1060cd..39163d9 100644
--- a/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt
@@ -41,16 +41,26 @@
 }
 
 {{#chip_cluster_commands}}
-{{#*inline "cluster"}}{{asUpperCamelCase parent.name preserveAcronyms=true}}{{/inline}}
-{{#*inline "command"}}{{asUpperCamelCase name preserveAcronyms=true}}{{/inline}}
-{{#*inline "callbackName"}}{{#if hasSpecificResponse}}{{>cluster}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}{{else}}CommandSuccess{{/if}}{{/inline}}
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandImpl"}}
+{{! This is used as the implementation for both the new-name and old-name bits, so check for both here. }}
+{{#unless (and (wasRemoved cluster command=command)
+               (wasRemoved (compatClusterNameRemapping parent.name) command=(compatCommandNameRemapping parent.name name)))}}
+{{#*inline "callbackName"}}{{#if hasSpecificResponse}}{{cluster}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}{{else}}CommandSuccess{{/if}}{{/inline}}
+{{#*inline "paramsType"}}
+{{#if (wasRemoved cluster command=command)}}
+MTR{{compatClusterNameRemapping parent.name}}Cluster{{compatCommandNameRemapping parent.name name}}Params
+{{else}}
+MTR{{cluster}}Cluster{{command}}Params
+{{/if}}
+{{/inline}}
 {{#unless (hasArguments)}}
 - (void){{asLowerCamelCase name}}WithCompletion:({{>command_completion_type command=.}})completion
 {
   [self {{asLowerCamelCase name}}WithParams:nil completion:completion];
 }
 {{/unless}}
-- (void){{asLowerCamelCase name}}WithParams: (MTR{{>cluster}}Cluster{{>command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completion:({{>command_completion_type command=.}})completion
+- (void){{asLowerCamelCase name}}WithParams: ({{> paramsType}} * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completion:({{>command_completion_type command=.}})completion
 {
     // Make a copy of params before we go async.
     params = [params copy];
@@ -100,6 +110,10 @@
     });
     std::move(*bridge).DispatchAction(self.device);
 }
+{{/unless}}
+{{/inline}}
+{{> commandImpl cluster=(asUpperCamelCase parent.name preserveAcronyms=true)
+                command=(asUpperCamelCase name preserveAcronyms=true)}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
@@ -212,13 +226,16 @@
 @implementation MTRBaseCluster{{compatClusterNameRemapping name}} (Deprecated)
 
 {{#chip_cluster_commands}}
-- (void){{asLowerCamelCase name}}WithParams:(MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase name}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandImpl"}}
+{{#unless (wasRemoved cluster command=command)}}
+- (void){{asLowerCamelCase command}}WithParams:(MTR{{cluster}}Cluster{{command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler
 {
   [self {{asLowerCamelCase name}}WithParams:params completion:
     {{#if hasSpecificResponse}}
     ^(MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}Params * _Nullable data, NSError * _Nullable error) {
       // Cast is safe because subclass does not add any selectors.
-      completionHandler(static_cast<MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase responseName}}Params *>(data), error);
+      completionHandler(static_cast<MTR{{cluster}}Cluster{{compatCommandNameRemapping parent.name responseName}}Params *>(data), error);
     }
     {{else}}
     completionHandler
@@ -226,17 +243,20 @@
     ];
 }
 {{#unless (hasArguments)}}
-- (void){{asLowerCamelCase name}}WithCompletionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler
+- (void){{asLowerCamelCase command}}WithCompletionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler
 {
   [self {{asLowerCamelCase name}}WithParams:nil completionHandler:completionHandler];
 }
 {{/unless}}
+{{/unless}}
+{{/inline}}
+{{> commandImpl cluster=(compatClusterNameRemapping parent.name)
+                command=(compatCommandNameRemapping parent.name name)}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
-{{!Backwards compat for now: Treat DeviceTypeList as DeviceList.  That's OK, since this is a deprecated API. }}
-{{#*inline "attribute"}}Attribute{{#if (isStrEqual (asUpperCamelCase parent.name) "Descriptor")}}{{#if (isStrEqual (asUpperCamelCase name) "DeviceTypeList")}}DeviceList{{else}}{{asUpperCamelCase name}}{{/if}}{{else}}{{asUpperCamelCase name}}{{/if}}{{/inline}}
-{{! TODO: We need a better setup for the API_AVALABLE annotations here; this does not scale at all sanely. }}
+{{#if (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) attribute=(compatAttributeNameRemapping parent.name name))}}
+{{#*inline "attribute"}}Attribute{{compatAttributeNameRemapping parent.name name}}{{/inline}}
 - (void)read{{>attribute}}With
 {{~#if_is_fabric_scoped_struct type~}}
   Params:(MTRReadParams * _Nullable)params completionHandler:
@@ -288,6 +308,7 @@
       }];
 }
 {{/if}}
+{{/if}}
 {{/chip_server_cluster_attributes}}
 
 - (nullable instancetype)initWithDevice:(MTRBaseDevice *)device
diff --git a/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt b/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt
index b4ba54f..930091b 100644
--- a/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt
@@ -25,17 +25,22 @@
                                    queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER {{availability (asUpperCamelCase name preserveAcronyms=true) minimalRelease="First major API revamp"}};
 
 {{#chip_cluster_commands}}
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandDecl"}}
+{{#unless (wasRemoved cluster command=command)}}
 /**
  * Command {{name}}
  *
  * {{description}}
  */
-{{#*inline "cluster"}}{{asUpperCamelCase parent.name preserveAcronyms=true}}{{/inline~}}
-{{~#*inline "command"}}{{asUpperCamelCase name preserveAcronyms=true}}{{/inline~}}
-- (void){{asLowerCamelCase name}}WithParams:(MTR{{>cluster}}Cluster{{>command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completion:({{>command_completion_type command=.}})completion {{availability (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) minimalRelease="First major API revamp"}};
+- (void){{asLowerCamelCase name}}WithParams:(MTR{{cluster}}Cluster{{command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completion:({{>command_completion_type command=.}})completion {{availability cluster command=command minimalRelease="First major API revamp"}};
 {{#unless (hasArguments)}}
-- (void){{asLowerCamelCase name}}WithCompletion:({{>command_completion_type command=.}})completion {{availability (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) minimalRelease="First major API revamp"}};
+- (void){{asLowerCamelCase name}}WithCompletion:({{>command_completion_type command=.}})completion {{availability cluster command=command minimalRelease="First major API revamp"}};
 {{/unless}}
+{{/unless}}
+{{/inline}}
+{{> commandDecl cluster=(asUpperCamelCase parent.name preserveAcronyms=true)
+                command=(asUpperCamelCase name preserveAcronyms=true)}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
@@ -117,14 +122,20 @@
                                   queue:(dispatch_queue_t)queue {{availability (compatClusterNameRemapping name) deprecatedRelease="First major API revamp" deprecationMessage="Please use initWithDevice:endpointID:queue:"}};
 
 {{#chip_cluster_commands}}
-{{#if (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name))}}
-- (void){{asLowerCamelCase name}}WithParams:(MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase name}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler
-  {{availability (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name) deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithParams:completion:")}};
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandDecl"}}
+{{#if (and (wasIntroducedBeforeRelease "First major API revamp" cluster command=command)
+           (not (wasRemoved cluster command=command)))}}
+- (void){{asLowerCamelCase command}}WithParams:(MTR{{cluster}}Cluster{{command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params completionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler
+  {{availability cluster command=command deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithParams:completion:")}};
 {{#unless (hasArguments)}}
-- (void){{asLowerCamelCase name}}WithCompletionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler
-  {{availability (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name) deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithCompletion:")}};
+- (void){{asLowerCamelCase command}}WithCompletionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler
+  {{availability cluster command=command deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithCompletion:")}};
 {{/unless}}
 {{/if}}
+{{/inline}}
+{{> commandDecl cluster=(compatClusterNameRemapping parent.name)
+                command=(compatCommandNameRemapping parent.name name)}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
diff --git a/src/darwin/Framework/CHIP/templates/MTRClusterConstants.zapt b/src/darwin/Framework/CHIP/templates/MTRClusterConstants.zapt
index 90032d0..87d783e 100644
--- a/src/darwin/Framework/CHIP/templates/MTRClusterConstants.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRClusterConstants.zapt
@@ -103,22 +103,34 @@
 // Cluster {{compatClusterNameRemapping ../clusterName}} deprecated command id names
 {{/if}}
 {{/first}}
-{{#if (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping ../clusterName) command=(asUpperCamelCase label) isForIds=true)}}
-MTRCluster{{compatClusterNameRemapping ../clusterName}}Command{{asUpperCamelCase label}}ID
-{{availability (compatClusterNameRemapping ../clusterName) command=(asUpperCamelCase label) deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use MTRCommandIDTypeCluster" (asUpperCamelCase ../clusterName preserveAcronyms=true) "Command" (asUpperCamelCase label preserveAcronyms=true) "ID") isForIds=true}}
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandIdDecl"}}
+{{#if (and (wasIntroducedBeforeRelease "First major API revamp" cluster command=command isForIds=true)
+           (not (wasRemoved cluster command=command isForIds=true)))}}
+MTRCluster{{cluster}}Command{{command}}ID
+{{availability cluster command=command deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use MTRCommandIDTypeCluster" (asUpperCamelCase ../clusterName preserveAcronyms=true) "Command" (asUpperCamelCase name preserveAcronyms=true) "ID") isForIds=true}}
 = {{asMEI manufacturerCode code}},
 {{/if}}
+{{/inline}}
+{{> commandIdDecl cluster=(compatClusterNameRemapping ../clusterName)
+                  command=(compatCommandNameRemapping ../clusterName name)}}
 {{#last}}
 
 {{/last}}
 {{/zcl_commands}}
 {{#zcl_commands}}
 {{~#*inline "cluster"}}{{asUpperCamelCase ../clusterName preserveAcronyms=true}}{{/inline~}}
-{{~#*inline "command"}}{{asUpperCamelCase label preserveAcronyms=true}}{{/inline~}}
 {{#first}}
 // Cluster {{>cluster}} commands
 {{/first}}
-MTRCommandIDTypeCluster{{>cluster}}Command{{>command}}ID {{availability (asUpperCamelCase ../clusterName preserveAcronyms=true) command=(asUpperCamelCase label preserveAcronyms=true) minimalRelease="First major API revamp" isForIds=true}} = {{asMEI manufacturerCode code}},
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandIdDecl"}}
+{{#unless (wasRemoved cluster command=command isForIds=true)}}
+MTRCommandIDTypeCluster{{cluster}}Command{{command}}ID {{availability cluster command=command minimalRelease="First major API revamp" isForIds=true}} = {{asMEI manufacturerCode code}},
+{{/unless}}
+{{/inline}}
+{{> commandIdDecl cluster=(asUpperCamelCase ../clusterName preserveAcronyms=true)
+                  command=(asUpperCamelCase name preserveAcronyms=true)}}
 {{#last}}
 
 {{/last}}
diff --git a/src/darwin/Framework/CHIP/templates/MTRClusters-src.zapt b/src/darwin/Framework/CHIP/templates/MTRClusters-src.zapt
index e272793..70ccaf6 100644
--- a/src/darwin/Framework/CHIP/templates/MTRClusters-src.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRClusters-src.zapt
@@ -55,17 +55,42 @@
 }
 
 {{#chip_cluster_commands}}
-{{#*inline "cluster"}}{{asUpperCamelCase parent.name preserveAcronyms=true}}{{/inline}}
-{{#*inline "callbackName"}}{{#if hasSpecificResponse}}{{>cluster}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}{{else}}CommandSuccess{{/if}}{{/inline}}
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandImpl"}}
+{{! This is used as the implementation for both the new-name and old-name bits, so check for both here. }}
+{{#unless (and (wasRemoved cluster command=command)
+               (wasRemoved (compatClusterNameRemapping parent.name) command=(compatCommandNameRemapping parent.name name)))}}
+{{#*inline "callbackName"}}{{#if hasSpecificResponse}}{{cluster}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}{{else}}CommandSuccess{{/if}}{{/inline}}
+{{#*inline "paramsType"}}
+{{#if (wasRemoved cluster command=command)}}
+MTR{{compatClusterNameRemapping parent.name}}Cluster{{compatCommandNameRemapping parent.name name}}Params
+{{else}}
+MTR{{cluster}}Cluster{{command}}Params
+{{/if}}
+{{/inline}}
+{{#*inline "clusterId"}}
+{{#if (wasRemoved cluster command=command)}}
+{{asMEI ../manufacturerCode ../code}}
+{{else}}
+MTRClusterIDType{{cluster}}ID
+{{/if}}
+{{/inline}}
+{{#*inline "commandId"}}
+{{#if (wasRemoved cluster command=command)}}
+{{asMEI manufacturerCode code}}
+{{else}}
+MTRCommandIDTypeCluster{{cluster}}Command{{command}}ID
+{{/if}}
+{{/inline}}
 {{#unless (hasArguments)}}
 - (void){{asLowerCamelCase name}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion
 {
   [self {{asLowerCamelCase name}}WithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion];
 }
 {{/unless}}
-- (void){{asLowerCamelCase name}}WithParams: (MTR{{>cluster}}Cluster{{asUpperCamelCase name preserveAcronyms=true}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion
+- (void){{asLowerCamelCase name}}WithParams: ({{> paramsType}} * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion
 {
-    NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, _endpoint, (unsigned int)MTRClusterIDType{{>cluster}}ID, (unsigned int)MTRCommandIDTypeCluster{{>cluster}}Command{{asUpperCamelCase name preserveAcronyms=true}}ID];
+    NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, _endpoint, (unsigned int){{> clusterId}}, (unsigned int){{> commandId}}];
     // Make a copy of params before we go async.
     params = [params copy];
     NSNumber *timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs;
@@ -137,6 +162,10 @@
       [self.device setExpectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs];
     }
 }
+{{/unless}}
+{{/inline}}
+{{> commandImpl cluster=(asUpperCamelCase parent.name preserveAcronyms=true)
+                command=(asUpperCamelCase name preserveAcronyms=true)}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
@@ -183,13 +212,16 @@
 }
 
 {{#chip_cluster_commands}}
-- (void){{asLowerCamelCase name}}WithParams:(MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase name}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandImpl"}}
+{{#unless (wasRemoved cluster command=command)}}
+- (void){{asLowerCamelCase command}}WithParams:(MTR{{cluster}}Cluster{{command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler
 {
   [self {{asLowerCamelCase name}}WithParams:params expectedValues:expectedDataValueDictionaries expectedValueInterval:expectedValueIntervalMs completion:
       {{#if hasSpecificResponse}}
     ^(MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}Params * _Nullable data, NSError * _Nullable error) {
       // Cast is safe because subclass does not add any selectors.
-      completionHandler(static_cast<MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase responseName}}Params *>(data), error);
+      completionHandler(static_cast<MTR{{cluster}}Cluster{{compatCommandNameRemapping parent.name responseName}}Params *>(data), error);
     }
     {{else}}
     completionHandler
@@ -197,40 +229,36 @@
     ];
 }
 {{#unless (hasArguments)}}
-- (void){{asLowerCamelCase name}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler
+- (void){{asLowerCamelCase command}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler
 {
   [self {{asLowerCamelCase name}}WithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completionHandler:completionHandler];
 }
 {{/unless}}
+{{/unless}}
+{{/inline}}
+{{> commandImpl cluster=(compatClusterNameRemapping parent.name)
+                command=(compatCommandNameRemapping parent.name name)}}
 {{/chip_cluster_commands}}
 {{~#chip_server_cluster_attributes}}
-{{~!Backwards compat for now: Treat DeviceTypeList as DeviceList.  That's OK, since all these bits are deprecated. ~}}
-{{~#*inline "attribute"}}Attribute{{#if (isStrEqual (asUpperCamelCase parent.name) "Descriptor")}}{{#if (isStrEqual (asUpperCamelCase name) "DeviceTypeList")}}DeviceList{{else}}{{asUpperCamelCase name}}{{/if}}{{else}}{{asUpperCamelCase name}}{{/if}}{{/inline~}}
 {{~#*inline "attributeImpls"}}
-- (NSDictionary<NSString *, id> *)read{{>attribute}}WithParams:(MTRReadParams * _Nullable)params
+{{#unless (isStrEqual attribute (asUpperCamelCase name preserveAcronyms=true))}}
+- (NSDictionary<NSString *, id> *)readAttribute{{attribute}}WithParams:(MTRReadParams * _Nullable)params
 {
   return [self readAttribute{{asUpperCamelCase name preserveAcronyms=true}}WithParams:params];
 }
 {{#if isWritableAttribute}}
-- (void)write{{>attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs
+- (void)writeAttribute{{attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs
 {
   [self writeAttribute{{asUpperCamelCase name preserveAcronyms=true}}WithValue:dataValueDictionary expectedValueInterval:expectedValueIntervalMs];
 }
-- (void)write{{>attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params
+- (void)writeAttribute{{attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params
 {
   [self writeAttribute{{asUpperCamelCase name preserveAcronyms=true}}WithValue:dataValueDictionary expectedValueInterval:expectedValueIntervalMs params:params];
 }
 {{/if}}
+{{/unless}}
 {{/inline~}}
-{{#if (isStrEqual (asUpperCamelCase name preserveAcronyms=true) (asUpperCamelCase name))}}
-  {{#if (isStrEqual (asUpperCamelCase parent.name preserveAcronyms=true) "Descriptor")}}
-    {{#if (isStrEqual (asUpperCamelCase name preserveAcronyms=true) "DeviceTypeList")}}
-      {{> attributeImpls}}
-    {{/if}}
-  {{/if}}
-{{else}}
-  {{> attributeImpls}}
-{{/if}}
+{{> attributeImpls attribute=(compatAttributeNameRemapping parent.name name)}}
 {{/chip_server_cluster_attributes}}
 @end
 
diff --git a/src/darwin/Framework/CHIP/templates/MTRClusters.zapt b/src/darwin/Framework/CHIP/templates/MTRClusters.zapt
index c3c9b29..eeda4eb 100644
--- a/src/darwin/Framework/CHIP/templates/MTRClusters.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRClusters.zapt
@@ -24,12 +24,17 @@
                                    queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER {{availability (asUpperCamelCase name preserveAcronyms=true) minimalRelease="First major API revamp"}};
 
 {{#chip_cluster_commands}}
-{{~#*inline "cluster"}}{{asUpperCamelCase parent.name preserveAcronyms=true}}{{/inline~}}
-{{~#*inline "command"}}{{asUpperCamelCase name preserveAcronyms=true}}{{/inline~}}
-- (void){{asLowerCamelCase name}}WithParams:(MTR{{>cluster}}Cluster{{>command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion {{availability (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) minimalRelease="First major API revamp"}};
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandDecl"}}
+{{#unless (wasRemoved cluster command=command)}}
+- (void){{asLowerCamelCase name}}WithParams:(MTR{{cluster}}Cluster{{command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion {{availability cluster command=command minimalRelease="First major API revamp"}};
 {{#unless (hasArguments)}}
-- (void){{asLowerCamelCase name}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion {{availability (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) minimalRelease="First major API revamp"}};
+- (void){{asLowerCamelCase name}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion {{availability cluster command=command minimalRelease="First major API revamp"}};
 {{/unless}}
+{{/unless}}
+{{/inline}}
+{{> commandDecl cluster=(asUpperCamelCase parent.name preserveAcronyms=true)
+                command=(asUpperCamelCase name preserveAcronyms=true)}}
 {{/chip_cluster_commands}}
 
 {{#chip_server_cluster_attributes}}
@@ -69,25 +74,31 @@
                                   queue:(dispatch_queue_t)queue {{availability (compatClusterNameRemapping name) deprecatedRelease="First major API revamp" deprecationMessage="Please use initWithDevice:endpoindID:queue:"}};
 
 {{#chip_cluster_commands}}
-{{#if (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name))}}
-- (void){{asLowerCamelCase name}}WithParams:(MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase name}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler {{availability (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name) deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithParams:expectedValues:expectedValueIntervalMs:completion:")}};
+{{! Takes two arguments: cluster name and command name, plus the ambient state where the command is "this" }}
+{{#*inline "commandDecl"}}
+{{#if (and (wasIntroducedBeforeRelease "First major API revamp" cluster command=command)
+           (not (wasRemoved cluster command=command)))}}
+- (void){{asLowerCamelCase command}}WithParams:(MTR{{cluster}}Cluster{{command}}Params * {{#unless (commandHasRequiredField .)}}_Nullable{{/unless}})params expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler {{availability cluster command=command deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithParams:expectedValues:expectedValueIntervalMs:completion:")}};
 {{#unless (hasArguments)}}
-- (void){{asLowerCamelCase name}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapClusterName=true}})completionHandler {{availability (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name) deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithExpectedValues:expectedValueIntervalMs:completion:")}};
+- (void){{asLowerCamelCase command}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completionHandler:({{>command_completion_type command=. compatRemapNames=true}})completionHandler {{availability cluster command=command deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use " (asLowerCamelCase name) "WithExpectedValues:expectedValueIntervalMs:completion:")}};
 {{/unless}}
 {{/if}}
+{{/inline}}
+{{> commandDecl cluster=(compatClusterNameRemapping parent.name)
+                command=(compatCommandNameRemapping parent.name name)}}
 {{/chip_cluster_commands}}
 {{~#chip_server_cluster_attributes}}
-{{~#*inline "attribute"}}Attribute{{compatAttributeNameRemapping parent.name name}}{{/inline~}}
 {{~#*inline "attributeDecls"}}
-- (NSDictionary<NSString *, id> *)read{{>attribute}}WithParams:(MTRReadParams * _Nullable)params {{availability (compatClusterNameRemapping parent.name) attribute=(compatAttributeNameRemapping parent.name name) deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use readAttribute" (asUpperCamelCase name preserveAcronyms=true) "WithParams on MTRCluster" (asUpperCamelCase parent.name preserveAcronyms=true))}};
+{{#unless (isStrEqual attribute (asUpperCamelCase name preserveAcronyms=true))}}
+- (NSDictionary<NSString *, id> *)readAttribute{{attribute}}WithParams:(MTRReadParams * _Nullable)params {{availability cluster attribute=attribute deprecatedRelease="First major API revamp" deprecationMessage=(concat "Please use readAttribute" (asUpperCamelCase name preserveAcronyms=true) "WithParams on MTRCluster" (asUpperCamelCase parent.name preserveAcronyms=true))}};
 {{#if isWritableAttribute}}
-- (void)write{{>attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs {{availability (compatClusterNameRemapping parent.name) attribute=(compatAttributeNameRemapping parent.name name) deprecationMessage=(concat "Please use writeAttribute" (asUpperCamelCase name preserveAcronyms=true) "WithValue on MTRCluster" (asUpperCamelCase parent.name preserveAcronyms=true))}};
-- (void)write{{>attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params {{availability (compatClusterNameRemapping parent.name) attribute=(compatAttributeNameRemapping parent.name name) deprecationMessage=(concat "Please use writeAttribute" (asUpperCamelCase name preserveAcronyms=true) "WithValue on MTRCluster" (asUpperCamelCase parent.name preserveAcronyms=true))}};
+- (void)writeAttribute{{attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs {{availability cluster attribute=attribute deprecationMessage=(concat "Please use writeAttribute" (asUpperCamelCase name preserveAcronyms=true) "WithValue on MTRCluster" (asUpperCamelCase parent.name preserveAcronyms=true))}};
+- (void)writeAttribute{{attribute}}WithValue:(NSDictionary<NSString *, id> *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params {{availability cluster attribute=attribute deprecationMessage=(concat "Please use writeAttribute" (asUpperCamelCase name preserveAcronyms=true) "WithValue on MTRCluster" (asUpperCamelCase parent.name preserveAcronyms=true))}};
 {{/if}}
-{{/inline~}}
-{{#unless (isStrEqual (asUpperCamelCase name preserveAcronyms=true) (compatAttributeNameRemapping parent.name name))}}
-  {{> attributeDecls}}
 {{/unless}}
+{{/inline~}}
+{{> attributeDecls cluster=(compatClusterNameRemapping parent.name)
+                   attribute=(compatAttributeNameRemapping parent.name name)}}
 {{/chip_server_cluster_attributes}}
 @end
 
diff --git a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt
index c2d4fe1..a52a37c 100644
--- a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt
@@ -6,7 +6,9 @@
 
 {{#zcl_clusters}}
 {{#zcl_commands}}
-@implementation MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}}Params
+{{#*inline "completeImpl"}}
+{{#unless (wasRemoved cluster command=command)}}
+@implementation MTR{{cluster}}Cluster{{command}}Params
 - (instancetype)init
 {
   if (self = [super init]) {
@@ -14,19 +16,25 @@
 
     {{>init_struct_member label=label type=type cluster=parent.parent.name}}
 {{/zcl_command_arguments}}
+{{#if (or (isStrEqual source "client")
+          (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) command=(compatCommandNameRemapping parent.name name)))}}
     _timedInvokeTimeoutMs = nil;
+{{/if}}
   }
   return self;
 }
 
 - (id)copyWithZone:(NSZone * _Nullable)zone;
 {
-  auto other = [[MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}}Params alloc] init];
+  auto other = [[MTR{{cluster}}Cluster{{command}}Params alloc] init];
 
   {{#zcl_command_arguments}}
   other.{{asStructPropertyName label}} = self.{{asStructPropertyName label}};
   {{/zcl_command_arguments}}
+{{#if (or (isStrEqual source "client")
+          (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) command=(compatCommandNameRemapping parent.name name)))}}
   other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs;
+{{/if}}
 
   return other;
 }
@@ -38,18 +46,25 @@
 }
 
 @end
-{{#*inline "deprecatedImpl"}}
+{{/unless}}
+{{/inline}}
+{{#*inline "oldNameImpl"}}
 
-@implementation MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase name}}Params
+@implementation MTR{{cluster}}Cluster{{command}}Params
 @end
 {{/inline}}
-{{#unless (isStrEqual (asUpperCamelCase parent.name preserveAcronyms=true) (compatClusterNameRemapping parent.name))}}
-{{> deprecatedImpl}}
+{{#if (not (wasRemoved (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true)))}}
+{{> completeImpl cluster=(asUpperCamelCase parent.name preserveAcronyms=true)
+                 command=(asUpperCamelCase name preserveAcronyms=true)}}
+{{#if (or (not (isStrEqual (asUpperCamelCase parent.name preserveAcronyms=true) (compatClusterNameRemapping parent.name)))
+          (not (isStrEqual (asUpperCamelCase name preserveAcronyms=true) (compatCommandNameRemapping parent.name name))))}}
+{{> oldNameImpl cluster=(compatClusterNameRemapping parent.name)
+                command=(compatCommandNameRemapping parent.name name)}}
+{{/if}}
 {{else}}
-{{#unless (isStrEqual (asUpperCamelCase name preserveAcronyms=true) (asUpperCamelCase name))}}
-{{> deprecatedImpl}}
-{{/unless}}
-{{/unless}}
+{{> completeImpl cluster=(compatClusterNameRemapping parent.name)
+                 command=(compatCommandNameRemapping parent.name name)}}
+{{/if}}
 {{/zcl_commands}}
 {{/zcl_clusters}}
 
diff --git a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc.zapt b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc.zapt
index d56d2ff..1143ec4 100644
--- a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc.zapt
+++ b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc.zapt
@@ -7,14 +7,16 @@
 
 {{#zcl_clusters}}
 {{#zcl_commands}}
+{{#*inline "completeDecl"}}
+{{#unless (wasRemoved cluster command=command)}}
 
-{{availability (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) isForCommandPayload=true}}
-@interface MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}}Params : NSObject <NSCopying>
+{{availability cluster command=command isForCommandPayload=true deprecationMessage="This command has been removed"}}
+@interface MTR{{cluster}}Cluster{{command}}Params : NSObject <NSCopying>
 {{#zcl_command_arguments}}
 
 {{! Override the getter name because some of our properties start with things
     like "new" or "init" }}
-@property (nonatomic, copy{{#unless (isStrEqual (asGetterName label) (asStructPropertyName label))}}, getter={{asGetterName label}}{{/unless}}) {{asObjectiveCType type parent.parent.name}} {{asStructPropertyName label}} {{availability (asUpperCamelCase ../../name preserveAcronyms=true) command=(asUpperCamelCase ../name preserveAcronyms=true) commandField=(asStructPropertyName label)}};
+@property (nonatomic, copy{{#unless (isStrEqual (asGetterName label) (asStructPropertyName label))}}, getter={{asGetterName label}}{{/unless}}) {{asObjectiveCType type parent.parent.name}} {{asStructPropertyName label}} {{availability ../cluster command=../command commandField=(asStructPropertyName label)}};
 {{/zcl_command_arguments}}
 {{#if (isStrEqual source "client")}}
 /**
@@ -34,7 +36,7 @@
 @property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs;
 {{! This is using the pre-renaming names for the isAvailableBefore test, because the pre-rename things inherit
     from the post-rename ones and need to have this selector.}}
-{{else if (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name))}}
+{{else if (wasIntroducedBeforeRelease "First major API revamp" (compatClusterNameRemapping parent.name) command=(compatCommandNameRemapping parent.name name))}}
 /**
  * Controls whether the command is a timed command (using Timed Invoke).
  *
@@ -52,20 +54,27 @@
 @property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs {{availability "" api="Timed Invoke for server to client commands" deprecationMessage="Timed invoke does not make sense for server to client commands"}};
 {{/if}}
 @end
-{{#*inline "deprecatedDecl"}}
+{{/unless}}
+{{/inline}}
+{{#*inline "oldNameDecl"}}
 
-{{availability (compatClusterNameRemapping parent.name) command=(asUpperCamelCase name) deprecationMessage=(concat "Please use MTR" (asUpperCamelCase parent.name preserveAcronyms=true) "Cluster" (asUpperCamelCase name preserveAcronyms=true) "Params")}}
-@interface MTR{{compatClusterNameRemapping parent.name}}Cluster{{asUpperCamelCase name}}Params : MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name}}Params
+{{availability cluster command=command deprecationMessage=(concat "Please use MTR" (asUpperCamelCase parent.name preserveAcronyms=true) "Cluster" (asUpperCamelCase name preserveAcronyms=true) "Params")}}
+@interface MTR{{cluster}}Cluster{{command}}Params : MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name}}Params
 @end
 
 {{/inline}}
-{{#unless (isStrEqual (asUpperCamelCase parent.name preserveAcronyms=true) (compatClusterNameRemapping parent.name))}}
-{{> deprecatedDecl}}
+{{#if (not (wasRemoved (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true)))}}
+{{> completeDecl cluster=(asUpperCamelCase parent.name preserveAcronyms=true)
+                 command=(asUpperCamelCase name preserveAcronyms=true)}}
+{{#if (or (not (isStrEqual (asUpperCamelCase parent.name preserveAcronyms=true) (compatClusterNameRemapping parent.name)))
+          (not (isStrEqual (asUpperCamelCase name preserveAcronyms=true) (compatCommandNameRemapping parent.name name))))}}
+{{> oldNameDecl cluster=(compatClusterNameRemapping parent.name)
+                command=(compatCommandNameRemapping parent.name name)}}
+{{/if}}
 {{else}}
-{{#unless (isStrEqual (asUpperCamelCase name preserveAcronyms=true) (asUpperCamelCase name))}}
-{{> deprecatedDecl}}
-{{/unless}}
-{{/unless}}
+{{> completeDecl cluster=(compatClusterNameRemapping parent.name)
+                 command=(compatCommandNameRemapping parent.name name)}}
+{{/if}}
 {{/zcl_commands}}
 {{/zcl_clusters}}
 
diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml
index 71c0db1..003b30f 100644
--- a/src/darwin/Framework/CHIP/templates/availability.yaml
+++ b/src/darwin/Framework/CHIP/templates/availability.yaml
@@ -38,9 +38,19 @@
 #            introduced/deprecated, not the construct itself.
 #   * "global attributes": An array of names of global attributes.
 #   * "apis": An array of API labels that codegen can use.
-#   * "renames": Can contain clusters, attributes, etc as described above, with
-#                the one difference that instead of an array the value is a hash
-#                with new names as keys and old names as values.
+#
+# * "renames": Can contain clusters, attributes, etc as described
+#              above for "introduced" and "deprecated", with the one
+#              difference that instead of an array the value is a hash
+#              with new names as keys and old names as values.
+#
+# * "removed": Can contain clusters, commands, attributes, etc as described
+#              above for "introduced" and "deprecated".  Items can be removed
+#              without ever being introduced, if they are added to the XML but
+#              we have never shipped generated APIs for them.
+#              NOTE: support for "removed" may not be complete in the templates.
+#              Please examine codegen carefully when using "removed" to make
+#              sure all the things that should have been removed have been.
 
 - release: "Initial release"
   versions:
@@ -4748,9 +4758,6 @@
           ClientMonitoring:
               - RegisterClientMonitoring
               - StayAwakeRequest
-          BasicInformation:
-              # TODO: Can we avoid generating this??
-              - MfgSpecificPing
       command fields:
           UnitTesting:
               TestSpecificResponse:
@@ -5152,6 +5159,10 @@
       apis:
           - Timed Invoke for server to client commands
           - Deprecated global attribute names
+  removed:
+      commands:
+          BasicInformation:
+              - MfgSpecificPing
   renames:
       clusters:
           UnitTesting: TestCluster
diff --git a/src/darwin/Framework/CHIP/templates/partials/command_completion_type.zapt b/src/darwin/Framework/CHIP/templates/partials/command_completion_type.zapt
index 6616a32..8270795 100644
--- a/src/darwin/Framework/CHIP/templates/partials/command_completion_type.zapt
+++ b/src/darwin/Framework/CHIP/templates/partials/command_completion_type.zapt
@@ -1,12 +1,19 @@
 {{#if command.hasSpecificResponse}}
 {{#*inline "clusterName"}}
-{{~#if compatRemapClusterName~}}
+{{~#if compatRemapNames~}}
 {{compatClusterNameRemapping command.parent.name}}
 {{~else~}}
 {{asUpperCamelCase command.parent.name preserveAcronyms=true}}
 {{~/if~}}
 {{/inline}}
-void (^)(MTR{{> clusterName}}Cluster{{asUpperCamelCase command.responseName}}Params * _Nullable data, NSError * _Nullable error)
+{{#*inline "responseName"}}
+{{~#if compatRemapNames~}}
+{{compatCommandNameRemapping command.parent.name command.responseName}}
+{{~else~}}
+{{asUpperCamelCase command.responseName preserveAcronyms=true}}
+{{~/if~}}
+{{/inline}}
+void (^)(MTR{{> clusterName}}Cluster{{> responseName}}Params * _Nullable data, NSError * _Nullable error)
 {{else}}
 MTRStatusCompletion
 {{/if}}
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
index 49696ea..eabcb97 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
@@ -1967,15 +1967,6 @@
                               endpointID:(NSNumber *)endpointID
                                    queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER MTR_NEWLY_AVAILABLE;
 
-/**
- * Command MfgSpecificPing
- *
- *
- */
-- (void)mfgSpecificPingWithParams:(MTRBasicInformationClusterMfgSpecificPingParams * _Nullable)params
-                       completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
-- (void)mfgSpecificPingWithCompletion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
-
 - (void)readAttributeDataModelRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
     MTR_NEWLY_AVAILABLE;
 - (void)subscribeAttributeDataModelRevisionWithParams:(MTRSubscribeParams *)params
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
index eb8b4ba..e71dfa0 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
@@ -12741,7 +12741,7 @@
 {
     [self mfgSpecificPingWithParams:nil completion:completion];
 }
-- (void)mfgSpecificPingWithParams:(MTRBasicInformationClusterMfgSpecificPingParams * _Nullable)params
+- (void)mfgSpecificPingWithParams:(MTRBasicClusterMfgSpecificPingParams * _Nullable)params
                        completion:(MTRStatusCompletion)completion
 {
     // Make a copy of params before we go async.
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
index c9c92bd..495b63a 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
@@ -5859,7 +5859,6 @@
     = 0x10020000,
 
     // Cluster BasicInformation commands
-    MTRCommandIDTypeClusterBasicInformationCommandMfgSpecificPingID MTR_NEWLY_AVAILABLE = 0x10020000,
 
     // Cluster OtaSoftwareUpdateProvider deprecated command id names
     MTRClusterOtaSoftwareUpdateProviderCommandQueryImageID API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
index feef92f..17144eb 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
@@ -895,14 +895,6 @@
                               endpointID:(NSNumber *)endpointID
                                    queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER MTR_NEWLY_AVAILABLE;
 
-- (void)mfgSpecificPingWithParams:(MTRBasicInformationClusterMfgSpecificPingParams * _Nullable)params
-                   expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries
-            expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs
-                       completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
-- (void)mfgSpecificPingWithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues
-                    expectedValueInterval:(NSNumber *)expectedValueIntervalMs
-                               completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
-
 - (NSDictionary<NSString *, id> *)readAttributeDataModelRevisionWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE;
 
 - (NSDictionary<NSString *, id> *)readAttributeVendorNameWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE;
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
index 22ab7d9..5db9b7b 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
@@ -5135,14 +5135,13 @@
               expectedValueInterval:expectedValueIntervalMs
                          completion:completion];
 }
-- (void)mfgSpecificPingWithParams:(MTRBasicInformationClusterMfgSpecificPingParams * _Nullable)params
+- (void)mfgSpecificPingWithParams:(MTRBasicClusterMfgSpecificPingParams * _Nullable)params
                    expectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues
             expectedValueInterval:(NSNumber *)expectedValueIntervalMs
                        completion:(MTRStatusCompletion)completion
 {
     NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex,
-                                     _endpoint, (unsigned int) MTRClusterIDTypeBasicInformationID,
-                                     (unsigned int) MTRCommandIDTypeClusterBasicInformationCommandMfgSpecificPingID];
+                                     _endpoint, (unsigned int) 0x00000028, (unsigned int) 0x10020000];
     // Make a copy of params before we go async.
     params = [params copy];
     NSNumber * timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs;
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h
index 8313f85..60c09f8 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h
@@ -1425,8 +1425,9 @@
 @property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs;
 @end
 
-MTR_NEWLY_AVAILABLE
-@interface MTRBasicInformationClusterMfgSpecificPingParams : NSObject <NSCopying>
+API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
+MTR_NEWLY_DEPRECATED("This command has been removed")
+@interface MTRBasicClusterMfgSpecificPingParams : NSObject <NSCopying>
 /**
  * Controls whether the command is a timed command (using Timed Invoke).
  *
@@ -1444,11 +1445,6 @@
 @property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs;
 @end
 
-API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
-MTR_NEWLY_DEPRECATED("Please use MTRBasicInformationClusterMfgSpecificPingParams")
-@interface MTRBasicClusterMfgSpecificPingParams : MTRBasicInformationClusterMfgSpecificPingParams
-@end
-
 MTR_NEWLY_AVAILABLE
 @interface MTROTASoftwareUpdateProviderClusterQueryImageParams : NSObject <NSCopying>
 
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm
index 6bb138c..0f925b1 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm
@@ -1960,7 +1960,7 @@
 }
 
 @end
-@implementation MTRBasicInformationClusterMfgSpecificPingParams
+@implementation MTRBasicClusterMfgSpecificPingParams
 - (instancetype)init
 {
     if (self = [super init]) {
@@ -1971,7 +1971,7 @@
 
 - (id)copyWithZone:(NSZone * _Nullable)zone;
 {
-    auto other = [[MTRBasicInformationClusterMfgSpecificPingParams alloc] init];
+    auto other = [[MTRBasicClusterMfgSpecificPingParams alloc] init];
 
     other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs;
 
@@ -1985,9 +1985,6 @@
 }
 
 @end
-
-@implementation MTRBasicClusterMfgSpecificPingParams
-@end
 @implementation MTROTASoftwareUpdateProviderClusterQueryImageParams
 - (instancetype)init
 {
diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
index 86ad518..9342937 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
+++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
@@ -10965,49 +10965,6 @@
 \*----------------------------------------------------------------------------*/
 
 /*
- * Command MfgSpecificPing
- */
-class BasicInformationMfgSpecificPing : public ClusterCommand {
-public:
-    BasicInformationMfgSpecificPing()
-        : ClusterCommand("mfg-specific-ping")
-    {
-        ClusterCommand::AddArguments();
-    }
-
-    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
-    {
-        ChipLogProgress(chipTool, "Sending cluster (0x00000028) command (0x00000000) on endpoint %u", endpointId);
-
-        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
-        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
-                                                                            endpointID:@(endpointId)
-                                                                                 queue:callbackQueue];
-        __auto_type * params = [[MTRBasicInformationClusterMfgSpecificPingParams alloc] init];
-        params.timedInvokeTimeoutMs
-            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
-        uint16_t repeatCount = mRepeatCount.ValueOr(1);
-        uint16_t __block responsesNeeded = repeatCount;
-        while (repeatCount--) {
-            [cluster mfgSpecificPingWithParams:params
-                                    completion:^(NSError * _Nullable error) {
-                                        responsesNeeded--;
-                                        if (error != nil) {
-                                            mError = error;
-                                            LogNSError("Error", error);
-                                        }
-                                        if (responsesNeeded == 0) {
-                                            SetCommandExitStatus(mError);
-                                        }
-                                    }];
-        }
-        return CHIP_NO_ERROR;
-    }
-
-private:
-};
-
-/*
  * Attribute DataModelRevision
  */
 class ReadBasicInformationDataModelRevision : public ReadAttribute {
@@ -97929,7 +97886,6 @@
 
     commands_list clusterCommands = {
         make_unique<ClusterCommand>(Id), //
-        make_unique<BasicInformationMfgSpecificPing>(), //
         make_unique<ReadAttribute>(Id), //
         make_unique<ReadBasicInformationDataModelRevision>(), //
         make_unique<WriteAttribute>(Id), //