Repository: Qiskit/qiskit

Issue:
`BlueprintCircuit` subclasses rebuild out-of-order after `_append`
### Environment

- **Qiskit Terra version**: 0.25.3
- **Python version**: 3.10
- **Operating system**: macOS


### What is happening?

Subclasses of `BlueprintCircuit` do not behave correctly when the inner-loop `_append` method is used; the circuit is not rebuilt prior to accepting the append.

### How can we reproduce the issue?

```python
from qiskit.circuit.library import RealAmplitudes, XGate
from qiskit.circuit import CircuitInstruction, ClassicalRegister

qc = RealAmplitudes(num_qubits=2, reps=2)
qc.add_register(ClassicalRegister(2, "meas"))
qc._append(CircuitInstruction(XGate(), (qc.qubits[0],), ()))
qc.draw()
```
gives
```
        ┌───┐┌────────────────────────────────────────────────┐
   q_0: ┤ X ├┤0                                               ├
        └───┘│  RealAmplitudes(θ[0],θ[1],θ[2],θ[3],θ[4],θ[5]) │
   q_1: ─────┤1                                               ├
             └────────────────────────────────────────────────┘
meas: 2/═══════════════════════════════════════════════════════
```

whereas using `QuantumCircuit.append` gives the expected:
```python
from qiskit.circuit.library import RealAmplitudes, XGate
from qiskit.circuit import CircuitInstruction, ClassicalRegister

qc = RealAmplitudes(num_qubits=2, reps=2)
qc.add_register(ClassicalRegister(2, "meas"))
qc.append(XGate(), [qc.qubits[0]])
qc.draw()
```
```
        ┌────────────────────────────────────────────────┐┌───┐
   q_0: ┤0                                               ├┤ X ├
        │  RealAmplitudes(θ[0],θ[1],θ[2],θ[3],θ[4],θ[5]) │└───┘
   q_1: ┤1                                               ├─────
        └────────────────────────────────────────────────┘
meas: 2/═══════════════════════════════════════════════════════
```

### What should happen?

Inner `_append` should handle enforcing the build, not `append`.

### Any suggestions?

_No response_


Discussion:

Resolving patch:
diff --git a/qiskit/circuit/library/blueprintcircuit.py b/qiskit/circuit/library/blueprintcircuit.py
--- a/qiskit/circuit/library/blueprintcircuit.py
+++ b/qiskit/circuit/library/blueprintcircuit.py
@@ -119,10 +119,10 @@ def qasm(self, formatted=False, filename=None, encoding=None):
             self._build()
         return super().qasm(formatted, filename, encoding)
 
-    def append(self, instruction, qargs=None, cargs=None):
+    def _append(self, instruction, _qargs=None, _cargs=None):
         if not self._is_built:
             self._build()
-        return super().append(instruction, qargs, cargs)
+        return super()._append(instruction, _qargs, _cargs)
 
     def compose(self, other, qubits=None, clbits=None, front=False, inplace=False, wrap=False):
         if not self._is_built:


Test patch:
diff --git a/test/python/circuit/library/test_blueprintcircuit.py b/test/python/circuit/library/test_blueprintcircuit.py
--- a/test/python/circuit/library/test_blueprintcircuit.py
+++ b/test/python/circuit/library/test_blueprintcircuit.py
@@ -16,8 +16,15 @@
 from ddt import ddt, data
 
 from qiskit.test.base import QiskitTestCase
-from qiskit.circuit import QuantumRegister, Parameter, QuantumCircuit, Gate, Instruction
-from qiskit.circuit.library import BlueprintCircuit
+from qiskit.circuit import (
+    QuantumRegister,
+    Parameter,
+    QuantumCircuit,
+    Gate,
+    Instruction,
+    CircuitInstruction,
+)
+from qiskit.circuit.library import BlueprintCircuit, XGate
 
 
 class MockBlueprint(BlueprintCircuit):
@@ -139,6 +146,34 @@ def test_to_gate_and_instruction(self, method):
             gate = circuit.to_instruction()
             self.assertIsInstance(gate, Instruction)
 
+    def test_build_before_appends(self):
+        """Test that both forms of direct append (public and semi-public) function correctly."""
+
+        class DummyBlueprint(BlueprintCircuit):
+            """Dummy circuit."""
+
+            def _check_configuration(self, raise_on_failure=True):
+                return True
+
+            def _build(self):
+                super()._build()
+                self.z(0)
+
+        expected = QuantumCircuit(2)
+        expected.z(0)
+        expected.x(0)
+
+        qr = QuantumRegister(2, "q")
+        mock = DummyBlueprint()
+        mock.add_register(qr)
+        mock.append(XGate(), [qr[0]], [])
+        self.assertEqual(expected, mock)
+
+        mock = DummyBlueprint()
+        mock.add_register(qr)
+        mock._append(CircuitInstruction(XGate(), (qr[0],), ()))
+        self.assertEqual(expected, mock)
+
 
 if __name__ == "__main__":
     unittest.main()