task: metadata: install: pip install -e .[test]
patch: diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst
index 0102869..2ecec4b 100644
--- a/docs/versionhistory.rst
+++ b/docs/versionhistory.rst
@@ -10,14 +10,19 @@ This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
   portals
 - Added ``__slots__`` to ``AsyncResource`` so that child classes can use ``__slots__``
   (`#733 <https://github.com/agronholm/anyio/pull/733>`_; PR by Justin Su)
+- Fixed two bugs with ``TaskGroup.start()`` on asyncio:
+
+  * Fixed erroneous ``RuntimeError: called 'started' twice on the same task status``
+    when cancelling a task in a TaskGroup created with the ``start()`` method before
+    the first checkpoint is reached after calling ``task_status.started()``
+    (`#706 <https://github.com/agronholm/anyio/issues/706>`_; PR by Dominik Schwabe)
+  * Fixed the entire task group being cancelled if a ``TaskGroup.start()`` call gets
+    cancelled (`#685 <https://github.com/agronholm/anyio/issues/685>`_,
+    `#710 <https://github.com/agronholm/anyio/issues/710>`_)
 - Fixed a race condition that caused crashes when multiple event loops of the same
   backend were running in separate threads and simultaneously attempted to use AnyIO for
   their first time (`#425 <https://github.com/agronholm/anyio/issues/425>`_; PR by David
   Jiricek and Ganden Schaffner)
-- Fixed erroneous ``RuntimeError: called 'started' twice on the same task status``
-  when cancelling a task in a TaskGroup created with the ``start()`` method before
-  the first checkpoint is reached after calling ``task_status.started()``
-  (`#706 <https://github.com/agronholm/anyio/issues/706>`_; PR by Dominik Schwabe)
 - Fixed cancellation delivery on asyncio incrementing the wrong cancel scope's
   cancellation counter when cascading a cancel operation to a child scope, thus failing
   to uncancel the host task (`#716 <https://github.com/agronholm/anyio/issues/716>`_)
diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py
index ecd865a..b69665c 100644
--- a/src/anyio/_backends/_asyncio.py
+++ b/src/anyio/_backends/_asyncio.py
@@ -714,6 +714,12 @@ class TaskGroup(abc.TaskGroup):
                 exc = e
 
             if exc is not None:
+                # The future can only be in the cancelled state if the host task was
+                # cancelled, so return immediately instead of adding one more
+                # CancelledError to the exceptions list
+                if task_status_future is not None and task_status_future.cancelled():
+                    return
+
                 if task_status_future is None or task_status_future.done():
                     if not isinstance(exc, CancelledError):
                         self._exceptions.append(exc)

problem_statement: Cancelling a TaskGroup in which a task is starting all also cancel the TaskGroup in which it is due to run
### Things to check first

- [X] I have searched the existing issues and didn't find my bug already reported there

- [X] I have checked that my bug is still present in the latest release


### AnyIO version

4.2

### Python version

3.10.13

### What happened?

This is related to, but slightly different from, issue #517 

Consider this sequence of steps with anyio (asyncio backend) in this way:

1. I start an outer TaskGroup
2. Within that, I start an inner TaskGroup
3. I start a task in the inner TaskGroup, due to run in the outer TaskGroup (e.g., calling `await outer_tg.start(foo)` in the context of the inner TaskGroup)
4. Before the routine calls `task_status.started()` and gets reparented to the outer TaskGroup, cancel the inner task group (and therefore this partially started task).

If you do all that, then the outer TaskGroup will be cancelled as well, including any other tasks that were running in it. Somehow the partially started task has leaked the cancellation from one TaskGroup to the other.

### How can we reproduce the bug?

One example of how this would look:

```python
async def issue_demo1():
    async with anyio.create_task_group() as run_tg:
        run_tg.start_soon(sleep_only)
        async with anyio.create_task_group() as start_tg:
            start_tg.start_soon(run_tg.start, sleep_twice)
            start_tg.cancel_scope.cancel()
```

If using `TaskGroup.start_soon()` on `TaskGroup.start()` looks a bit suspicious, another way would be to do cancellation in the background, for example with a time out:

```python
async def issue_demo2():
    async with anyio.create_task_group() as run_tg:
        run_tg.start_soon(sleep_only)
        async with anyio.create_task_group() as start_tg:
            start_tg.cancel_scope.deadline = anyio.current_time() + 0.5
            await run_tg.start(sleep_twice)
```

Here are definitions of the coroutines used in the examples:

```python
async def sleep_twice(task_status=anyio.TASK_STATUS_IGNORED):
    try:
        print("sleep_twice(): at beginning")
        await anyio.sleep(1)
        task_status.started()
        print("sleep_twice(): started() called")
        await anyio.sleep(1)
        print("sleep_twice(): completed")
    except BaseException as be:
        print(f"sleep_twice(): got exception {be!r}")
        raise

async def sleep_only():
    try:
        print("sleep_only(): at beginning")
        await anyio.sleep(100)
        print("sleep_only(): completed")
    except BaseException as be:
        print(f"sleep_only(): got exception {be!r}")
        raise
```

Here is an example output:

```
sleep_only(): at beginning
sleep_twice(): at beginning
sleep_twice(): got exception CancelledError()
sleep_only(): got exception CancelledError('Cancelled by cancel scope 27ba061c850')
```

repo: agronholm/anyio
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_taskgroups.py b/tests/test_taskgroups.py
index da84f65..11329df 100644
--- a/tests/test_taskgroups.py
+++ b/tests/test_taskgroups.py
@@ -22,6 +22,7 @@ from anyio import (
     get_current_task,
     move_on_after,
     sleep,
+    sleep_forever,
     wait_all_tasks_blocked,
 )
 from anyio.abc import TaskGroup, TaskStatus
@@ -127,7 +128,6 @@ async def test_no_called_started_twice() -> None:
     async def taskfunc(*, task_status: TaskStatus) -> None:
         task_status.started()
 
-    # anyio>4.3.0 should not raise "RuntimeError: called 'started' twice on the same task status"
     async with create_task_group() as tg:
         coro = tg.start(taskfunc)
         tg.cancel_scope.cancel()
@@ -196,9 +196,6 @@ async def test_start_cancelled() -> None:
     assert not finished
 
 
-@pytest.mark.xfail(
-    sys.version_info < (3, 9), reason="Requires a way to detect cancellation source"
-)
 @pytest.mark.parametrize("anyio_backend", ["asyncio"])
 async def test_start_native_host_cancelled() -> None:
     started = finished = False
@@ -1360,6 +1357,24 @@ async def test_cancel_child_task_when_host_is_shielded() -> None:
                 await cancelled.wait()
 
 
+async def test_start_cancels_parent_scope() -> None:
+    """Regression test for #685 / #710."""
+    started: bool = False
+
+    async def in_task_group(task_status: TaskStatus[None]) -> None:
+        nonlocal started
+        started = True
+        await sleep_forever()
+
+    async with create_task_group() as tg:
+        with CancelScope() as inner_scope:
+            inner_scope.cancel()
+            await tg.start(in_task_group)
+
+    assert started
+    assert not tg.cancel_scope.cancel_called
+
+
 class TestTaskStatusTyping:
     """
     These tests do not do anything at run time, but since the test suite is also checked