[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1109741: unblock: ansible-lint/25.6.1-1



Package: release.debian.org
Severity: normal
X-Debbugs-Cc: ansible-lint@packages.debian.org, debian@rocketjump.eu
Control: affects -1 + src:ansible-lint
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package ansible-lint

[ Reason ]
This package fixes the autopkgtests when running against ansible-core >=
2.19.0~rc2-1, as the latter added a handful of deprecation warnings which are
fatal in the test suite.

Unfortunately Gregory did not coordinate this upload with me, which bumps the
upstream version from 25.2.1 to 25.6.1 (upstream does not follow semantic
versioning, those are mostly bugfixes). I would have preferred a more targeted
fix.

A large part (> 80%) of the debdiff are upstream bumps of the package requirements (irrelevant to Debian), and renaming of playbook tasks to make them unique in the testsuite.

If you believe the changes are too large this late in the freeze, I'm willing to
provide a more targeted fix via t-p-u.

[ Impact ]
This unblock is needed to make the autopkgtests pass when run against
ansible-core >= 2.19.0~rc2-1.

[ Tests ]
There is good autopkgtest coverage for this package.

[ Risks ]
It's a bump to a later upstream, which has good test coverage. ansible-lint is
also a leaf package, so no other packages are directly affected.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
%

unblock ansible-lint/25.6.1-1
diff -Nru ansible-lint-25.2.1/collections/ansible_collections/local/testcollection/playbooks/playbook_bug4452.yml ansible-lint-25.6.1/collections/ansible_collections/local/testcollection/playbooks/playbook_bug4452.yml
--- ansible-lint-25.2.1/collections/ansible_collections/local/testcollection/playbooks/playbook_bug4452.yml	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/collections/ansible_collections/local/testcollection/playbooks/playbook_bug4452.yml	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,12 @@
+---
+- name: Role for 4452
+  hosts: localhost
+  gather_facts: false
+  tasks:
+    - name: Import role in subdir
+      ansible.builtin.import_role:
+        name: local.testcollection.subdirectory.bug4452
+
+    - name: Import role in 3rd level subdir
+      ansible.builtin.import_role:
+        name: local.testcollection.level1.level2.role_level3
diff -Nru ansible-lint-25.2.1/collections/ansible_collections/local/testcollection/roles/level1/level2/role_level3/tasks/main.yml ansible-lint-25.6.1/collections/ansible_collections/local/testcollection/roles/level1/level2/role_level3/tasks/main.yml
--- ansible-lint-25.2.1/collections/ansible_collections/local/testcollection/roles/level1/level2/role_level3/tasks/main.yml	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/collections/ansible_collections/local/testcollection/roles/level1/level2/role_level3/tasks/main.yml	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,4 @@
+---
+- name: Debug
+  ansible.builtin.debug:
+    msg: "Role in l3 subdir"
diff -Nru ansible-lint-25.2.1/collections/ansible_collections/local/testcollection/roles/subdirectory/bug4452/tasks/main.yml ansible-lint-25.6.1/collections/ansible_collections/local/testcollection/roles/subdirectory/bug4452/tasks/main.yml
--- ansible-lint-25.2.1/collections/ansible_collections/local/testcollection/roles/subdirectory/bug4452/tasks/main.yml	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/collections/ansible_collections/local/testcollection/roles/subdirectory/bug4452/tasks/main.yml	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,4 @@
+---
+- name: Debug
+  ansible.builtin.debug:
+    msg: "Role in subdir"
diff -Nru ansible-lint-25.2.1/.config/constraints.txt ansible-lint-25.6.1/.config/constraints.txt
--- ansible-lint-25.2.1/.config/constraints.txt	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.config/constraints.txt	2025-06-19 09:30:13.000000000 +0200
@@ -1,33 +1,33 @@
 # This file was autogenerated by uv via the following command:
 #    tox run -e deps
-ansible-compat==25.1.5    # via ansible-lint (pyproject.toml)
-astroid==3.3.9            # via pylint
+ansible-compat==25.5.0    # via ansible-lint (pyproject.toml)
+astroid==3.3.10           # via pylint
 asttokens==3.0.0          # via stack-data
 attrs==25.3.0             # via jsonschema, referencing
 babel==2.17.0             # via mkdocs-material
 backrefs==5.8             # via mkdocs-material
-beautifulsoup4==4.13.3    # via linkchecker, mkdocs-htmlproofer-plugin
+beautifulsoup4==4.13.4    # via linkchecker, mkdocs-htmlproofer-plugin
 bindep==2.13.0            # via tox-extra
 black==25.1.0             # via ansible-lint (pyproject.toml)
-boolean-py==4.0           # via license-expression
+boolean-py==5.0           # via license-expression
 bracex==2.5.post1         # via wcmatch
-cachetools==5.5.2         # via tox
+cachetools==6.0.0         # via tox
 cairocffi==1.7.1          # via cairosvg
 cairosvg==2.7.1           # via mkdocs-ansible
-certifi==2025.1.31        # via requests
+certifi==2025.6.15        # via requests
 cffi==1.17.1              # via cairocffi, cryptography
 chardet==5.2.0            # via tox
-charset-normalizer==3.4.1  # via requests
-click==8.1.8              # via black, mkdocs
+charset-normalizer==3.4.2  # via requests
+click==8.2.1              # via black, mkdocs
 colorama==0.4.6           # via griffe, mkdocs-material, tox
-coverage==7.7.1           # via coverage-enable-subprocess, ansible-lint (pyproject.toml)
+coverage==7.9.1           # via coverage-enable-subprocess, ansible-lint (pyproject.toml)
 coverage-enable-subprocess==1.0  # via ansible-lint (pyproject.toml)
-cryptography==44.0.2      # via ansible-core
+cryptography==45.0.4      # via ansible-core
 csscompressor==0.9.5      # via mkdocs-minify-plugin
 cssselect2==0.8.0         # via cairosvg
 decorator==5.2.1          # via ipdb, ipython
 defusedxml==0.7.1         # via cairosvg
-dill==0.3.9               # via pylint
+dill==0.4.0               # via pylint
 distlib==0.3.9            # via virtualenv
 distro==1.9.0             # via bindep
 dnspython==2.7.0          # via linkchecker
@@ -37,105 +37,102 @@
 ghp-import==2.1.0         # via mkdocs
 gitdb==4.0.12             # via gitpython
 gitpython==3.1.44         # via tox-extra
-griffe==1.7.1             # via mkdocstrings-python
+griffe==1.7.3             # via mkdocstrings-python
 hjson==3.1.0              # via mkdocs-macros-plugin, super-collections
 htmlmin2==0.1.13          # via mkdocs-minify-plugin
 idna==3.10                # via requests
-importlib-metadata==8.6.1  # via ansible-lint (pyproject.toml)
+importlib-metadata==8.7.0  # via ansible-lint (pyproject.toml)
 iniconfig==2.1.0          # via pytest
 ipdb==0.13.13             # via ansible-lint (pyproject.toml)
-ipython==8.34.0           # via ipdb, ansible-lint (pyproject.toml)
+ipython==8.36.0           # via ipdb, ansible-lint (pyproject.toml)
 isort==6.0.1              # via pylint
 jedi==0.19.2              # via ipython
 jinja2==3.1.6             # via ansible-core, mkdocs, mkdocs-macros-plugin, mkdocs-material, mkdocstrings
 jmespath==1.0.1           # via ansible-lint (pyproject.toml)
 jsmin==3.0.1              # via mkdocs-minify-plugin
-jsonschema==4.23.0        # via ansible-compat, ansible-lint (pyproject.toml)
-jsonschema-specifications==2024.10.1  # via jsonschema
+jsonschema==4.24.0        # via ansible-compat, ansible-lint (pyproject.toml)
+jsonschema-specifications==2025.4.1  # via jsonschema
 license-expression==30.4.1  # via ansible-lint (pyproject.toml)
 linkchecker==10.5.0       # via mkdocs-ansible
-markdown==3.7             # via markdown-include, mkdocs, mkdocs-autorefs, mkdocs-htmlproofer-plugin, mkdocs-material, mkdocstrings, pymdown-extensions
+markdown==3.8             # via markdown-include, mkdocs, mkdocs-autorefs, mkdocs-htmlproofer-plugin, mkdocs-material, mkdocstrings, pymdown-extensions
 markdown-exec==1.10.3     # via mkdocs-ansible
 markdown-include==0.8.1   # via mkdocs-ansible
 markupsafe==3.0.2         # via jinja2, mkdocs, mkdocs-autorefs, mkdocstrings
 matplotlib-inline==0.1.7  # via ipython
 mccabe==0.7.0             # via pylint
 mergedeep==1.3.4          # via mkdocs, mkdocs-get-deps
-mkdocs==1.6.1             # via mkdocs-ansible, mkdocs-autorefs, mkdocs-gen-files, mkdocs-htmlproofer-plugin, mkdocs-macros-plugin, mkdocs-material, mkdocs-minify-plugin, mkdocs-monorepo-plugin, mkdocstrings
-mkdocs-ansible==25.2.0    # via ansible-lint (pyproject.toml)
-mkdocs-autorefs==1.4.1    # via mkdocstrings, mkdocstrings-python
+mkdocs==1.6.1             # via mkdocs-ansible, mkdocs-autorefs, mkdocs-gen-files, mkdocs-htmlproofer-plugin, mkdocs-macros-plugin, mkdocs-material, mkdocs-minify-plugin, mkdocstrings
+mkdocs-ansible==25.5.0    # via ansible-lint (pyproject.toml)
+mkdocs-autorefs==1.4.2    # via mkdocstrings, mkdocstrings-python
 mkdocs-gen-files==0.5.0   # via mkdocs-ansible
 mkdocs-get-deps==0.2.0    # via mkdocs
 mkdocs-htmlproofer-plugin==1.3.0  # via mkdocs-ansible
 mkdocs-macros-plugin==1.3.7  # via mkdocs-ansible
-mkdocs-material==9.6.9    # via mkdocs-ansible
+mkdocs-material==9.6.14   # via mkdocs-ansible
 mkdocs-material-extensions==1.3.1  # via mkdocs-ansible, mkdocs-material
 mkdocs-minify-plugin==0.8.0  # via mkdocs-ansible
-mkdocs-monorepo-plugin==1.1.0  # via mkdocs-ansible
-mkdocstrings==0.29.0      # via mkdocs-ansible, mkdocstrings-python
-mkdocstrings-python==1.16.8  # via mkdocs-ansible
-mypy==1.15.0              # via ansible-lint (pyproject.toml)
-mypy-extensions==1.0.0    # via black, mypy
+mkdocstrings==0.29.1      # via mkdocs-ansible, mkdocstrings-python
+mkdocstrings-python==1.16.12  # via mkdocs-ansible
+mypy==1.16.0              # via ansible-lint (pyproject.toml)
+mypy-extensions==1.1.0    # via black, mypy
 netaddr==1.3.0            # via ansible-lint (pyproject.toml)
-packaging==24.2           # via ansible-compat, ansible-core, bindep, black, mkdocs, mkdocs-macros-plugin, pyproject-api, pytest, pytest-sugar, tox, tox-extra, tox-uv, ansible-lint (pyproject.toml)
+packaging==25.0           # via ansible-compat, ansible-core, bindep, black, mkdocs, mkdocs-macros-plugin, pyproject-api, pytest, pytest-sugar, tox, tox-extra, tox-uv, ansible-lint (pyproject.toml)
 paginate==0.5.7           # via mkdocs-material
 parsley==1.3              # via bindep
 parso==0.8.4              # via jedi
-pathspec==0.12.1          # via black, mkdocs, mkdocs-macros-plugin, yamllint, ansible-lint (pyproject.toml)
+pathspec==0.12.1          # via black, mkdocs, mkdocs-macros-plugin, mypy, yamllint, ansible-lint (pyproject.toml)
 pbr==6.1.1                # via bindep
 pexpect==4.9.0            # via ipython
-pillow==11.1.0            # via cairosvg, mkdocs-ansible
-platformdirs==4.3.7       # via black, mkdocs-get-deps, pylint, tox, virtualenv
-pluggy==1.5.0             # via pytest, tox
-prompt-toolkit==3.0.50    # via ipython
+pillow==11.2.1            # via cairosvg, mkdocs-ansible
+platformdirs==4.3.8       # via black, mkdocs-get-deps, pylint, tox, virtualenv
+pluggy==1.6.0             # via pytest, tox
+prompt-toolkit==3.0.51    # via ipython
 psutil==7.0.0             # via pytest-xdist, ansible-lint (pyproject.toml)
 ptyprocess==0.7.0         # via pexpect
 pure-eval==0.2.3          # via stack-data
 pycparser==2.22           # via cffi
-pygments==2.19.1          # via ipython, mkdocs-material
-pylint==3.3.6             # via ansible-lint (pyproject.toml)
-pymdown-extensions==10.14.3  # via markdown-exec, mkdocs-ansible, mkdocs-material, mkdocstrings
-pyproject-api==1.9.0      # via tox
-pytest==8.3.5             # via pytest-instafail, pytest-mock, pytest-plus, pytest-sugar, pytest-xdist, ansible-lint (pyproject.toml)
+pygments==2.19.1          # via ipython, mkdocs-material, pytest
+pylint==3.3.7             # via ansible-lint (pyproject.toml)
+pymdown-extensions==10.15  # via markdown-exec, mkdocs-ansible, mkdocs-material, mkdocstrings
+pyproject-api==1.9.1      # via tox
+pytest==8.4.0             # via pytest-instafail, pytest-mock, pytest-plus, pytest-sugar, pytest-xdist, ansible-lint (pyproject.toml)
 pytest-instafail==0.5.0   # via ansible-lint (pyproject.toml)
-pytest-mock==3.14.0       # via ansible-lint (pyproject.toml)
+pytest-mock==3.14.1       # via ansible-lint (pyproject.toml)
 pytest-plus==0.8.1        # via ansible-lint (pyproject.toml)
 pytest-sugar==1.0.0       # via ansible-lint (pyproject.toml)
-pytest-xdist==3.6.1       # via ansible-lint (pyproject.toml)
+pytest-xdist==3.7.0       # via ansible-lint (pyproject.toml)
 python-dateutil==2.9.0.post0  # via ghp-import, mkdocs-macros-plugin
-python-slugify==8.0.4     # via mkdocs-monorepo-plugin
 pyyaml==6.0.2             # via ansible-compat, ansible-core, mkdocs, mkdocs-get-deps, mkdocs-macros-plugin, pymdown-extensions, pyyaml-env-tag, yamllint, ansible-lint (pyproject.toml)
-pyyaml-env-tag==0.1       # via mkdocs
+pyyaml-env-tag==1.1       # via mkdocs
 referencing==0.36.2       # via jsonschema, jsonschema-specifications, types-jsonschema, ansible-lint (pyproject.toml)
-requests==2.32.3          # via linkchecker, mkdocs-htmlproofer-plugin, mkdocs-material
-rpds-py==0.24.0           # via jsonschema, referencing
-ruamel-yaml==0.18.10      # via ansible-lint (pyproject.toml)
-setproctitle==1.3.5       # via pytest-xdist
-setuptools==78.1.0        # via pbr
+requests==2.32.4          # via linkchecker, mkdocs-htmlproofer-plugin, mkdocs-material
+rpds-py==0.25.1           # via jsonschema, referencing
+ruamel-yaml==0.18.11      # via ansible-lint (pyproject.toml)
+setproctitle==1.3.6       # via pytest-xdist
+setuptools==80.9.0        # via pbr
 six==1.17.0               # via python-dateutil
 smmap==5.0.2              # via gitdb
-soupsieve==2.6            # via beautifulsoup4
+soupsieve==2.7            # via beautifulsoup4
 stack-data==0.6.3         # via ipython
 subprocess-tee==0.4.2     # via ansible-compat, ansible-lint (pyproject.toml)
 super-collections==0.5.3  # via mkdocs-macros-plugin
-termcolor==2.5.0          # via mkdocs-macros-plugin, pytest-sugar
-text-unidecode==1.3       # via python-slugify
+termcolor==3.1.0          # via mkdocs-macros-plugin, pytest-sugar
 tinycss2==1.4.0           # via cairosvg, cssselect2
-tomlkit==0.13.2           # via pylint
-tox==4.25.0               # via tox-extra, tox-uv, ansible-lint (pyproject.toml)
+tomlkit==0.13.3           # via pylint
+tox==4.26.0               # via tox-extra, tox-uv, ansible-lint (pyproject.toml)
 tox-extra==2.1.0          # via ansible-lint (pyproject.toml)
-tox-uv==1.25.0            # via tox-extra, ansible-lint (pyproject.toml)
+tox-uv==1.26.0            # via tox-extra, ansible-lint (pyproject.toml)
 traitlets==5.14.3         # via ipython, matplotlib-inline
-types-jsonschema==4.23.0.20241208  # via ansible-lint (pyproject.toml)
-types-pyyaml==6.0.12.20250326  # via ansible-lint (pyproject.toml)
-urllib3==2.3.0            # via requests
-virtualenv==20.29.3       # via tox
+types-jsonschema==4.24.0.20250528  # via ansible-lint (pyproject.toml)
+types-pyyaml==6.0.12.20250516  # via ansible-lint (pyproject.toml)
+urllib3==2.4.0            # via requests
+virtualenv==20.31.2       # via tox
 watchdog==6.0.0           # via mkdocs
 wcmatch==10.0             # via ansible-lint (pyproject.toml)
 wcwidth==0.2.13           # via prompt-toolkit
 webencodings==0.5.1       # via cssselect2, tinycss2
-yamllint==1.37.0          # via ansible-lint (pyproject.toml)
-zipp==3.21.0              # via importlib-metadata
+yamllint==1.37.1          # via ansible-lint (pyproject.toml)
+zipp==3.23.0              # via importlib-metadata
 
 # The following packages were excluded from the output:
 # ansible-core
diff -Nru ansible-lint-25.2.1/.config/dictionary.txt ansible-lint-25.6.1/.config/dictionary.txt
--- ansible-lint-25.2.1/.config/dictionary.txt	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.config/dictionary.txt	2025-06-19 09:30:13.000000000 +0200
@@ -17,7 +17,6 @@
 PYTHONBREAKPOINT
 PYTHONIOENCODING
 PYTHONPYCACHEPREFIX
-REQPASS
 RULEDIRS
 RUNLEVEL
 Renderable
diff -Nru ansible-lint-25.2.1/.config/requirements-docs.in ansible-lint-25.6.1/.config/requirements-docs.in
--- ansible-lint-25.2.1/.config/requirements-docs.in	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.config/requirements-docs.in	2025-06-19 09:30:13.000000000 +0200
@@ -1 +1 @@
-mkdocs-ansible>=24.12.0  # do not use lock extra because it would break dependabot updates
+mkdocs-ansible>=25.5.0  # do not use lock extra because it would break dependabot updates
diff -Nru ansible-lint-25.2.1/.config/requirements.in ansible-lint-25.6.1/.config/requirements.in
--- ansible-lint-25.2.1/.config/requirements.in	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.config/requirements.in	2025-06-19 09:30:13.000000000 +0200
@@ -9,7 +9,7 @@
 packaging>=22.0 # Apache-2.0,BSD-2-Clause
 pathspec>=0.10.3 # Mozilla Public License 2.0 (MPL 2.0)
 pyyaml>=6.0.2 # MIT (compilation probles with older versions)
-ruamel.yaml>=0.18.5,!=0.18.7,!=0.18.8 # MIT
+ruamel.yaml>=0.18.11 # MIT (https://sourceforge.net/p/ruamel-yaml/tickets/545/)
 referencing>=0.36.2 # MIT, https://github.com/python-jsonschema/referencing/issues/216
 subprocess-tee>=0.4.1 # MIT, used by ansible-compat
 yamllint >= 1.34.0 # GPLv3
diff -Nru ansible-lint-25.2.1/.config/requirements-lock.txt ansible-lint-25.6.1/.config/requirements-lock.txt
--- ansible-lint-25.2.1/.config/requirements-lock.txt	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.config/requirements-lock.txt	2025-06-19 09:30:13.000000000 +0200
@@ -1,31 +1,31 @@
 # This file was autogenerated by uv via the following command:
 #    tox run -e deps
-ansible-compat==25.1.5    # via ansible-lint (pyproject.toml)
+ansible-compat==25.5.0    # via ansible-lint (pyproject.toml)
 attrs==25.3.0             # via jsonschema, referencing
 black==25.1.0             # via ansible-lint (pyproject.toml)
 bracex==2.5.post1         # via wcmatch
 cffi==1.17.1              # via cryptography
-click==8.1.8              # via black
-cryptography==44.0.2      # via ansible-core
+click==8.2.1              # via black
+cryptography==45.0.4      # via ansible-core
 filelock==3.18.0          # via ansible-lint (pyproject.toml)
-importlib-metadata==8.6.1  # via ansible-lint (pyproject.toml)
+importlib-metadata==8.7.0  # via ansible-lint (pyproject.toml)
 jinja2==3.1.6             # via ansible-core
-jsonschema==4.23.0        # via ansible-compat, ansible-lint (pyproject.toml)
-jsonschema-specifications==2024.10.1  # via jsonschema
+jsonschema==4.24.0        # via ansible-compat, ansible-lint (pyproject.toml)
+jsonschema-specifications==2025.4.1  # via jsonschema
 markupsafe==3.0.2         # via jinja2
-mypy-extensions==1.0.0    # via black
-packaging==24.2           # via ansible-compat, ansible-core, black, ansible-lint (pyproject.toml)
+mypy-extensions==1.1.0    # via black
+packaging==25.0           # via ansible-compat, ansible-core, black, ansible-lint (pyproject.toml)
 pathspec==0.12.1          # via black, yamllint, ansible-lint (pyproject.toml)
-platformdirs==4.3.7       # via black
+platformdirs==4.3.8       # via black
 pycparser==2.22           # via cffi
 pyyaml==6.0.2             # via ansible-compat, ansible-core, yamllint, ansible-lint (pyproject.toml)
 referencing==0.36.2       # via jsonschema, jsonschema-specifications, ansible-lint (pyproject.toml)
-rpds-py==0.24.0           # via jsonschema, referencing
-ruamel-yaml==0.18.10      # via ansible-lint (pyproject.toml)
+rpds-py==0.25.1           # via jsonschema, referencing
+ruamel-yaml==0.18.11      # via ansible-lint (pyproject.toml)
 subprocess-tee==0.4.2     # via ansible-compat, ansible-lint (pyproject.toml)
 wcmatch==10.0             # via ansible-lint (pyproject.toml)
-yamllint==1.37.0          # via ansible-lint (pyproject.toml)
-zipp==3.21.0              # via importlib-metadata
+yamllint==1.37.1          # via ansible-lint (pyproject.toml)
+zipp==3.23.0              # via importlib-metadata
 
 # The following packages were excluded from the output:
 # ansible-core
diff -Nru ansible-lint-25.2.1/.config/requirements-test.in ansible-lint-25.6.1/.config/requirements-test.in
--- ansible-lint-25.2.1/.config/requirements-test.in	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.config/requirements-test.in	2025-06-19 09:30:13.000000000 +0200
@@ -13,11 +13,11 @@
 pytest >= 7.2.2
 pytest-instafail >= 0.5.0 # only for local development, via PYTEST_ADDOPTS=-edit
 pytest-mock
-pytest-plus >= 0.6 # for PYTEST_REQPASS
+pytest-plus >= 0.6
 pytest-sugar  # shows failures immediately, even with xdist
 pytest-xdist[psutil,setproctitle] >= 2.1.0
 ruamel-yaml-clib  # needed for mypy
-ruamel.yaml>=0.17.31
+ruamel.yaml>=0.18.11
 tox >= 4.0.0
 tox-extra>=2.1
 tox-uv>=1.25
diff -Nru ansible-lint-25.2.1/conftest.py ansible-lint-25.6.1/conftest.py
--- ansible-lint-25.2.1/conftest.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/conftest.py	2025-06-19 09:30:13.000000000 +0200
@@ -39,7 +39,7 @@
         # we need to be sure that we have the requirements installed as some tests
         # might depend on these. This approach is compatible with GHA caching.
         try:
-            subprocess.check_output(  # noqa: S603
+            subprocess.check_output(
                 ["./tools/install-reqs.sh"],
                 stderr=subprocess.PIPE,
                 text=True,
diff -Nru ansible-lint-25.2.1/debian/changelog ansible-lint-25.6.1/debian/changelog
--- ansible-lint-25.2.1/debian/changelog	2025-05-10 21:04:00.000000000 +0200
+++ ansible-lint-25.6.1/debian/changelog	2025-07-11 10:31:16.000000000 +0200
@@ -1,3 +1,14 @@
+ansible-lint (25.6.1-1) unstable; urgency=medium
+
+  * New upstream version 25.6.1
+  * Minor patch in deb-testing.patch
+  * Fix remove_importlib_metadata.patch
+  * Add disable-test_ro_venv.patch
+  * Add partially-disable-test_normalize_complex_command.patch
+    because Ansible 2.19 emits a deprecated warning
+
+ -- Gregory Colpart <reg@debian.org>  Fri, 11 Jul 2025 10:31:16 +0200
+
 ansible-lint (25.2.1-3) unstable; urgency=medium
 
   * Team upload.
diff -Nru ansible-lint-25.2.1/debian/patches/deb-testing.patch ansible-lint-25.6.1/debian/patches/deb-testing.patch
--- ansible-lint-25.2.1/debian/patches/deb-testing.patch	2025-05-10 21:04:00.000000000 +0200
+++ ansible-lint-25.6.1/debian/patches/deb-testing.patch	2025-07-11 10:31:16.000000000 +0200
@@ -35,7 +35,7 @@
 -        # we need to be sure that we have the requirements installed as some tests
 -        # might depend on these. This approach is compatible with GHA caching.
 -        try:
--            subprocess.check_output(  # noqa: S603
+-            subprocess.check_output(
 -                ["./tools/install-reqs.sh"],
 -                stderr=subprocess.PIPE,
 -                text=True,
diff -Nru ansible-lint-25.2.1/debian/patches/disable-test_ro_venv.patch ansible-lint-25.6.1/debian/patches/disable-test_ro_venv.patch
--- ansible-lint-25.2.1/debian/patches/disable-test_ro_venv.patch	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/debian/patches/disable-test_ro_venv.patch	2025-07-11 10:31:16.000000000 +0200
@@ -0,0 +1,66 @@
+From: Gregory Colpart <reg@debian.org>
+Date: Sat, 12 Jul 2025 21:37:13 +0200
+Subject: avoid "/bin/sh: 1: python: not found" when building
+
+---
+ test/test_main.py | 50 +++++++++++++++++++++++++-------------------------
+ 1 file changed, 25 insertions(+), 25 deletions(-)
+
+diff --git a/test/test_main.py b/test/test_main.py
+index 9e0dcd7..cec9c7a 100644
+--- a/test/test_main.py
++++ b/test/test_main.py
+@@ -183,28 +183,28 @@ def test_list_tags() -> None:
+             assert isinstance(item, str)
+ 
+ 
+-def test_ro_venv() -> None:
+-    """Tests behavior when the virtual environment is read-only."""
+-    tox_work_dir = os.environ.get("TOX_WORK_DIR", ".tox")
+-    venv_path = f"{tox_work_dir}/ro"
+-    commands = [
+-        f"mkdir -p {venv_path}",
+-        f"chmod -R a+w {venv_path}",
+-        f"rm -rf {venv_path}",
+-        f"python -m venv --symlinks {venv_path}",
+-        f"{venv_path}/bin/python -m pip install -q -e .",
+-        f"chmod -R a-w {venv_path}",
+-        # running with a ro venv and default cwd
+-        f"{venv_path}/bin/ansible-lint --version",
+-        # running from a read-only cwd:
+-        f"cd / && {abspath(venv_path)}/bin/ansible-lint --version",  # noqa: PTH100
+-        # running with a ro venv and a custom project path in forced non-online mode, so it will need to install requirements
+-        f"{venv_path}/bin/ansible-lint -vv --no-offline --project-dir ./examples/reqs_v2/ ./examples/reqs_v2/",
+-    ]
+-    for cmd in commands:
+-        result = subprocess.run(
+-            cmd, capture_output=True, shell=True, text=True, check=False
+-        )
+-        assert result.returncode == 0, (
+-            f"Got {result.returncode} running {cmd}\n\tstderr: {result.stderr}\n\tstdout: {result.stdout}"
+-        )
++#def test_ro_venv() -> None:
++#    """Tests behavior when the virtual environment is read-only."""
++#    tox_work_dir = os.environ.get("TOX_WORK_DIR", ".tox")
++#    venv_path = f"{tox_work_dir}/ro"
++#    commands = [
++#        f"mkdir -p {venv_path}",
++#        f"chmod -R a+w {venv_path}",
++#        f"rm -rf {venv_path}",
++#        f"python3 -m venv --symlinks {venv_path}",
++#        f"{venv_path}/bin/python -m pip install -q -e .",
++#        f"chmod -R a-w {venv_path}",
++#        # running with a ro venv and default cwd
++#        f"{venv_path}/bin/ansible-lint --version",
++#        # running from a read-only cwd:
++#        f"cd / && {abspath(venv_path)}/bin/ansible-lint --version",  # noqa: PTH100
++#        # running with a ro venv and a custom project path in forced non-online mode, so it will need to install requirements
++#        f"{venv_path}/bin/ansible-lint -vv --no-offline --project-dir ./examples/reqs_v2/ ./examples/reqs_v2/",
++#    ]
++#    for cmd in commands:
++#        result = subprocess.run(
++#            cmd, capture_output=True, shell=True, text=True, check=False
++#        )
++#        assert result.returncode == 0, (
++#            f"Got {result.returncode} running {cmd}\n\tstderr: {result.stderr}\n\tstdout: {result.stdout}"
++#        )
diff -Nru ansible-lint-25.2.1/debian/patches/partially-disable-test_normalize_complex_command.patch ansible-lint-25.6.1/debian/patches/partially-disable-test_normalize_complex_command.patch
--- ansible-lint-25.2.1/debian/patches/partially-disable-test_normalize_complex_command.patch	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/debian/patches/partially-disable-test_normalize_complex_command.patch	2025-07-11 10:31:16.000000000 +0200
@@ -0,0 +1,42 @@
+From: Gregory Colpart <gcolpart+git@evolix.fr>
+Date: Sat, 12 Jul 2025 22:54:32 +0200
+Subject: partially disable test_normalize_complex_command
+
+---
+ test/test_utils.py | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/test/test_utils.py b/test/test_utils.py
+index 0dc0bbe..b227dd0 100644
+--- a/test/test_utils.py
++++ b/test/test_utils.py
+@@ -132,13 +132,13 @@ def test_normalize(
+ 
+ def test_normalize_complex_command() -> None:
+     """Test that tasks specified differently are normalized same way."""
+-    task1 = utils.Task(
+-        {
+-            "name": "hello",
+-            "action": {"module": "pip", "name": "df", "editable": "false"},
+-        },
+-        filename="tasks.yml",
+-    )
++    #task1 = utils.Task(
++    #    {
++    #        "name": "hello",
++    #        "action": {"module": "pip", "name": "df", "editable": "false"},
++    #    },
++    #    filename="tasks.yml",
++    #)
+     task2 = utils.Task(
+         {"name": "hello", "pip": {"name": "df", "editable": "false"}},
+         filename="tasks.yml",
+@@ -151,7 +151,7 @@ def test_normalize_complex_command() -> None:
+         {"name": "hello", "action": "pip name=df editable=false"},
+         filename="tasks.yml",
+     )
+-    assert task1._normalize_task() == task2._normalize_task()  # noqa: SLF001
++    #assert task1._normalize_task() == task2._normalize_task()  # noqa: SLF001
+     assert task2._normalize_task() == task3._normalize_task()  # noqa: SLF001
+     assert task3._normalize_task() == task4._normalize_task()  # noqa: SLF001
+ 
diff -Nru ansible-lint-25.2.1/debian/patches/remove_importlib_metadata.patch ansible-lint-25.6.1/debian/patches/remove_importlib_metadata.patch
--- ansible-lint-25.2.1/debian/patches/remove_importlib_metadata.patch	2025-05-10 21:04:00.000000000 +0200
+++ ansible-lint-25.6.1/debian/patches/remove_importlib_metadata.patch	2025-07-11 10:31:16.000000000 +0200
@@ -4,20 +4,20 @@
  hjson==3.1.0              # via mkdocs-macros-plugin, super-collections
  htmlmin2==0.1.13          # via mkdocs-minify-plugin
  idna==3.10                # via requests
--importlib-metadata==8.6.1  # via ansible-lint (pyproject.toml)
+-importlib-metadata==8.7.0  # via ansible-lint (pyproject.toml)
  iniconfig==2.1.0          # via pytest
  ipdb==0.13.13             # via ansible-lint (pyproject.toml)
- ipython==8.34.0           # via ipdb, ansible-lint (pyproject.toml)
+ ipython==8.36.0           # via ipdb, ansible-lint (pyproject.toml)
 --- a/.config/requirements-lock.txt
 +++ b/.config/requirements-lock.txt
 @@ -8,7 +8,6 @@
- click==8.1.8              # via black
- cryptography==44.0.2      # via ansible-core
+ click==8.2.1              # via black
+ cryptography==45.0.4      # via ansible-core
  filelock==3.18.0          # via ansible-lint (pyproject.toml)
--importlib-metadata==8.6.1  # via ansible-lint (pyproject.toml)
+-importlib-metadata==8.7.0  # via ansible-lint (pyproject.toml)
  jinja2==3.1.6             # via ansible-core
- jsonschema==4.23.0        # via ansible-compat, ansible-lint (pyproject.toml)
- jsonschema-specifications==2024.10.1  # via jsonschema
+ jsonschema==4.24.0        # via ansible-compat, ansible-lint (pyproject.toml)
+ jsonschema-specifications==2025.4.1  # via jsonschema
 --- a/.config/requirements.in
 +++ b/.config/requirements.in
 @@ -4,7 +4,6 @@
@@ -30,7 +30,7 @@
  pathspec>=0.10.3 # Mozilla Public License 2.0 (MPL 2.0)
 --- a/.pre-commit-config.yaml
 +++ b/.pre-commit-config.yaml
-@@ -165,7 +165,6 @@
+@@ -163,7 +163,6 @@
            - black>=22.10.0
            - cryptography>=39.0.1
            - filelock>=3.12.2
@@ -52,8 +52,8 @@
  
      def __init__(self, name: str = "ansible-lint") -> None:
          """Load linter metadata requirements."""
--        for req_str in importlib_metadata.metadata(name).json["requires_dist"]:
-+        for req_str in importlib.metadata.metadata(name).json["requires_dist"]:
-             req = Requirement(req_str)
-             if req.name:
-                 self[req.name] = req.specifier
+-        metadata = importlib_metadata.metadata(name)
++        metadata = importlib.metadata.metadata(name)
+         if metadata:
+             for req_str in metadata.json["requires_dist"]:
+                 req = Requirement(req_str)
diff -Nru ansible-lint-25.2.1/debian/patches/series ansible-lint-25.6.1/debian/patches/series
--- ansible-lint-25.2.1/debian/patches/series	2025-05-10 21:04:00.000000000 +0200
+++ ansible-lint-25.6.1/debian/patches/series	2025-07-11 10:31:16.000000000 +0200
@@ -2,3 +2,5 @@
 deb-testing.patch
 remove_disable_lookups_from_templating.patch
 remove_importlib_metadata.patch
+disable-test_ro_venv.patch
+partially-disable-test_normalize_complex_command.patch
diff -Nru ansible-lint-25.2.1/docs/configuring.md ansible-lint-25.6.1/docs/configuring.md
--- ansible-lint-25.2.1/docs/configuring.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/docs/configuring.md	2025-06-19 09:30:13.000000000 +0200
@@ -42,7 +42,7 @@
 
 ## Ignoring rules for entire files
 
-Ansible-lint will load skip rules from an `.ansible-lint-ignore` or
+Ansible-lint will load ignore rules from an `.ansible-lint-ignore` or
 `.config/ansible-lint-ignore.txt` file that should reside adjacent to the config
 file. The file format is very simple, containing the filename and the rule to be
 ignored. It also supports comments starting with `#`.
@@ -56,6 +56,15 @@
 The file can also be created by adding `--generate-ignore` to the command line.
 Keep in mind that this will override any existing file content.
 
+By default, rules ignored here will raise a non-fatal warning in the
+output.  If you add `skip` to the line, the test will be skipped
+(see `skip_list`) and not raise any warning.
+
+```yaml title=".ansible-lint-ignore"
+playbook.yml role-name  # raises warning
+playbook2.yml role-name skip  # no warning
+```
+
 ## Pre-commit setup
 
 To use Ansible-lint with the [pre-commit] tool, add the following to the
diff -Nru ansible-lint-25.2.1/docs/installing.md ansible-lint-25.6.1/docs/installing.md
--- ansible-lint-25.2.1/docs/installing.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/docs/installing.md	2025-06-19 09:30:13.000000000 +0200
@@ -35,10 +35,10 @@
     related to the installation will be closed and locked.
 
 For a container image, we recommend using
-[creator-ee](https://github.com/ansible/creator-ee/) which includes
-`ansible-dev-tools` (it combines critical Ansible development packages into a
-unified Python package). If you have a use case that the `creator-ee` container
-doesn't satisfy, please contact the team through the
+[community-ansible-dev-tools](https://ansible.readthedocs.io/projects/dev-tools/container/)
+which includes `ansible-dev-tools` (it combines critical Ansible development packages into
+a unified Python package). If you have a use case that the `community-ansible-dev-tools`
+container doesn't satisfy, please contact the team through the
 [discussion](https://github.com/ansible/ansible-lint/discussions) forum.
 
 You can also run Ansible-lint on your source code with the
diff -Nru ansible-lint-25.2.1/docs/rules/args.md ansible-lint-25.6.1/docs/rules/args.md
--- ansible-lint-25.2.1/docs/rules/args.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/docs/rules/args.md	2025-06-19 09:30:13.000000000 +0200
@@ -40,6 +40,13 @@
           - my_param <= 100
           - my_param >= 0
         quiet: invalid # <- Value for option `quiet` is invalid.
+
+    - name: Do not use mutually exclusive arguments together
+      ansible.builtin.command:
+        cmd: /bin/echo # <- cmd and argv are mutually exclusive options
+        argv:
+          - Hello
+      when_changed: false
 ```
 
 ## Correct Code
@@ -69,6 +76,18 @@
           - my_param <= 100
           - my_param >= 0
         quiet: True # <- Has correct type value for option `quiet` which is boolean.
+
+    - name: Do not use mutually exclusive arguments together
+      ansible.builtin.command:
+        cmd: "/bin/echo Hello" # <- Does not use `cmd` and `argv`
+      when_changed: false
+
+    - name: Do not use mutually exclusive arguments together alternative
+      ansible.builtin.command:
+        argv: # <- Does not use `cmd` and `argv`
+          - /bin/echo
+          - Hello
+      when_changed: false
 ```
 
 ## Special cases
diff -Nru ansible-lint-25.2.1/docs/rules/name.md ansible-lint-25.6.1/docs/rules/name.md
--- ansible-lint-25.2.1/docs/rules/name.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/docs/rules/name.md	2025-06-19 09:30:13.000000000 +0200
@@ -15,10 +15,15 @@
   helps with the identification of tasks inside the source code when they fail.
   The use of templating inside `name` keys is discouraged as there are multiple
   cases where the rendering of the name template is not possible.
+- `name[unique]` - All task names within a single play should be unique.
 
 If you want to ignore some of the messages above, you can add any of them to the
 `skip_list`.
 
+## name[unique]
+
+This check ensures that every task name is unique within the same play. This includes tasks defined in the `pre_tasks`, `tasks`, `post_tasks`, and `handlers` sections. Having unique names is crucial for reliably using features like `--start-at-task` and makes playbook execution easier to follow and debug.
+
 ## name[prefix]
 
 This rule applies only to included task files that are not named `main.yml` or
diff -Nru ansible-lint-25.2.1/docs/rules/no-log-password.md ansible-lint-25.6.1/docs/rules/no-log-password.md
--- ansible-lint-25.2.1/docs/rules/no-log-password.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/docs/rules/no-log-password.md	2025-06-19 09:30:13.000000000 +0200
@@ -6,6 +6,14 @@
 While most Ansible modules mask sensitive data, using secrets inside a loop can result in those secrets being logged.
 Explicitly adding `no_log: true` prevents accidentally exposing secrets.
 
+This is an opt-in rule.
+You must enable it in your Ansible-lint configuration as follows:
+
+```yaml
+enable_list:
+  - no-log-password
+```
+
 ## Problematic Code
 
 ```yaml
diff -Nru ansible-lint-25.2.1/docs/rules/package-latest.md ansible-lint-25.6.1/docs/rules/package-latest.md
--- ansible-lint-25.2.1/docs/rules/package-latest.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/docs/rules/package-latest.md	2025-06-19 09:30:13.000000000 +0200
@@ -2,7 +2,7 @@
 
 This rule checks that package managers install software in a controlled, safe manner.
 
-Package manager modules, such as `ansible.builtin.yum`, include a `state` parameter that configures how Ansible installs software.
+Package manager modules, such as `ansible.builtin.dnf`, include a `state` parameter that configures how Ansible installs software.
 In production environments, you should set `state` to `present` and specify a target version to ensure that packages are installed to a planned and tested version.
 
 Setting `state` to `latest` not only installs software, it performs an update and installs additional packages.
@@ -17,7 +17,7 @@
   hosts: localhost
   tasks:
     - name: Install Ansible
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: ansible
         state: latest # <- Installs the latest package.
 
@@ -33,7 +33,7 @@
         state: latest # <- Installs the latest package.
 
     - name: Install sudo with update_only to false
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: sudo
         state: latest
         update_only: false # <- Updates and installs packages.
@@ -53,9 +53,9 @@
   hosts: localhost
   tasks:
     - name: Install Ansible
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: ansible-2.12.7.0
-        state: present # <- Pins the version to install with yum.
+        state: present # <- Pins the version to install with dnf.
 
     - name: Install Ansible-lint
       ansible.builtin.pip:
@@ -70,7 +70,7 @@
         state: present # <- Ensures the package is installed.
 
     - name: Update sudo with update_only to true
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: sudo
         state: latest
         update_only: true # <- Updates but does not install additional packages.
diff -Nru ansible-lint-25.2.1/examples/broken/load-failure-invalid.yml ansible-lint-25.6.1/examples/broken/load-failure-invalid.yml
--- ansible-lint-25.2.1/examples/broken/load-failure-invalid.yml	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/examples/broken/load-failure-invalid.yml	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,5 @@
+---
+- aaa: 1
+  bbb: 2
+  c: 3
+foo: bar
diff -Nru ansible-lint-25.2.1/examples/playbooks/import_role_fqcn.yml ansible-lint-25.6.1/examples/playbooks/import_role_fqcn.yml
--- ansible-lint-25.2.1/examples/playbooks/import_role_fqcn.yml	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/examples/playbooks/import_role_fqcn.yml	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,9 @@
+---
+- name: Roles
+  hosts: localhost
+  roles:
+    - name: local.testcollection.bug4095
+    - name: local.testcollection.subdirectory.bug4452
+
+- name: Import a playbook with role in a subdirectory
+  ansible.builtin.import_playbook: local.testcollection.playbook_bug4452
diff -Nru ansible-lint-25.2.1/examples/playbooks/lots_of_warnings.yml ansible-lint-25.6.1/examples/playbooks/lots_of_warnings.yml
--- ansible-lint-25.2.1/examples/playbooks/lots_of_warnings.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/lots_of_warnings.yml	2025-06-19 09:30:13.000000000 +0200
@@ -6,995 +6,995 @@
 - name: Fixture
   hosts: webservers
   tasks:
-    - name: Executing git through command
+    - name: Executing git through command 1
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 2
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 3
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 4
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 5
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 6
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 7
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 8
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 9
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 10
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 11
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 12
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 13
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 14
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 15
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 16
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 17
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 18
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 19
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 20
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 21
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 22
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 23
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 24
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 25
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 26
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 27
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 28
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 29
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 30
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 31
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 32
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 33
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 34
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 35
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 36
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 37
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 38
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 39
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 40
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 41
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 42
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 43
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 44
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 45
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 46
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 47
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 48
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 49
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 50
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 51
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 52
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 53
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 54
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 55
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 56
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 57
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 58
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 59
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 60
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 61
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 62
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 63
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 64
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 65
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 66
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 67
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 68
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 69
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 70
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 71
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 72
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 73
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 74
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 75
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 76
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 77
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 78
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 79
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 80
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 81
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 82
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 83
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 84
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 85
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 86
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 87
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 88
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 89
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 90
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 91
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 92
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 93
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 94
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 95
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 96
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 97
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 98
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 99
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 100
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 101
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 102
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 103
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 104
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 105
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 106
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 107
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 108
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 109
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 110
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 111
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 112
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 113
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 114
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 115
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 116
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 117
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 118
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 119
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 120
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 121
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 122
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 123
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 124
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 125
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 126
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 127
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 128
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 129
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 130
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 131
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 132
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 133
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 134
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 135
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 136
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 137
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 138
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 139
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 140
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 141
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 142
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 143
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 144
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 145
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 146
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 147
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 148
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 149
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 150
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 151
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 152
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 153
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 154
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 155
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 156
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 157
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 158
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 159
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 160
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 161
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 162
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 163
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 164
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 165
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 166
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 167
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 168
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 169
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 170
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 171
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 172
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 173
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 174
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 175
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 176
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 177
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 178
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 179
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 180
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 181
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 182
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 183
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 184
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 185
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 186
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 187
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 188
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 189
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 190
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 191
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 192
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 193
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 194
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 195
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 196
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 197
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 198
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 199
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 200
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 201
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 202
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 203
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 204
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 205
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 206
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 207
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 208
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 209
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 210
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 211
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 212
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 213
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 214
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 215
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 216
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 217
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 218
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 219
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 220
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 221
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 222
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 223
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 224
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 225
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 226
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 227
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 228
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 229
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 230
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 231
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 232
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 233
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 234
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 235
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 236
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 237
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 238
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 239
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 240
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 241
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 242
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 243
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 244
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 245
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 246
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 247
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 248
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 249
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 250
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 251
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 252
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 253
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 254
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 255
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 256
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 257
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 258
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 259
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 260
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 261
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 262
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 263
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 264
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 265
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 266
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 267
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 268
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 269
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 270
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 271
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 272
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 273
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 274
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 275
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 276
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 277
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 278
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 279
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 280
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 281
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 282
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 283
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 284
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 285
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 286
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 287
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 288
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 289
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 290
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 291
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 292
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 293
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 294
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 295
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 296
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 297
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 298
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 299
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 300
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 301
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 302
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 303
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 304
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 305
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 306
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 307
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 308
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 309
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 310
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 311
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 312
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 313
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 314
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 315
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 316
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 317
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 318
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 319
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 320
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 321
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 322
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 323
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 324
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 325
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 326
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 327
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 328
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 329
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 330
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 331
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 332
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 333
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 334
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 335
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 336
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 337
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 338
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 339
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 340
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 341
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 342
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 343
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 344
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 345
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 346
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 347
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 348
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 349
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 350
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 351
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 352
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 353
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 354
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 355
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 356
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 357
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 358
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 359
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 360
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 361
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 362
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 363
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 364
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 365
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 366
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 367
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 368
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 369
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 370
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 371
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 372
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 373
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 374
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 375
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 376
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 377
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 378
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 379
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 380
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 381
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 382
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 383
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 384
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 385
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 386
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 387
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 388
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 389
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 390
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 391
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 392
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 393
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 394
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 395
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 396
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 397
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 398
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 399
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 400
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 401
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 402
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 403
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 404
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 405
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 406
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 407
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 408
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 409
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 410
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 411
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 412
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 413
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 414
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 415
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 416
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 417
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 418
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 419
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 420
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 421
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 422
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 423
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 424
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 425
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 426
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 427
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 428
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 429
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 430
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 431
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 432
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 433
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 434
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 435
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 436
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 437
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 438
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 439
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 440
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 441
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 442
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 443
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 444
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 445
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 446
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 447
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 448
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 449
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 450
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 451
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 452
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 453
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 454
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 455
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 456
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 457
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 458
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 459
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 460
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 461
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 462
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 463
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 464
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 465
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 466
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 467
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 468
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 469
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 470
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 471
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 472
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 473
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 474
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 475
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 476
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 477
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 478
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 479
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 480
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 481
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 482
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 483
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 484
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 485
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 486
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 487
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 488
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 489
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 490
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 491
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 492
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 493
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 494
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 495
       action: ansible.builtin.command git clone blah
-    - name: Executing git through command
+    - name: Executing git through command 496
       action: ansible.builtin.command git clone blah
diff -Nru ansible-lint-25.2.1/examples/playbooks/rule-args-module-fail.yml ansible-lint-25.6.1/examples/playbooks/rule-args-module-fail.yml
--- ansible-lint-25.2.1/examples/playbooks/rule-args-module-fail.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/rule-args-module-fail.yml	2025-06-19 09:30:13.000000000 +0200
@@ -16,7 +16,7 @@
         enabled: true
         masked: false
 
-    - name: Enable service httpd and ensure it is not masked
+    - name: Enable service httpd and ensure it is not masked 2
       # module should produce: 'Unsupported parameters for ansible.builtin.systemd module"
       ansible.builtin.systemd:
         foo: true
@@ -35,3 +35,11 @@
         path: /opt/software/deployment
         state: away
         mode: "0600"
+
+    - name: Mutually exclusive cmd and argv
+      # module should produce: 'arguments {"cmd", "argv"} are mutually exclusive'
+      ansible.builtin.command:
+        cmd: /bin/echo
+        argv:
+          - Hello
+      changed_when: false
diff -Nru ansible-lint-25.2.1/examples/playbooks/rule-command-instead-of-module-pass.yml ansible-lint-25.6.1/examples/playbooks/rule-command-instead-of-module-pass.yml
--- ansible-lint-25.2.1/examples/playbooks/rule-command-instead-of-module-pass.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/rule-command-instead-of-module-pass.yml	2025-06-19 09:30:13.000000000 +0200
@@ -46,7 +46,7 @@
       ansible.builtin.command: yum clean all
       changed_when: false
 
-    - name: Clear yum cache
+    - name: Clear yum cache (Empty command)
       ansible.builtin.command: ""
       changed_when: false
 
diff -Nru ansible-lint-25.2.1/examples/playbooks/rule_literal_compare_fail.yml ansible-lint-25.6.1/examples/playbooks/rule_literal_compare_fail.yml
--- ansible-lint-25.2.1/examples/playbooks/rule_literal_compare_fail.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/rule_literal_compare_fail.yml	2025-06-19 09:30:13.000000000 +0200
@@ -2,12 +2,12 @@
 - name: Fixture for literal-compare
   hosts: localhost
   tasks:
-    - name: Example task # <-- 1st
+    - name: Example task 1 # <-- 1st
       ansible.builtin.debug:
         msg: test
       when: my_var == True
 
-    - name: Example task # <-- 2nd
+    - name: Example task 2 # <-- 2nd
       ansible.builtin.debug:
         msg: test
       when: my_var == false
diff -Nru ansible-lint-25.2.1/examples/playbooks/rule_literal_compare_pass.yml ansible-lint-25.6.1/examples/playbooks/rule_literal_compare_pass.yml
--- ansible-lint-25.2.1/examples/playbooks/rule_literal_compare_pass.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/rule_literal_compare_pass.yml	2025-06-19 09:30:13.000000000 +0200
@@ -2,7 +2,7 @@
 - name: Fixture for literal-compare
   hosts: localhost
   tasks:
-    - name: Example task
+    - name: Example task 1
       ansible.builtin.debug:
         msg: test
       when: my_var
@@ -14,12 +14,12 @@
         - 1 + 1 == 2
         - true
 
-    - name: Example task
+    - name: Example task 2
       ansible.builtin.debug:
         msg: test
       when: not my_var
 
-    - name: Example task
+    - name: Example task 3
       ansible.builtin.debug:
         msg: test
       when: my_var not None
diff -Nru ansible-lint-25.2.1/examples/playbooks/rule-no-tabs.yml ansible-lint-25.6.1/examples/playbooks/rule-no-tabs.yml
--- ansible-lint-25.2.1/examples/playbooks/rule-no-tabs.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/rule-no-tabs.yml	2025-06-19 09:30:13.000000000 +0200
@@ -2,7 +2,7 @@
 - name: Fixture for no-tabs rule
   hosts: localhost
   tasks:
-    - name: Should not trigger no-tabs rules
+    - name: Should not trigger no-tabs rules 1
       ansible.builtin.lineinfile:
         path: some.txt
         regexp: ^\t$
@@ -13,7 +13,7 @@
     - name: Key has a tab
       ansible.builtin.debug:
         "ms\tg": "The associated key has \t and should trigger no-tabs here."
-    - name: Should not trigger no-tabs rules # noqa fqcn
+    - name: Should not trigger no-tabs rules 2 # noqa fqcn
       lineinfile:
         path: some.txt
         regexp: "^\t$"
@@ -24,7 +24,7 @@
     #     path: some.txt
     #     regexp: "^\t$"
     #     line: string with \t inside
-    - name: Should not trigger no-tabs rules
+    - name: Should not trigger no-tabs rules 3
       community.windows.win_lineinfile:
         path: some.txt
         regexp: "^\t$"
diff -Nru ansible-lint-25.2.1/examples/playbooks/rule-risky-shell-pipe-pass.yml ansible-lint-25.6.1/examples/playbooks/rule-risky-shell-pipe-pass.yml
--- ansible-lint-25.2.1/examples/playbooks/rule-risky-shell-pipe-pass.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/rule-risky-shell-pipe-pass.yml	2025-06-19 09:30:13.000000000 +0200
@@ -13,19 +13,19 @@
         false | cat
       changed_when: false
 
-    - name: Pipeline with pipefail, complex set
+    - name: Pipeline with pipefail, complex set - 1
       ansible.builtin.shell: |
         set -e -x -o pipefail
         false | cat
       changed_when: false
 
-    - name: Pipeline with pipefail, complex set
+    - name: Pipeline with pipefail, complex set - 2
       ansible.builtin.shell: |
         set -e -x -o pipefail
         false | cat
       changed_when: false
 
-    - name: Pipeline with pipefail, complex set
+    - name: Pipeline with pipefail, complex set - 3
       ansible.builtin.shell: |
         set -eo pipefail
         false | cat
diff -Nru ansible-lint-25.2.1/examples/playbooks/transform-jinja.transformed.yml ansible-lint-25.6.1/examples/playbooks/transform-jinja.transformed.yml
--- ansible-lint-25.2.1/examples/playbooks/transform-jinja.transformed.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/transform-jinja.transformed.yml	2025-06-19 09:30:13.000000000 +0200
@@ -13,7 +13,7 @@
             foo: "{{ 1 }}" # <-- jinja2[spacing]
             msg: "{{ 'a' b }}" # <-- jinja2[invalid]
 
-    - name: A block used to check that we do not identify error at correct level
+    - name: Another block used to check that we do not identify error at correct level
       block:
         - name: Foo # <-- this is valid jinja2
           ansible.builtin.debug:
diff -Nru ansible-lint-25.2.1/examples/playbooks/transform-jinja.yml ansible-lint-25.6.1/examples/playbooks/transform-jinja.yml
--- ansible-lint-25.2.1/examples/playbooks/transform-jinja.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/transform-jinja.yml	2025-06-19 09:30:13.000000000 +0200
@@ -13,7 +13,7 @@
             foo: "{{ 1  }}" # <-- jinja2[spacing]
             msg: "{{ 'a' b }}" # <-- jinja2[invalid]
 
-    - name: A block used to check that we do not identify error at correct level
+    - name: Another block used to check that we do not identify error at correct level
       block:
         - name: Foo # <-- this is valid jinja2
           ansible.builtin.debug:
diff -Nru ansible-lint-25.2.1/examples/playbooks/transform-no-free-form.transformed.yml ansible-lint-25.6.1/examples/playbooks/transform-no-free-form.transformed.yml
--- ansible-lint-25.2.1/examples/playbooks/transform-no-free-form.transformed.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/transform-no-free-form.transformed.yml	2025-06-19 09:30:13.000000000 +0200
@@ -8,7 +8,7 @@
         cmd: touch foo
       changed_when: false
 
-    - name: Create a placefolder file
+    - name: Create a placefolder file 2
       ansible.builtin.command: # <-- command can also go first
         chdir: /tmp
         cmd: touch bar
diff -Nru ansible-lint-25.2.1/examples/playbooks/transform-no-free-form.yml ansible-lint-25.6.1/examples/playbooks/transform-no-free-form.yml
--- ansible-lint-25.2.1/examples/playbooks/transform-no-free-form.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/transform-no-free-form.yml	2025-06-19 09:30:13.000000000 +0200
@@ -6,7 +6,7 @@
       ansible.builtin.command: chdir=/tmp touch foo # <-- don't use shorthand
       changed_when: false
 
-    - name: Create a placefolder file
+    - name: Create a placefolder file 2
       ansible.builtin.command: touch bar chdir=/tmp # <-- command can also go first
       changed_when: false
 
diff -Nru ansible-lint-25.2.1/examples/playbooks/vars/noqa_multiline.yml ansible-lint-25.6.1/examples/playbooks/vars/noqa_multiline.yml
--- ansible-lint-25.2.1/examples/playbooks/vars/noqa_multiline.yml	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/examples/playbooks/vars/noqa_multiline.yml	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,26 @@
+---
+# noqa: jinja[spacing]
+foo_postgresql_grafana_password_encoded: >-
+  {% if '!' in foo_postgresql_grafana_password or '#' in foo_postgresql_grafana_password %}
+  {{- ('\"\"\"' + foo_postgresql_grafana_password + '\"\"\"') | b64encode -}}
+  {% else %}
+  {{- foo_postgresql_grafana_password | b64encode -}}
+  {% endif %}
+
+# noqa: jinja[spacing]
+
+foo_postgresql_grafana_password_encoded_2: >-
+  {% if '!' in foo_postgresql_grafana_password or '#' in foo_postgresql_grafana_password %}
+  {{- ('\"\"\"' + foo_postgresql_grafana_password + '\"\"\"') | b64encode -}}
+  {% else %}
+  {{- foo_postgresql_grafana_password | b64encode -}}
+  {% endif %}
+
+inner:
+  # noqa: jinja[spacing]
+  foo_postgresql_grafana_password_encoded: >-
+    {% if '!' in foo_postgresql_grafana_password or '#' in foo_postgresql_grafana_password %}
+    {{- ('\"\"\"' + foo_postgresql_grafana_password + '\"\"\"') | b64encode -}}
+    {% else %}
+    {{- foo_postgresql_grafana_password | b64encode -}}
+    {% endif %}
diff -Nru ansible-lint-25.2.1/examples/playbooks/vars/strings.transformed.yml ansible-lint-25.6.1/examples/playbooks/vars/strings.transformed.yml
--- ansible-lint-25.2.1/examples/playbooks/vars/strings.transformed.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/examples/playbooks/vars/strings.transformed.yml	2025-06-19 09:30:13.000000000 +0200
@@ -5,13 +5,13 @@
 single: "single" # this is a comment
 single_with_double: '"single" quoted' # this is a comment
 
-single_multiline_with_octothorpe: "single over 160 char line to force wrapping. over 160 char line to force wrapping. over 160 char line to force wrapping. over 160\n
+single_multiline_with_octothorpe: "single over 160 char line to force wrapping. over 160 char line to force wrapping. over 160 char line to force wrapping. over 160\n\
   # this is not a comment"
 
 double: "double" # this is a comment
 double_with_single: "'double' quoted" # this is a comment
 
-double_multiline_with_octothorpe: "double over 160 char line to force wrapping. over 160 char line to force wrapping. over 160 char line to force wrapping. over 160\n
+double_multiline_with_octothorpe: "double over 160 char line to force wrapping. over 160 char line to force wrapping. over 160 char line to force wrapping. over 160\n\
   # this is not a comment"
 
 # this is a comment
diff -Nru ansible-lint-25.2.1/.git_archival.txt ansible-lint-25.6.1/.git_archival.txt
--- ansible-lint-25.2.1/.git_archival.txt	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.git_archival.txt	2025-06-19 09:30:13.000000000 +0200
@@ -1,4 +1,4 @@
-node: c16f018b1bdfdea6717f4b5b1b141a78b86021cd
-node-date: 2025-04-03T11:56:32Z
+node: 06f616d6e86e9ce4c74393318d1cbb2d016af413
+node-date: 2025-06-19T08:30:13+01:00
 describe-name: v25
-ref-names: HEAD -> main, tag: v25.2.1, tag: v25
+ref-names: tag: v25.6.1, tag: v25
diff -Nru ansible-lint-25.2.1/.github/lower-constraints.txt ansible-lint-25.6.1/.github/lower-constraints.txt
--- ansible-lint-25.2.1/.github/lower-constraints.txt	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.github/lower-constraints.txt	2025-06-19 09:30:13.000000000 +0200
@@ -9,7 +9,7 @@
 packaging==24.2 # Due to tox-uv
 pathspec==0.10.3
 pyyaml==6.0.2
-ruamel.yaml==0.18.5 # MIT
+ruamel.yaml==0.18.11 # MIT
 subprocess-tee==0.4.1 # MIT, used by ansible-compat
 # https://packages.ubuntu.com/noble/python3-wcmatch
 # https://packages.fedoraproject.org/pkgs/python-wcmatch/python3-wcmatch/
diff -Nru ansible-lint-25.2.1/.github/workflows/ack.yml ansible-lint-25.6.1/.github/workflows/ack.yml
--- ansible-lint-25.2.1/.github/workflows/ack.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.github/workflows/ack.yml	2025-06-19 09:30:13.000000000 +0200
@@ -1,7 +1,8 @@
 ---
 # See https://github.com/ansible/devtools/blob/main/.github/workflows/ack.yml
 name: ack
-"on":
+on:
+  merge_group:
   pull_request_target:
     types: [opened, labeled, unlabeled, synchronize]
 
diff -Nru ansible-lint-25.2.1/.github/workflows/tox.yml ansible-lint-25.6.1/.github/workflows/tox.yml
--- ansible-lint-25.2.1/.github/workflows/tox.yml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.github/workflows/tox.yml	2025-06-19 09:30:13.000000000 +0200
@@ -2,6 +2,7 @@
 name: tox
 
 on:
+  merge_group:
   push:
     branches:
       - "main"
@@ -155,12 +156,12 @@
         if: ${{ matrix.command5 }}
 
       - name: Archive logs
-        uses: actions/upload-artifact@v4
+        uses: coactions/upload-artifact@v4
         with:
           name: logs-${{ matrix.name }}.zip
           include-hidden-files: true
+          if-no-files-found: ignore
           path: |
-            .tox/**/log/
             .tox/**/.coverage*
             .tox/**/coverage.xml
 
@@ -259,7 +260,7 @@
           fi
 
       - name: Upload coverage data
-        uses: codecov/codecov-action@v5.4.0
+        uses: codecov/codecov-action@v5.4.3
         with:
           name: ${{ matrix.name }}
           # verbose: true # optional (default = false)
diff -Nru ansible-lint-25.2.1/.gitignore ansible-lint-25.6.1/.gitignore
--- ansible-lint-25.2.1/.gitignore	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.gitignore	2025-06-19 09:30:13.000000000 +0200
@@ -28,6 +28,7 @@
 
 # Unit test / coverage reports
 .tox
+junit.xml
 
 # Needed for CLI tests
 .sandbox
diff -Nru ansible-lint-25.2.1/.pre-commit-config.yaml ansible-lint-25.6.1/.pre-commit-config.yaml
--- ansible-lint-25.2.1/.pre-commit-config.yaml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.pre-commit-config.yaml	2025-06-19 09:30:13.000000000 +0200
@@ -17,6 +17,7 @@
     examples/broken/encoding.yml|
     examples/broken/encoding.j2|
     examples/broken/yaml-with-tabs/invalid-due-tabs.yaml|
+    examples/broken/load-failure-invalid.yml|
     examples/playbooks/collections/.*|
     examples/playbooks/vars/empty.transformed.yml|
     examples/playbooks/vars/empty.yml|
@@ -60,14 +61,14 @@
           - prettier@3.2.4
           - prettier-plugin-sort-json@3.1.0
   - repo: https://github.com/streetsidesoftware/cspell-cli
-    rev: v8.17.3
+    rev: v9.0.1
     hooks:
       - id: cspell
         # entry: codespell --relative
         args: [--relative, --no-progress, --no-summary]
         name: Spell check with cspell
   - repo: https://github.com/python-jsonschema/check-jsonschema
-    rev: 0.31.3
+    rev: 0.33.0
     hooks:
       - id: check-github-workflows
   - repo: https://github.com/pre-commit/pre-commit-hooks.git
@@ -117,7 +118,7 @@
         additional_dependencies:
           - tomli
   - repo: https://github.com/adrienverge/yamllint.git
-    rev: v1.36.2
+    rev: v1.37.1
     hooks:
       - id: yamllint
         exclude: >
@@ -144,17 +145,14 @@
       - id: tox-ini-fmt
 
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: v0.11.0
+    rev: v0.11.13
     hooks:
-      - id: ruff
-        args:
-          - --fix
-          - --exit-non-zero-on-fix
-        types_or: [python, pyi]
-      # - id: ruff-format # must be after ruff
-      #   types_or: [python, pyi]
+      - id: ruff-format
+        alias: ruff
+      - id: ruff-check
+        alias: ruff
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v1.15.0
+    rev: v1.16.1
     hooks:
       - id: mypy
         # "." and pass_files are used to make pre-commit mypy behave the same as standalone mypy
@@ -180,12 +178,12 @@
           - wcmatch
           - yamllint>=1.34.0
   - repo: https://github.com/RobertCraigie/pyright-python
-    rev: v1.1.398
+    rev: v1.1.402
     hooks:
       - id: pyright
         additional_dependencies: *deps
   - repo: https://github.com/pycqa/pylint
-    rev: v3.3.6
+    rev: v3.3.7
     hooks:
       - id: pylint
         args:
diff -Nru ansible-lint-25.2.1/.prettierignore ansible-lint-25.6.1/.prettierignore
--- ansible-lint-25.2.1/.prettierignore	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/.prettierignore	2025-06-19 09:30:13.000000000 +0200
@@ -28,6 +28,7 @@
 
 # Unit test / coverage reports
 .tox
+junit.xml
 
 # Needed for CLI tests
 .sandbox
diff -Nru ansible-lint-25.2.1/pyproject.toml ansible-lint-25.6.1/pyproject.toml
--- ansible-lint-25.2.1/pyproject.toml	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/pyproject.toml	2025-06-19 09:30:13.000000000 +0200
@@ -15,10 +15,8 @@
   "Intended Audience :: Developers",
   "Intended Audience :: Information Technology",
   "Intended Audience :: System Administrators",
-  "License :: OSI Approved :: MIT License",
   "Operating System :: MacOS",
   "Operating System :: POSIX",
-  "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
   "Programming Language :: Python :: 3",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
@@ -34,7 +32,7 @@
 description = "Checks playbooks for practices and behavior that could potentially be improved"
 dynamic = ["version", "dependencies", "optional-dependencies"]
 keywords = ["ansible", "lint"]
-license = {text = "GPLv3+"}
+license = "GPL-3.0-or-later"
 maintainers = [{"email" = "info@ansible.com", "name" = "Ansible by Red Hat"}]
 name = "ansible-lint"
 readme = "README.md"
@@ -63,7 +61,7 @@
 [tool.coverage.report]
 exclude_also = ["pragma: no cover", "if TYPE_CHECKING:"]
 # Increase it just so it would pass on any single-python run
-fail_under = 95
+fail_under = 93
 # During development we might remove code (files) with coverage data, and we dont want to fail:
 ignore_errors = true
 omit = ["test/*"]
@@ -73,10 +71,9 @@
 skip_empty = true
 
 [tool.coverage.run]
+# branch is more reliable than lines, protects against false positives
+branch = true
 concurrency = ["multiprocessing", "thread"]
-# Do not use branch until bug is fixes:
-# https://github.com/nedbat/coveragepy/issues/605
-# branch = true
 parallel = true
 source = ["src"]
 
@@ -411,11 +408,7 @@
   # https://github.com/ansible/ansible/pull/80968
   "ignore:Attribute s is deprecated and will be removed in Python 3.14; use value instead:DeprecationWarning"
 ]
-junit_duration_report = "call"
-junit_family = "xunit1"
-# Our github annotation parser from .github/workflows/tox.yml requires xunit1 format. Ref:
-# https://github.com/shyim/junit-report-annotations-action/issues/3#issuecomment-663241378
-junit_suite_name = "ansible_lint_test_suite"
+junit_family = "legacy"
 minversion = "4.6.6"
 # https://code.visualstudio.com/docs/python/testing
 # coverage is re-enabled in `tox.ini`. That approach is safer than
@@ -501,6 +494,7 @@
   "FURB110",
   "FURB113",
   "FURB118",
+  "PLC0207", # maxsplit with [-1] preview rule
   "PLC0415",
   "PLC2701",
   "PLW1641",
diff -Nru ansible-lint-25.2.1/src/ansiblelint/cli.py ansible-lint-25.6.1/src/ansiblelint/cli.py
--- ansible-lint-25.2.1/src/ansiblelint/cli.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/cli.py	2025-06-19 09:30:13.000000000 +0200
@@ -61,7 +61,9 @@
         config[paths_var] = normalized_paths
 
 
-def load_config(config_file: str | None) -> tuple[dict[Any, Any], str | None]:
+def load_config(
+    config_file: str | None = None, project_path: str | None = None
+) -> tuple[dict[Any, Any], str | None]:
     """Load configuration from disk."""
     config_path = None
 
@@ -74,7 +76,7 @@
         if not os.path.exists(config_path):
             _logger.error("Config file not found '%s'", config_path)
             sys.exit(RC.INVALID_CONFIG)
-    config_path = config_path or get_config_path()
+    config_path = config_path or get_config_path(None, project_path=project_path)
     if not config_path or not os.path.exists(config_path):
         # a missing default config file should not trigger an error
         return {}, None
@@ -100,7 +102,9 @@
     return config, config_path
 
 
-def get_config_path(config_file: str | None = None) -> str | None:
+def get_config_path(
+    config_file: str | None = None, project_path: str | None = None
+) -> str | None:
     """Return local config file."""
     if config_file:
         project_filenames = [config_file]
@@ -112,7 +116,7 @@
             ".config/ansible-lint.yml",
             ".config/ansible-lint.yaml",
         ]
-    parent = tail = os.getcwd()
+    parent = tail = project_path or os.getcwd()
     while tail:
         for project_filename in project_filenames:
             filename = os.path.abspath(os.path.join(parent, project_filename))
@@ -460,8 +464,8 @@
     parser.add_argument(
         "--offline",
         dest="offline",
-        action="store_const",
-        const=True,
+        action=argparse.BooleanOptionalAction,
+        default=False,
         help="Disable installation of requirements.yml and schema refreshing",
     )
     parser.add_argument(
@@ -595,7 +599,9 @@
         )
 
     # save info about custom config file, as options.config_file may be modified by merge_config
-    file_config, options.config_file = load_config(options.config_file)
+    file_config, options.config_file = load_config(
+        options.config_file, project_path=options.project_dir
+    )
     config = merge_config(file_config, options)
 
     options.rulesdirs = get_rules_dirs(
diff -Nru ansible-lint-25.2.1/src/ansiblelint/formatters/__init__.py ansible-lint-25.6.1/src/ansiblelint/formatters/__init__.py
--- ansible-lint-25.2.1/src/ansiblelint/formatters/__init__.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/formatters/__init__.py	2025-06-19 09:30:13.000000000 +0200
@@ -96,7 +96,7 @@
         result = (
             f"[repr.path]{self._format_path(match.filename or '')}[/][dim]:{match.position}:[/] "
             f"[{match.level}][bold]{self.escape(match.tag)}[/]"
-            f"{ f': {match.message}' if not options.quiet else '' }[/]"
+            f"{f': {match.message}' if not options.quiet else ''}[/]"
         )
         if match.level != "error":
             result += f" [dim][{match.level}]({match.level})[/][/]"
@@ -307,9 +307,9 @@
             ],
         }
         if match.column:
-            result["locations"][0]["physicalLocation"]["region"][
-                "startColumn"
-            ] = match.column
+            result["locations"][0]["physicalLocation"]["region"]["startColumn"] = (
+                match.column
+            )
         return result
 
     @staticmethod
diff -Nru ansible-lint-25.2.1/src/ansiblelint/loaders.py ansible-lint-25.6.1/src/ansiblelint/loaders.py
--- ansible-lint-25.2.1/src/ansiblelint/loaders.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/loaders.py	2025-06-19 09:30:13.000000000 +0200
@@ -2,6 +2,7 @@
 
 from __future__ import annotations
 
+import enum
 import logging
 import os
 from collections import defaultdict
@@ -28,6 +29,19 @@
     alternative: str
 
 
+class IgnoreRuleQualifier(enum.Enum):
+    """Extra flags for ignored rules."""
+
+    SKIP = "Force skip, not warning"
+
+
+class IgnoreRule(NamedTuple):
+    """Ignored rule."""
+
+    rule: str
+    qualifiers: frozenset[IgnoreRuleQualifier]
+
+
 IGNORE_FILE = IgnoreFile(".ansible-lint-ignore", ".config/ansible-lint-ignore.txt")
 
 yaml_load = partial(yaml.load, Loader=FullLoader)
@@ -41,7 +55,19 @@
         return yaml_load(content)
 
 
-def load_ignore_txt(filepath: Path | None = None) -> dict[str, set[str]]:
+def get_ignore_rule(rule: str, qualifiers: str) -> IgnoreRule:
+    """Validate qualifiers and return an IgnoreRule."""
+    s = set()
+    if qualifiers:
+        for q in qualifiers.split(","):
+            if q == "skip":
+                s.add(IgnoreRuleQualifier.SKIP)
+            else:
+                raise ValueError
+    return IgnoreRule(rule, frozenset(s))
+
+
+def load_ignore_txt(filepath: Path | None = None) -> dict[str, set[IgnoreRule]]:
     """Return a list of rules to ignore."""
     result = defaultdict(set)
 
@@ -64,17 +90,21 @@
                 entry = line.split("#")[0].rstrip()
                 if entry:
                     try:
-                        path, rule = entry.split()
+                        fields = entry.split()
+                        path = fields[0]
+                        rule = fields[1]
+                        qualifiers = fields[2] if len(fields) == 3 else ""
+                        result[path].add(get_ignore_rule(rule, qualifiers))
                     except ValueError as exc:  # pragma: no cover
                         msg = f"Unable to parse line '{line}' from {ignore_file} file."
                         raise RuntimeError(msg) from exc
-                    result[path].add(rule)
-
     return result
 
 
 __all__ = [
     "IGNORE_FILE",
+    "IgnoreRule",
+    "IgnoreRuleQualifier",
     "YAMLError",
     "load_ignore_txt",
     "yaml_from_file",
diff -Nru ansible-lint-25.2.1/src/ansiblelint/__main__.py ansible-lint-25.6.1/src/ansiblelint/__main__.py
--- ansible-lint-25.2.1/src/ansiblelint/__main__.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/__main__.py	2025-06-19 09:30:13.000000000 +0200
@@ -57,7 +57,7 @@
     log_entries,
     options,
 )
-from ansiblelint.loaders import load_ignore_txt
+from ansiblelint.loaders import IgnoreRule, IgnoreRuleQualifier, load_ignore_txt
 from ansiblelint.output import (
     console,
     console_stderr,
@@ -272,6 +272,19 @@
         result.matches.pop(idx)
 
 
+# By default, matches ignored in .ansible-lint-ignore are treated
+# as warnings [1].  If the user explicitly adds a skip qualifier
+# to the rule, it is treated as skipped here and does not show up
+# even as a warning.
+# [1] https://github.com/ansible/ansible-lint/issues/3068
+def _rule_is_skipped(tag: str, rules: set[IgnoreRule]) -> bool:
+    for rule in rules:
+        if tag != rule.rule:
+            return False
+        return IgnoreRuleQualifier.SKIP in rule.qualifiers
+    return False
+
+
 # pylint: disable=too-many-locals,too-many-statements
 def main(argv: list[str] | None = None) -> int:
     """Linter CLI entry point."""
@@ -376,10 +389,17 @@
 
     # Remove skip_list items from the result
     result.matches = [m for m in result.matches if m.tag not in app.options.skip_list]
-    # Mark matches as ignored inside ignore file
+    # load ignore file
     ignore_map = load_ignore_txt(options.ignore_file)
+    # prune qualified skips from ignore file
+    result.matches = [
+        m for m in result.matches if not _rule_is_skipped(m.tag, ignore_map[m.filename])
+    ]
+    # others entries are ignored
     for match in result.matches:
-        if match.tag in ignore_map[match.filename]:  # pragma: no cover
+        if match.tag in [
+            i.rule for i in ignore_map[match.filename]
+        ]:  # pragma: no cover
             match.ignored = True
             _logger.debug("Ignored: %s", match)
 
diff -Nru ansible-lint-25.2.1/src/ansiblelint/requirements.py ansible-lint-25.6.1/src/ansiblelint/requirements.py
--- ansible-lint-25.2.1/src/ansiblelint/requirements.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/requirements.py	2025-06-19 09:30:13.000000000 +0200
@@ -13,10 +13,12 @@
 
     def __init__(self, name: str = "ansible-lint") -> None:
         """Load linter metadata requirements."""
-        for req_str in importlib_metadata.metadata(name).json["requires_dist"]:
-            req = Requirement(req_str)
-            if req.name:
-                self[req.name] = req.specifier
+        metadata = importlib_metadata.metadata(name)
+        if metadata:
+            for req_str in metadata.json["requires_dist"]:
+                req = Requirement(req_str)
+                if req.name:
+                    self[req.name] = req.specifier
 
     def matches(self, req_name: str, req_version: str | Version) -> bool:
         """Verify if given version is matching current metadata dependencies."""
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/args.md ansible-lint-25.6.1/src/ansiblelint/rules/args.md
--- ansible-lint-25.2.1/src/ansiblelint/rules/args.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/args.md	2025-06-19 09:30:13.000000000 +0200
@@ -40,6 +40,13 @@
           - my_param <= 100
           - my_param >= 0
         quiet: invalid # <- Value for option `quiet` is invalid.
+
+    - name: Do not use mutually exclusive arguments together
+      ansible.builtin.command:
+        cmd: /bin/echo # <- cmd and argv are mutually exclusive options
+        argv:
+          - Hello
+      when_changed: false
 ```
 
 ## Correct Code
@@ -69,6 +76,18 @@
           - my_param <= 100
           - my_param >= 0
         quiet: True # <- Has correct type value for option `quiet` which is boolean.
+
+    - name: Do not use mutually exclusive arguments together
+      ansible.builtin.command:
+        cmd: "/bin/echo Hello" # <- Does not use `cmd` and `argv`
+      when_changed: false
+
+    - name: Do not use mutually exclusive arguments together alternative
+      ansible.builtin.command:
+        argv: # <- Does not use `cmd` and `argv`
+          - /bin/echo
+          - Hello
+      when_changed: false
 ```
 
 ## Special cases
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/args.py ansible-lint-25.6.1/src/ansiblelint/rules/args.py
--- ansible-lint-25.2.1/src/ansiblelint/rules/args.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/args.py	2025-06-19 09:30:13.000000000 +0200
@@ -64,6 +64,10 @@
     # https://github.com/ansible/ansible-lint/issues/2824
     "ansible.builtin.async_status": {"_async_dir": "/tmp/ansible-async"},
 }
+workarounds_mutex_args_map = {
+    # https://github.com/ansible/ansible-lint/issues/4623
+    "ansible.builtin.command": [{"cmd", "argv"}],
+}
 
 
 class ValidationPassedError(Exception):
@@ -136,6 +140,19 @@
 
         if loaded_module.resolved_fqcn in workarounds_inject_map:
             module_args.update(workarounds_inject_map[loaded_module.resolved_fqcn])
+        if loaded_module.resolved_fqcn in workarounds_mutex_args_map:
+            results.extend(
+                self.create_matcherror(
+                    message=f"Module arguments {mutex_set} are mutually exclusive",
+                    lineno=task.line,
+                    tag="args[module]",
+                    filename=file,
+                )
+                for mutex_set in workarounds_mutex_args_map[loaded_module.resolved_fqcn]
+                if len(mutex_set - module_args.keys()) < len(mutex_set) - 1
+            )
+            if results:
+                return self._sanitize_results(results, module_name)
         if loaded_module.resolved_fqcn in workarounds_drop_map:
             for key in workarounds_drop_map[loaded_module.resolved_fqcn]:
                 module_args.pop(key, None)
@@ -287,7 +304,7 @@
         """Test rule invalid module options."""
         success = "examples/playbooks/rule-args-module-fail.yml"
         results = Runner(success, rules=default_rules_collection).run()
-        assert len(results) == 5
+        assert len(results) == 6
         assert results[0].tag == "args[module]"
         # First part of regex is for ansible-core up to 2.18, second part is for ansible-core 2.19+
         assert re.match(
@@ -311,6 +328,8 @@
         )
         assert results[4].tag == "args[module]"
         assert "value of state must be one of" in results[4].message
+        assert results[5].tag == "args[module]"
+        assert "are mutually exclusive" in results[5].message
 
     def test_args_module_pass(
         default_rules_collection: RulesCollection,
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/inline_env_var.py ansible-lint-25.6.1/src/ansiblelint/rules/inline_env_var.py
--- ansible-lint-25.2.1/src/ansiblelint/rules/inline_env_var.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/inline_env_var.py	2025-06-19 09:30:13.000000000 +0200
@@ -44,9 +44,11 @@
     version_changed = "5.0.11"
 
     expected_args = [
+        "argv",
         "chdir",
         "creates",
         "executable",
+        "expand_argument_vars",
         "removes",
         "stdin",
         "stdin_add_newline",
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/name.md ansible-lint-25.6.1/src/ansiblelint/rules/name.md
--- ansible-lint-25.2.1/src/ansiblelint/rules/name.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/name.md	2025-06-19 09:30:13.000000000 +0200
@@ -15,10 +15,15 @@
   helps with the identification of tasks inside the source code when they fail.
   The use of templating inside `name` keys is discouraged as there are multiple
   cases where the rendering of the name template is not possible.
+- `name[unique]` - All task names within a single play should be unique.
 
 If you want to ignore some of the messages above, you can add any of them to the
 `skip_list`.
 
+## name[unique]
+
+This check ensures that every task name is unique within the same play. This includes tasks defined in the `pre_tasks`, `tasks`, `post_tasks`, and `handlers` sections. Having unique names is crucial for reliably using features like `--start-at-task` and makes playbook execution easier to follow and debug.
+
 ## name[prefix]
 
 This rule applies only to included task files that are not named `main.yml` or
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/name.py ansible-lint-25.6.1/src/ansiblelint/rules/name.py
--- ansible-lint-25.2.1/src/ansiblelint/rules/name.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/name.py	2025-06-19 09:30:13.000000000 +0200
@@ -39,8 +39,47 @@
         "name[prefix]": "Task name should start with a prefix.",
         "name[casing]": "All names should start with an uppercase letter.",
         "name[template]": "Jinja templates should only be at the end of 'name'",
+        "name[unique]": "Task names should be unique within a play.",
     }
 
+    def _check_unique_task_names(
+        self,
+        tasks: list[MutableMapping[str, Any]],
+        seen_names: dict[str, int],
+        file: Lintable,
+    ) -> list[MatchError]:
+        """Helper function to iterate through a list of tasks and check for duplicates."""
+        errors: list[MatchError] = []
+        if not tasks:
+            return errors
+
+        for task in tasks:
+            # We skip tasks without a name, as that is covered by the 'name[missing]' rule.
+            task_name = task.get("name")
+            if not task_name:
+                continue
+
+            # If a task-like dict lacks a line number, we cannot perform the uniqueness check, so we skip it.
+            if "__line__" not in task:
+                continue
+
+            # The linter adds '__line__' to each task dictionary.
+            lineno = task["__line__"]
+
+            if task_name in seen_names:
+                message = f"Task name '{task_name}' is not unique. It was first used on line {seen_names[task_name]}."
+                errors.append(
+                    self.create_matcherror(
+                        message=message,
+                        lineno=lineno,
+                        filename=file,
+                        tag="name[unique]",
+                    )
+                )
+            else:
+                seen_names[task_name] = lineno
+        return errors
+
     def matchplay(self, file: Lintable, data: dict[str, Any]) -> list[MatchError]:
         """Return matches found for a specific play (entry in playbook)."""
         results: list[MatchError] = []
@@ -48,6 +87,8 @@
             return []
         if file.failed():  # pragma: no cover
             return results
+
+        # Check if the play itself is named
         if "name" not in data:
             return [
                 self.create_matcherror(
@@ -64,6 +105,17 @@
                 data=data,
             ),
         )
+
+        # Check for unique task names within this play
+        seen_task_names: dict[str, int] = {}
+        task_sections = ["pre_tasks", "tasks", "post_tasks", "handlers"]
+        for section in task_sections:
+            tasks = data.get(section, [])
+            if tasks:
+                results.extend(
+                    self._check_unique_task_names(tasks, seen_task_names, file)
+                )
+
         return results
 
     def matchtask(
@@ -71,6 +123,7 @@
         task: Task,
         file: Lintable | None = None,
     ) -> list[MatchError]:
+        """Check rules for a single task."""
         results: list[MatchError] = []
         if file and file.failed():  # pragma: no cover
             return results
@@ -153,7 +206,8 @@
                     effective_name = name[len(prefix) :]
 
         if (
-            effective_name[0].isalpha()
+            effective_name
+            and effective_name[0].isalpha()
             and effective_name[0].islower()
             and not effective_name[0].isupper()
         ):
@@ -204,7 +258,7 @@
             lintable_dir = lintable_dir.parent
             pathex = lintable_dir / stem
 
-        if stems[0].startswith(kind):
+        if stems and stems[0].startswith(kind):
             del stems[0]
         return str(wcmatch.pathlib.PurePath(*stems, stem))
 
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/no_log_password.md ansible-lint-25.6.1/src/ansiblelint/rules/no_log_password.md
--- ansible-lint-25.2.1/src/ansiblelint/rules/no_log_password.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/no_log_password.md	2025-06-19 09:30:13.000000000 +0200
@@ -6,6 +6,14 @@
 While most Ansible modules mask sensitive data, using secrets inside a loop can result in those secrets being logged.
 Explicitly adding `no_log: true` prevents accidentally exposing secrets.
 
+This is an opt-in rule.
+You must enable it in your Ansible-lint configuration as follows:
+
+```yaml
+enable_list:
+  - no-log-password
+```
+
 ## Problematic Code
 
 ```yaml
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/package_latest.md ansible-lint-25.6.1/src/ansiblelint/rules/package_latest.md
--- ansible-lint-25.2.1/src/ansiblelint/rules/package_latest.md	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/package_latest.md	2025-06-19 09:30:13.000000000 +0200
@@ -2,7 +2,7 @@
 
 This rule checks that package managers install software in a controlled, safe manner.
 
-Package manager modules, such as `ansible.builtin.yum`, include a `state` parameter that configures how Ansible installs software.
+Package manager modules, such as `ansible.builtin.dnf`, include a `state` parameter that configures how Ansible installs software.
 In production environments, you should set `state` to `present` and specify a target version to ensure that packages are installed to a planned and tested version.
 
 Setting `state` to `latest` not only installs software, it performs an update and installs additional packages.
@@ -17,7 +17,7 @@
   hosts: localhost
   tasks:
     - name: Install Ansible
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: ansible
         state: latest # <- Installs the latest package.
 
@@ -33,7 +33,7 @@
         state: latest # <- Installs the latest package.
 
     - name: Install sudo with update_only to false
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: sudo
         state: latest
         update_only: false # <- Updates and installs packages.
@@ -53,9 +53,9 @@
   hosts: localhost
   tasks:
     - name: Install Ansible
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: ansible-2.12.7.0
-        state: present # <- Pins the version to install with yum.
+        state: present # <- Pins the version to install with dnf.
 
     - name: Install Ansible-lint
       ansible.builtin.pip:
@@ -70,7 +70,7 @@
         state: present # <- Ensures the package is installed.
 
     - name: Update sudo with update_only to true
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         name: sudo
         state: latest
         update_only: true # <- Updates but does not install additional packages.
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/package_latest.py ansible-lint-25.6.1/src/ansiblelint/rules/package_latest.py
--- ansible-lint-25.2.1/src/ansiblelint/rules/package_latest.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/package_latest.py	2025-06-19 09:30:13.000000000 +0200
@@ -81,5 +81,6 @@
             and not task["action"].get("version")
             and not task["action"].get("update_only")
             and not task["action"].get("only_upgrade")
+            and not task["action"].get("download_only")
             and task["action"].get("state") == "latest"
         )
diff -Nru ansible-lint-25.2.1/src/ansiblelint/rules/risky_octal.py ansible-lint-25.6.1/src/ansiblelint/rules/risky_octal.py
--- ansible-lint-25.2.1/src/ansiblelint/rules/risky_octal.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/rules/risky_octal.py	2025-06-19 09:30:13.000000000 +0200
@@ -38,8 +38,7 @@
 
     id = "risky-octal"
     description = (
-        "Numeric file permissions without leading zero can behave "
-        "in unexpected ways."
+        "Numeric file permissions without leading zero can behave in unexpected ways."
     )
     link = "https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html";
     severity = "VERY_HIGH"
diff -Nru ansible-lint-25.2.1/src/ansiblelint/runner.py ansible-lint-25.6.1/src/ansiblelint/runner.py
--- ansible-lint-25.2.1/src/ansiblelint/runner.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/runner.py	2025-06-19 09:30:13.000000000 +0200
@@ -23,6 +23,9 @@
 from ansible.parsing.splitter import split_args
 from ansible.plugins.loader import add_all_plugin_dirs
 from ansible_compat.runtime import AnsibleWarning
+from ruamel.yaml.parser import ParserError as RuamelParserError
+from yaml.parser import ParserError
+from yaml.scanner import ScannerError
 
 import ansiblelint.skip_utils
 import ansiblelint.utils
@@ -213,14 +216,33 @@
                 self.lintables.remove(lintable)
                 continue
             if isinstance(lintable.data, States) and lintable.exc:
+                line = 1
+                column = None
+                detail = ""
+                sub_tag = ""
                 lintable.exc.__class__.__name__.lower()
+                message = None
+                if lintable.exc.__cause__ and isinstance(
+                    lintable.exc.__cause__,
+                    ScannerError | ParserError | RuamelParserError,
+                ):
+                    sub_tag = "yaml"
+                    if isinstance(lintable.exc.args, tuple):
+                        message = lintable.exc.args[0]
+                    detail = lintable.exc.__cause__.problem
+                    if lintable.exc.__cause__.problem_mark:
+                        line = lintable.exc.__cause__.problem_mark.line + 1
+                        column = lintable.exc.__cause__.problem_mark.column + 1
+
                 matches.append(
                     MatchError(
                         lintable=lintable,
-                        message=str(lintable.exc),
-                        details=str(lintable.exc.__cause__),
+                        message=message or str(lintable.exc),
+                        details=detail or str(lintable.exc.__cause__),
                         rule=self.rules["load-failure"],
-                        tag=f"load-failure[{lintable.exc.__class__.__name__.lower()}]",
+                        lineno=line,
+                        column=column,
+                        tag=f"load-failure[{sub_tag or lintable.exc.__class__.__name__.lower()}]",
                     ),
                 )
                 lintable.stop_processing = True
diff -Nru ansible-lint-25.2.1/src/ansiblelint/schemas/ansible-navigator.json ansible-lint-25.6.1/src/ansiblelint/schemas/ansible-navigator.json
--- ansible-lint-25.2.1/src/ansiblelint/schemas/ansible-navigator.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/schemas/ansible-navigator.json	2025-06-19 09:30:13.000000000 +0200
@@ -287,7 +287,7 @@
           "$ref": "#/$defs/EnvironmentVariablesModel"
         },
         "image": {
-          "default": "quay.io/ansible/creator-ee:v0.2.0",
+          "default": "ghcr.io/ansible/community-ansible-dev-tools:latest",
           "description": "Specify the name of the execution environment image",
           "title": "Image",
           "type": "string"
diff -Nru ansible-lint-25.2.1/src/ansiblelint/schemas/meta.json ansible-lint-25.6.1/src/ansiblelint/schemas/meta.json
--- ansible-lint-25.2.1/src/ansiblelint/schemas/meta.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/schemas/meta.json	2025-06-19 09:30:13.000000000 +0200
@@ -378,6 +378,7 @@
               "39",
               "40",
               "41",
+              "42",
               "all"
             ],
             "type": "string"
@@ -875,6 +876,7 @@
               "21.02",
               "22.03",
               "23.05",
+              "24.10",
               "all"
             ],
             "type": "string"
@@ -1014,6 +1016,7 @@
               "15SP3",
               "15SP4",
               "15SP5",
+              "15SP6",
               "all"
             ],
             "type": "string"
@@ -1129,6 +1132,8 @@
               "maverick",
               "natty",
               "oneiric",
+              "oracular",
+              "plucky",
               "precise",
               "quantal",
               "raring",
@@ -1504,7 +1509,7 @@
         "versions": {
           "default": "all",
           "items": {
-            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "all"],
+            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "8.0", "all"],
             "type": "string"
           },
           "type": "array"
@@ -1523,7 +1528,7 @@
         "versions": {
           "default": "all",
           "items": {
-            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "all"],
+            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "8.0", "all"],
             "type": "string"
           },
           "type": "array"
diff -Nru ansible-lint-25.2.1/src/ansiblelint/schemas/__store__.json ansible-lint-25.6.1/src/ansiblelint/schemas/__store__.json
--- ansible-lint-25.2.1/src/ansiblelint/schemas/__store__.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/schemas/__store__.json	2025-06-19 09:30:13.000000000 +0200
@@ -24,7 +24,7 @@
     "url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/inventory.json";
   },
   "meta": {
-    "etag": "62cce45a9b8bd96872d8ee1c465d3ff6b60facf6a4aeba5c2e128df02b5f52a5",
+    "etag": "60f3ce2a78ec4fb705c589da409a384ac97315e17810379c5049169986ce3097",
     "url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/meta.json";
   },
   "meta-runtime": {
diff -Nru ansible-lint-25.2.1/src/ansiblelint/skip_utils.py ansible-lint-25.6.1/src/ansiblelint/skip_utils.py
--- ansible-lint-25.2.1/src/ansiblelint/skip_utils.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/skip_utils.py	2025-06-19 09:30:13.000000000 +0200
@@ -55,7 +55,8 @@
 
 _logger = logging.getLogger(__name__)
 _found_deprecated_tags: set[str] = set()
-_noqa_comment_re = re.compile(r"^# noqa(\s|:)")
+_noqa_comment_re = re.compile(r"^\s*# noqa(\s|:)", flags=re.MULTILINE)
+_noqa_comment_line_re = re.compile(r"^\s*# noqa(\s|:).*$")
 
 # playbook: Sequence currently expects only instances of one of the two
 # classes below but we should consider avoiding this chimera.
@@ -257,6 +258,28 @@
         yield task
 
 
+def _continue_skip_next_lines(
+    lintable: Lintable,
+) -> None:
+    """When a line only contains a noqa comment (and possibly indentation), add the skip also to the next non-empty line."""
+    # If line starts with _noqa_comment_line_re, add next non-empty line to same lintable.line_skips
+    line_content = lintable.content.splitlines()
+    for line_no in list(lintable.line_skips.keys()):
+        if _noqa_comment_line_re.fullmatch(line_content[line_no - 1]):
+            # Find next non-empty line
+            next_line_no = line_no
+            while (
+                next_line_no < len(line_content)
+                and not line_content[next_line_no].strip()
+            ):
+                next_line_no += 1
+            if next_line_no >= len(line_content):
+                continue
+            lintable.line_skips[next_line_no + 1].update(
+                lintable.line_skips[line_no],
+            )
+
+
 def _get_rule_skips_from_yaml(
     yaml_input: Sequence[Any],
     lintable: Lintable,
@@ -268,7 +291,17 @@
         return []
 
     def traverse_yaml(obj: Any) -> None:
-        for entry in obj.ca.items.values():
+        traversable = list(obj.ca.items.values())
+        if obj.ca.comment:
+            traversable.append(obj.ca.comment)
+        for entry in traversable:
+            # flatten all lists we might have in entries. Some arcane ruamel CommentedMap magic
+            entry = [
+                item
+                for sublist in entry
+                if sublist is not None
+                for item in (sublist if isinstance(sublist, list) else [sublist])
+            ]
             for v in entry:
                 if isinstance(v, CommentToken):
                     comment_str = v.value
@@ -298,6 +331,7 @@
     for comment_obj_str in yaml_comment_obj_strings:
         for line in comment_obj_str.split(r"\n"):
             rule_id_list.extend(get_rule_skips_from_line(line, lintable=lintable))
+    _continue_skip_next_lines(lintable)
 
     return [normalize_tag(tag) for tag in rule_id_list]
 
diff -Nru ansible-lint-25.2.1/src/ansiblelint/utils.py ansible-lint-25.6.1/src/ansiblelint/utils.py
--- ansible-lint-25.2.1/src/ansiblelint/utils.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/utils.py	2025-06-19 09:30:13.000000000 +0200
@@ -523,11 +523,11 @@
             for loc in self.app.runtime.config.collections_paths:
                 append_playbook_path(
                     loc,
-                    playbook_path[:-1] + [f"{playbook_path[-1]}.yml"],
+                    [*playbook_path[:-1], f"{playbook_path[-1]}.yml"],
                 )
                 append_playbook_path(
                     loc,
-                    playbook_path[:-1] + [f"{playbook_path[-1]}.yaml"],
+                    [*playbook_path[:-1], f"{playbook_path[-1]}.yaml"],
                 )
         else:
             possible_paths.append(lintable.path.parent / v)
@@ -568,22 +568,29 @@
 
     def _rolepath(self, basedir: str, role: str) -> str | None:
         role_path = None
-        namespace_name, collection_name, role_name = parse_fqcn(role)
+        namespace_name, collection_name, *role_name = parse_fqcn(role)
 
         possible_paths = [
             # if included from a playbook
-            path_dwim(basedir, os.path.join("roles", role_name)),
-            path_dwim(basedir, role_name),
+            path_dwim(basedir, os.path.join("roles", role_name[-1])),
+            path_dwim(basedir, role_name[-1]),
             # if included from roles/[role]/meta/main.yml
-            path_dwim(basedir, os.path.join("..", "..", "..", "roles", role_name)),
-            path_dwim(basedir, os.path.join("..", "..", role_name)),
+            path_dwim(basedir, os.path.join("..", "..", "..", "roles", role_name[-1])),
+            path_dwim(basedir, os.path.join("..", "..", role_name[-1])),
             # if checking a role in the current directory
-            path_dwim(basedir, os.path.join("..", role_name)),
+            path_dwim(basedir, os.path.join("..", role_name[-1])),
         ]
+        if len(role_name) > 1:
+            # This ignores deeper structures than 1 level
+            possible_paths.append(path_dwim(basedir, os.path.join("roles", *role_name)))
+            possible_paths.append(path_dwim(basedir, os.path.join(*role_name)))
+            possible_paths.append(
+                path_dwim(basedir, os.path.join("..", "..", *role_name))
+            )
 
         for loc in self.app.runtime.config.default_roles_path:
             loc = os.path.expanduser(loc)
-            possible_paths.append(path_dwim(loc, role_name))
+            possible_paths.append(path_dwim(loc, role_name[-1]))
 
         if namespace_name and collection_name:
             for loc in get_app(cached=True).runtime.config.collections_paths:
@@ -596,7 +603,7 @@
                             namespace_name,
                             collection_name,
                             "roles",
-                            role_name,
+                            role_name[-1],
                         ),
                     ),
                 )
@@ -1160,8 +1167,8 @@
         yaml.constructor.ConstructorError,
         ruamel.yaml.parser.ParserError,
     ) as exc:
-        msg = f"Failed to load YAML file: {lintable.path}"
-        raise RuntimeError(msg) from exc
+        msg = "Failed to load YAML file"
+        raise RuntimeError(msg, lintable.path) from exc
 
     if len(result) == 0:
         return None  # empty documents
@@ -1214,6 +1221,7 @@
         "gather_facts",
         "hosts",
         "import_playbook",
+        "ansible.builtin.import_playbook",
         "post_tasks",
         "pre_tasks",
         "roles",
@@ -1342,4 +1350,7 @@
 
 def parse_fqcn(name: str) -> tuple[str, ...]:
     """Parse name parameter into FQCN segments."""
-    return tuple(name.split(".")) if is_fqcn(name) else ("", "", name)
+    if not is_fqcn(name):
+        return ("", "", name)
+
+    return tuple(name.split("."))
diff -Nru ansible-lint-25.2.1/src/ansiblelint/yaml_utils.py ansible-lint-25.6.1/src/ansiblelint/yaml_utils.py
--- ansible-lint-25.2.1/src/ansiblelint/yaml_utils.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/src/ansiblelint/yaml_utils.py	2025-06-19 09:30:13.000000000 +0200
@@ -1,5 +1,6 @@
 """Utility helpers to simplify working with yaml-based data."""
 
+# cspell: ignore docinfo
 # pylint: disable=too-many-lines
 from __future__ import annotations
 
@@ -17,6 +18,7 @@
 from ruamel.yaml.comments import CommentedMap, CommentedSeq, Format
 from ruamel.yaml.composer import ComposerError
 from ruamel.yaml.constructor import RoundTripConstructor
+from ruamel.yaml.docinfo import Version
 from ruamel.yaml.emitter import Emitter, ScalarAnalysis
 
 # Module 'ruamel.yaml' does not explicitly export attribute 'YAML'; implicit reexport disabled
@@ -1028,7 +1030,7 @@
         return None
 
     @version.setter
-    def version(self, val: tuple[int, int] | None) -> None:
+    def version(self, val: str | tuple[int, int] | list[int] | Version | None) -> None:
         """Ensure that yaml version uses our default value.
 
         The yaml Reader updates this value based on the ``%YAML`` directive in files.
@@ -1036,7 +1038,15 @@
         But, None effectively resets the parsing version to YAML 1.2 (ruamel's default).
         """
         if val is not None:
-            self._yaml_version = val
+            if isinstance(val, tuple):
+                self._yaml_version = val
+            elif isinstance(val, list):
+                self._yaml_version = (val[0], val[1])
+            elif isinstance(val, Version):
+                self._yaml_version = (val.major, val.minor)
+            else:
+                msg = f"Unsupported argument {val}"
+                raise TypeError(msg)
         elif hasattr(self, "_yaml_version_default"):
             self._yaml_version = self._yaml_version_default
         # We do nothing if the object did not have a previous default version defined
diff -Nru ansible-lint-25.2.1/test/rules/test_inline_env_var.py ansible-lint-25.6.1/test/rules/test_inline_env_var.py
--- ansible-lint-25.2.1/test/rules/test_inline_env_var.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/rules/test_inline_env_var.py	2025-06-19 09:30:13.000000000 +0200
@@ -59,6 +59,17 @@
     command: echo
     args:
       strip_empty_ends: false
+
+  - name: Command with expand_argument_vars option
+    command:
+      cmd: /bin/echo $LITERAL
+      expand_argument_vars: false
+
+  - name: Mutually exclusive cmd and argv should not trigger a false-positive
+    ansible.builtin.command:
+      cmd: /bin/echo
+      argv:
+         - Hello
 """
 
 FAIL_PLAY_TASKS = """
diff -Nru ansible-lint-25.2.1/test/schemas/f/ansible-navigator.json ansible-lint-25.6.1/test/schemas/f/ansible-navigator.json
--- ansible-lint-25.2.1/test/schemas/f/ansible-navigator.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/schemas/f/ansible-navigator.json	2025-06-19 09:30:13.000000000 +0200
@@ -287,7 +287,7 @@
           "$ref": "#/$defs/EnvironmentVariablesModel"
         },
         "image": {
-          "default": "quay.io/ansible/creator-ee:v0.2.0",
+          "default": "ghcr.io/ansible/community-ansible-dev-tools:latest",
           "description": "Specify the name of the execution environment image",
           "title": "Image",
           "type": "string"
diff -Nru ansible-lint-25.2.1/test/schemas/f/meta.json ansible-lint-25.6.1/test/schemas/f/meta.json
--- ansible-lint-25.2.1/test/schemas/f/meta.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/schemas/f/meta.json	2025-06-19 09:30:13.000000000 +0200
@@ -378,6 +378,7 @@
               "39",
               "40",
               "41",
+              "42",
               "all"
             ],
             "type": "string"
@@ -875,6 +876,7 @@
               "21.02",
               "22.03",
               "23.05",
+              "24.10",
               "all"
             ],
             "type": "string"
@@ -1014,6 +1016,7 @@
               "15SP3",
               "15SP4",
               "15SP5",
+              "15SP6",
               "all"
             ],
             "type": "string"
@@ -1129,6 +1132,8 @@
               "maverick",
               "natty",
               "oneiric",
+              "oracular",
+              "plucky",
               "precise",
               "quantal",
               "raring",
@@ -1504,7 +1509,7 @@
         "versions": {
           "default": "all",
           "items": {
-            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "all"],
+            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "8.0", "all"],
             "type": "string"
           },
           "type": "array"
@@ -1523,7 +1528,7 @@
         "versions": {
           "default": "all",
           "items": {
-            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "all"],
+            "enum": ["5.5", "6.0", "6.5", "6.7", "7.0", "8.0", "all"],
             "type": "string"
           },
           "type": "array"
diff -Nru ansible-lint-25.2.1/test/schemas/f/__store__.json ansible-lint-25.6.1/test/schemas/f/__store__.json
--- ansible-lint-25.2.1/test/schemas/f/__store__.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/schemas/f/__store__.json	2025-06-19 09:30:13.000000000 +0200
@@ -24,7 +24,7 @@
     "url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/inventory.json";
   },
   "meta": {
-    "etag": "62cce45a9b8bd96872d8ee1c465d3ff6b60facf6a4aeba5c2e128df02b5f52a5",
+    "etag": "60f3ce2a78ec4fb705c589da409a384ac97315e17810379c5049169986ce3097",
     "url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/meta.json";
   },
   "meta-runtime": {
diff -Nru ansible-lint-25.2.1/test/schemas/package.json ansible-lint-25.6.1/test/schemas/package.json
--- ansible-lint-25.2.1/test/schemas/package.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/schemas/package.json	2025-06-19 09:30:13.000000000 +0200
@@ -4,7 +4,7 @@
     "js-yaml": "^4.1.0",
     "safe-stable-stringify": "^2.5.0",
     "ts-node": "^10.9.2",
-    "vscode-json-languageservice": "^5.4.3"
+    "vscode-json-languageservice": "^5.5.0"
   },
   "scripts": {
     "compile": "tsc",
@@ -12,15 +12,15 @@
     "test": "python3 src/rebuild.py && mocha"
   },
   "devDependencies": {
-    "@types/chai": "^5.2.0",
+    "@types/chai": "^5.2.2",
     "@types/js-yaml": "^4.0.9",
     "@types/minimatch": "^5.1.2",
     "@types/mocha": "^10.0.10",
-    "@types/node": "^22.13.10",
+    "@types/node": "^22.15.25",
     "chai": "^5.2.0",
     "minimatch": "^10.0.1",
-    "mocha": "^11.1.0",
-    "typescript": "^5.8.2"
+    "mocha": "^11.5.0",
+    "typescript": "^5.8.3"
   },
   "directories": {
     "test": "./src"
diff -Nru ansible-lint-25.2.1/test/schemas/package-lock.json ansible-lint-25.6.1/test/schemas/package-lock.json
--- ansible-lint-25.2.1/test/schemas/package-lock.json	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/schemas/package-lock.json	2025-06-19 09:30:13.000000000 +0200
@@ -9,18 +9,18 @@
         "js-yaml": "^4.1.0",
         "safe-stable-stringify": "^2.5.0",
         "ts-node": "^10.9.2",
-        "vscode-json-languageservice": "^5.4.3"
+        "vscode-json-languageservice": "^5.5.0"
       },
       "devDependencies": {
-        "@types/chai": "^5.2.0",
+        "@types/chai": "^5.2.2",
         "@types/js-yaml": "^4.0.9",
         "@types/minimatch": "^5.1.2",
         "@types/mocha": "^10.0.10",
-        "@types/node": "^22.13.10",
+        "@types/node": "^22.15.25",
         "chai": "^5.2.0",
         "minimatch": "^10.0.1",
-        "mocha": "^11.1.0",
-        "typescript": "^5.8.2"
+        "mocha": "^11.5.0",
+        "typescript": "^5.8.3"
       }
     },
     "node_modules/@cspotcode/source-map-support": {
@@ -191,9 +191,9 @@
       "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
     },
     "node_modules/@types/chai": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.0.tgz";,
-      "integrity": "sha512-FWnQYdrG9FAC8KgPVhDFfrPL1FBsL3NtIt2WsxKvwu/61K6HiuDF3xAb7c7w/k9ML2QOUHcwTgU7dKLFPK6sBg==",
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz";,
+      "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -227,12 +227,12 @@
       "license": "MIT"
     },
     "node_modules/@types/node": {
-      "version": "22.13.10",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz";,
-      "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
+      "version": "22.15.25",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.25.tgz";,
+      "integrity": "sha512-RJCAZ1E7JgMDJRnyVwIvlnKnNa0oHXrgSeq5aoXdhxCOSuwCe9sccKnngOJq8GuukzSf45u4VeD0JxUXfC3Dwg==",
       "license": "MIT",
       "dependencies": {
-        "undici-types": "~6.20.0"
+        "undici-types": "~6.21.0"
       }
     },
     "node_modules/@vscode/l10n": {
@@ -290,15 +290,6 @@
         }
       }
     },
-    "node_modules/ansi-colors": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz";,
-      "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/ansi-regex": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz";,
@@ -323,19 +314,6 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1";
       }
     },
-    "node_modules/anymatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz";,
-      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-      "dev": true,
-      "dependencies": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
     "node_modules/arg": {
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz";,
@@ -361,15 +339,6 @@
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
       "dev": true
     },
-    "node_modules/binary-extensions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz";,
-      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/brace-expansion": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz";,
@@ -379,18 +348,6 @@
         "balanced-match": "^1.0.0"
       }
     },
-    "node_modules/braces": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz";,
-      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
-      "dependencies": {
-        "fill-range": "^7.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz";,
@@ -464,30 +421,19 @@
       }
     },
     "node_modules/chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz";,
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz";,
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
       "dev": true,
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://paulmillr.com/funding/";
-        }
-      ],
+      "license": "MIT",
       "dependencies": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
+        "readdirp": "^4.0.1"
       },
       "engines": {
-        "node": ">= 8.10.0"
+        "node": ">= 14.16.0"
       },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
+      "funding": {
+        "url": "https://paulmillr.com/funding/";
       }
     },
     "node_modules/cliui": {
@@ -587,10 +533,11 @@
       }
     },
     "node_modules/diff": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz";,
-      "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz";,
+      "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
       "dev": true,
+      "license": "BSD-3-Clause",
       "engines": {
         "node": ">=0.3.1"
       }
@@ -634,18 +581,6 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz";,
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
-    "node_modules/fill-range": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz";,
-      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/find-up": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz";,
@@ -688,20 +623,6 @@
         "url": "https://github.com/sponsors/isaacs";
       }
     },
-    "node_modules/fsevents": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz";,
-      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-      "dev": true,
-      "hasInstallScript": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-      }
-    },
     "node_modules/get-caller-file": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz";,
@@ -741,18 +662,6 @@
         "url": "https://github.com/sponsors/isaacs";
       }
     },
-    "node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz";,
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
     "node_modules/glob/node_modules/minimatch": {
       "version": "9.0.5",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz";,
@@ -787,27 +696,6 @@
         "he": "bin/he"
       }
     },
-    "node_modules/is-binary-path": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz";,
-      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "dependencies": {
-        "binary-extensions": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz";,
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/is-fullwidth-code-point": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz";,
@@ -817,27 +705,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz";,
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz";,
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
     "node_modules/is-plain-obj": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz";,
@@ -981,24 +848,25 @@
       }
     },
     "node_modules/mocha": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz";,
-      "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==",
+      "version": "11.5.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.5.0.tgz";,
+      "integrity": "sha512-VKDjhy6LMTKm0WgNEdlY77YVsD49LZnPSXJAaPNL9NRYQADxvORsyG1DIQY6v53BKTnlNbEE2MbVCDbnxr4K3w==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "ansi-colors": "^4.1.3",
         "browser-stdout": "^1.3.1",
-        "chokidar": "^3.5.3",
+        "chokidar": "^4.0.1",
         "debug": "^4.3.5",
-        "diff": "^5.2.0",
+        "diff": "^7.0.0",
         "escape-string-regexp": "^4.0.0",
         "find-up": "^5.0.0",
         "glob": "^10.4.5",
         "he": "^1.2.0",
         "js-yaml": "^4.1.0",
         "log-symbols": "^4.1.0",
-        "minimatch": "^5.1.6",
+        "minimatch": "^9.0.5",
         "ms": "^2.1.3",
+        "picocolors": "^1.1.1",
         "serialize-javascript": "^6.0.2",
         "strip-json-comments": "^3.1.1",
         "supports-color": "^8.1.1",
@@ -1016,15 +884,19 @@
       }
     },
     "node_modules/mocha/node_modules/minimatch": {
-      "version": "5.1.6",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz";,
-      "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz";,
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
       "dev": true,
+      "license": "ISC",
       "dependencies": {
         "brace-expansion": "^2.0.1"
       },
       "engines": {
-        "node": ">=10"
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs";
       }
     },
     "node_modules/ms": {
@@ -1033,15 +905,6 @@
       "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
       "dev": true
     },
-    "node_modules/normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz";,
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/p-limit": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz";,
@@ -1124,17 +987,12 @@
         "node": ">= 14.16"
       }
     },
-    "node_modules/picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz";,
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz";,
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
       "dev": true,
-      "engines": {
-        "node": ">=8.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert";
-      }
+      "license": "ISC"
     },
     "node_modules/punycode": {
       "version": "2.1.1",
@@ -1154,15 +1012,17 @@
       }
     },
     "node_modules/readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz";,
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz";,
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
       "dev": true,
-      "dependencies": {
-        "picomatch": "^2.2.1"
-      },
+      "license": "MIT",
       "engines": {
-        "node": ">=8.10.0"
+        "node": ">= 14.18.0"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://paulmillr.com/funding/";
       }
     },
     "node_modules/require-directory": {
@@ -1339,18 +1199,6 @@
         "url": "https://github.com/chalk/supports-color?sponsor=1";
       }
     },
-    "node_modules/to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz";,
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "dependencies": {
-        "is-number": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
     "node_modules/ts-node": {
       "version": "10.9.2",
       "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz";,
@@ -1402,9 +1250,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "5.8.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz";,
-      "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
+      "version": "5.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz";,
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
       "license": "Apache-2.0",
       "bin": {
         "tsc": "bin/tsc",
@@ -1415,9 +1263,9 @@
       }
     },
     "node_modules/undici-types": {
-      "version": "6.20.0",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz";,
-      "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+      "version": "6.21.0",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz";,
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
       "license": "MIT"
     },
     "node_modules/uri-js": {
@@ -1434,15 +1282,16 @@
       "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
     },
     "node_modules/vscode-json-languageservice": {
-      "version": "5.4.3",
-      "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.4.3.tgz";,
-      "integrity": "sha512-NVSEQDloP9NYccuqKg4eI46kutZpwucBY4csBB6FCxbM7AZVoBt0oxTItPVA+ZwhnG1bg/fmiBRAwcGJyNQoPA==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.5.0.tgz";,
+      "integrity": "sha512-JchBzp8ArzhCVpRS/LT4wzEEvwHXIUEdZD064cGTI4RVs34rNCZXPUguIYSfGBcHH1GV79ufPcfy3Pd8+ukbKw==",
+      "license": "MIT",
       "dependencies": {
         "@vscode/l10n": "^0.0.18",
         "jsonc-parser": "^3.3.1",
         "vscode-languageserver-textdocument": "^1.0.12",
         "vscode-languageserver-types": "^3.17.5",
-        "vscode-uri": "^3.0.8"
+        "vscode-uri": "^3.1.0"
       }
     },
     "node_modules/vscode-languageserver-textdocument": {
@@ -1457,9 +1306,10 @@
       "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
     },
     "node_modules/vscode-uri": {
-      "version": "3.0.8",
-      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz";,
-      "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz";,
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+      "license": "MIT"
     },
     "node_modules/which": {
       "version": "2.0.2",
@@ -1712,9 +1562,9 @@
       "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
     },
     "@types/chai": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.0.tgz";,
-      "integrity": "sha512-FWnQYdrG9FAC8KgPVhDFfrPL1FBsL3NtIt2WsxKvwu/61K6HiuDF3xAb7c7w/k9ML2QOUHcwTgU7dKLFPK6sBg==",
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz";,
+      "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==",
       "dev": true,
       "requires": {
         "@types/deep-eql": "*"
@@ -1745,11 +1595,11 @@
       "dev": true
     },
     "@types/node": {
-      "version": "22.13.10",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz";,
-      "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
+      "version": "22.15.25",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.25.tgz";,
+      "integrity": "sha512-RJCAZ1E7JgMDJRnyVwIvlnKnNa0oHXrgSeq5aoXdhxCOSuwCe9sccKnngOJq8GuukzSf45u4VeD0JxUXfC3Dwg==",
       "requires": {
-        "undici-types": "~6.20.0"
+        "undici-types": "~6.21.0"
       }
     },
     "@vscode/l10n": {
@@ -1786,12 +1636,6 @@
         "ajv": "^8.0.0"
       }
     },
-    "ansi-colors": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz";,
-      "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
-      "dev": true
-    },
     "ansi-regex": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz";,
@@ -1807,16 +1651,6 @@
         "color-convert": "^2.0.1"
       }
     },
-    "anymatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz";,
-      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-      "dev": true,
-      "requires": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      }
-    },
     "arg": {
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz";,
@@ -1839,12 +1673,6 @@
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
       "dev": true
     },
-    "binary-extensions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz";,
-      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "dev": true
-    },
     "brace-expansion": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz";,
@@ -1854,15 +1682,6 @@
         "balanced-match": "^1.0.0"
       }
     },
-    "braces": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz";,
-      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
-      "requires": {
-        "fill-range": "^7.1.1"
-      }
-    },
     "browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz";,
@@ -1916,19 +1735,12 @@
       "dev": true
     },
     "chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz";,
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz";,
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
       "dev": true,
       "requires": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "fsevents": "~2.3.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
+        "readdirp": "^4.0.1"
       }
     },
     "cliui": {
@@ -2003,9 +1815,9 @@
       "dev": true
     },
     "diff": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz";,
-      "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz";,
+      "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
       "dev": true
     },
     "eastasianwidth": {
@@ -2037,15 +1849,6 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz";,
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
-    "fill-range": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz";,
-      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
-      "requires": {
-        "to-regex-range": "^5.0.1"
-      }
-    },
     "find-up": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz";,
@@ -2072,13 +1875,6 @@
         "signal-exit": "^4.0.1"
       }
     },
-    "fsevents": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz";,
-      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-      "dev": true,
-      "optional": true
-    },
     "get-caller-file": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz";,
@@ -2116,15 +1912,6 @@
         }
       }
     },
-    "glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz";,
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "requires": {
-        "is-glob": "^4.0.1"
-      }
-    },
     "has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz";,
@@ -2137,42 +1924,12 @@
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
-    "is-binary-path": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz";,
-      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "requires": {
-        "binary-extensions": "^2.0.0"
-      }
-    },
-    "is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz";,
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-      "dev": true
-    },
     "is-fullwidth-code-point": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz";,
       "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
       "dev": true
     },
-    "is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz";,
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "requires": {
-        "is-extglob": "^2.1.1"
-      }
-    },
-    "is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz";,
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true
-    },
     "is-plain-obj": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz";,
@@ -2274,24 +2031,24 @@
       "dev": true
     },
     "mocha": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz";,
-      "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==",
+      "version": "11.5.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.5.0.tgz";,
+      "integrity": "sha512-VKDjhy6LMTKm0WgNEdlY77YVsD49LZnPSXJAaPNL9NRYQADxvORsyG1DIQY6v53BKTnlNbEE2MbVCDbnxr4K3w==",
       "dev": true,
       "requires": {
-        "ansi-colors": "^4.1.3",
         "browser-stdout": "^1.3.1",
-        "chokidar": "^3.5.3",
+        "chokidar": "^4.0.1",
         "debug": "^4.3.5",
-        "diff": "^5.2.0",
+        "diff": "^7.0.0",
         "escape-string-regexp": "^4.0.0",
         "find-up": "^5.0.0",
         "glob": "^10.4.5",
         "he": "^1.2.0",
         "js-yaml": "^4.1.0",
         "log-symbols": "^4.1.0",
-        "minimatch": "^5.1.6",
+        "minimatch": "^9.0.5",
         "ms": "^2.1.3",
+        "picocolors": "^1.1.1",
         "serialize-javascript": "^6.0.2",
         "strip-json-comments": "^3.1.1",
         "supports-color": "^8.1.1",
@@ -2302,9 +2059,9 @@
       },
       "dependencies": {
         "minimatch": {
-          "version": "5.1.6",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz";,
-          "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+          "version": "9.0.5",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz";,
+          "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
           "dev": true,
           "requires": {
             "brace-expansion": "^2.0.1"
@@ -2318,12 +2075,6 @@
       "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
       "dev": true
     },
-    "normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz";,
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true
-    },
     "p-limit": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz";,
@@ -2376,10 +2127,10 @@
       "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
       "dev": true
     },
-    "picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz";,
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+    "picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz";,
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
       "dev": true
     },
     "punycode": {
@@ -2397,13 +2148,10 @@
       }
     },
     "readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz";,
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "requires": {
-        "picomatch": "^2.2.1"
-      }
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz";,
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+      "dev": true
     },
     "require-directory": {
       "version": "2.1.1",
@@ -2512,15 +2260,6 @@
         "has-flag": "^4.0.0"
       }
     },
-    "to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz";,
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "requires": {
-        "is-number": "^7.0.0"
-      }
-    },
     "ts-node": {
       "version": "10.9.2",
       "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz";,
@@ -2549,14 +2288,14 @@
       }
     },
     "typescript": {
-      "version": "5.8.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz";,
-      "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="
+      "version": "5.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz";,
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="
     },
     "undici-types": {
-      "version": "6.20.0",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz";,
-      "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="
+      "version": "6.21.0",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz";,
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="
     },
     "uri-js": {
       "version": "4.4.1",
@@ -2572,15 +2311,15 @@
       "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
     },
     "vscode-json-languageservice": {
-      "version": "5.4.3",
-      "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.4.3.tgz";,
-      "integrity": "sha512-NVSEQDloP9NYccuqKg4eI46kutZpwucBY4csBB6FCxbM7AZVoBt0oxTItPVA+ZwhnG1bg/fmiBRAwcGJyNQoPA==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.5.0.tgz";,
+      "integrity": "sha512-JchBzp8ArzhCVpRS/LT4wzEEvwHXIUEdZD064cGTI4RVs34rNCZXPUguIYSfGBcHH1GV79ufPcfy3Pd8+ukbKw==",
       "requires": {
         "@vscode/l10n": "^0.0.18",
         "jsonc-parser": "^3.3.1",
         "vscode-languageserver-textdocument": "^1.0.12",
         "vscode-languageserver-types": "^3.17.5",
-        "vscode-uri": "^3.0.8"
+        "vscode-uri": "^3.1.0"
       }
     },
     "vscode-languageserver-textdocument": {
@@ -2594,9 +2333,9 @@
       "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
     },
     "vscode-uri": {
-      "version": "3.0.8",
-      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz";,
-      "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz";,
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="
     },
     "which": {
       "version": "2.0.2",
diff -Nru ansible-lint-25.2.1/test/test_config.py ansible-lint-25.6.1/test/test_config.py
--- ansible-lint-25.2.1/test/test_config.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_config.py	2025-06-19 09:30:13.000000000 +0200
@@ -12,6 +12,6 @@
             for rule in default_rules_collection.rules:
                 if profile_rule_id == rule.id:
                     forbidden_tags = profile_banned_tags & set(rule.tags)
-                    assert (
-                        not forbidden_tags
-                    ), f"Rule {profile_rule_id} from {name} profile cannot use {profile_banned_tags & set(rule.tags)} tag."
+                    assert not forbidden_tags, (
+                        f"Rule {profile_rule_id} from {name} profile cannot use {profile_banned_tags & set(rule.tags)} tag."
+                    )
diff -Nru ansible-lint-25.2.1/test/test_file_utils.py ansible-lint-25.6.1/test/test_file_utils.py
--- ansible-lint-25.2.1/test/test_file_utils.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_file_utils.py	2025-06-19 09:30:13.000000000 +0200
@@ -98,13 +98,13 @@
     my_options.lintables = [str(lint_path)]
     files = file_utils.discover_lintables(my_options)
     stderr = capsys.readouterr().err
-    assert (
-        not stderr
-    ), f"No stderr output is expected when the verbosity is off, got: {stderr}"
-    assert (
-        len(files) == yaml_count
-    ), "Expected to find {yaml_count} yaml files in {lint_path}".format_map(
-        locals(),
+    assert not stderr, (
+        f"No stderr output is expected when the verbosity is off, got: {stderr}"
+    )
+    assert len(files) == yaml_count, (
+        "Expected to find {yaml_count} yaml files in {lint_path}".format_map(
+            locals(),
+        )
     )
 
 
diff -Nru ansible-lint-25.2.1/test/test_loaders.py ansible-lint-25.6.1/test/test_loaders.py
--- ansible-lint-25.2.1/test/test_loaders.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_loaders.py	2025-06-19 09:30:13.000000000 +0200
@@ -6,7 +6,14 @@
 from pathlib import Path
 from textwrap import dedent
 
-from ansiblelint.loaders import IGNORE_FILE, load_ignore_txt
+import pytest
+
+from ansiblelint.loaders import (
+    IGNORE_FILE,
+    IgnoreRule,
+    IgnoreRuleQualifier,
+    load_ignore_txt,
+)
 
 
 def test_load_ignore_txt_default_empty() -> None:
@@ -35,6 +42,7 @@
                     # See https://ansible.readthedocs.io/projects/lint/configuring/#ignoring-rules-for-entire-files
                     playbook2.yml package-latest # comment
                     playbook2.yml foo-bar
+                    playbook2.yml another-role skip # rule with qualifier
                 """,
                 ),
             )
@@ -47,7 +55,13 @@
         finally:
             os.chdir(cwd)
 
-    assert result == {"playbook2.yml": {"package-latest", "foo-bar"}}
+    assert result == {
+        "playbook2.yml": {
+            IgnoreRule("package-latest", frozenset()),
+            IgnoreRule("foo-bar", frozenset()),
+            IgnoreRule("another-role", frozenset([IgnoreRuleQualifier.SKIP])),
+        }
+    }
 
 
 def test_load_ignore_txt_default_success_alternative() -> None:
@@ -76,8 +90,11 @@
             os.chdir(cwd)
 
     assert result == {
-        "playbook.yml": {"more-foo", "foo-bar"},
-        "tasks/main.yml": {"more-bar"},
+        "playbook.yml": {
+            IgnoreRule("more-foo", frozenset()),
+            IgnoreRule("foo-bar", frozenset()),
+        },
+        "tasks/main.yml": {IgnoreRule("more-bar", frozenset())},
     }
 
 
@@ -108,10 +125,10 @@
             os.chdir(cwd)
 
     assert result == {
-        "playbook.yml": {"hector"},
-        "roles/eduardo/tasks/main.yml": {"lalo"},
-        "roles/guzman/tasks/main.yml": {"lalo"},
-        "vars/main.yml": {"tuco"},
+        "playbook.yml": {IgnoreRule("hector", frozenset())},
+        "roles/eduardo/tasks/main.yml": {IgnoreRule("lalo", frozenset())},
+        "roles/guzman/tasks/main.yml": {IgnoreRule("lalo", frozenset())},
+        "vars/main.yml": {IgnoreRule("tuco", frozenset())},
     }
 
 
@@ -120,3 +137,22 @@
     result = load_ignore_txt(Path(str(uuid.uuid4())))
 
     assert not result
+
+
+def test_load_ignore_txt_invalid_tags(monkeypatch: pytest.MonkeyPatch) -> None:
+    """Test load_ignore_txt with an existing ignore-file in the default location."""
+    with tempfile.TemporaryDirectory() as temporary_directory:
+        ignore_file = Path(temporary_directory) / IGNORE_FILE.default
+
+        with ignore_file.open("w", encoding="utf-8") as _ignore_file:
+            _ignore_file.write(
+                dedent(
+                    """
+                    playbook2.yml package-latest invalid-tag
+                """,
+                ),
+            )
+
+        monkeypatch.chdir(temporary_directory)
+        with pytest.raises(RuntimeError, match="Unable to parse line"):
+            load_ignore_txt()
diff -Nru ansible-lint-25.2.1/test/test_main.py ansible-lint-25.6.1/test/test_main.py
--- ansible-lint-25.2.1/test/test_main.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_main.py	2025-06-19 09:30:13.000000000 +0200
@@ -8,6 +8,7 @@
 import time
 from collections.abc import Mapping
 from http.client import RemoteDisconnected
+from os.path import abspath
 from pathlib import Path
 
 import pytest
@@ -159,8 +160,9 @@
         for x in (
             "Invalid type for configuration option setting: CACHE_PLUGIN_TIMEOUT",
             "has an invalid value: Invalid type provided for 'int': 'invalid-value'",
+            "has an invalid value: Invalid value provided for 'integer': 'invalid-value'",
         )
-    )
+    ), proc.stderr
 
 
 def test_list_tags() -> None:
@@ -179,3 +181,30 @@
         assert isinstance(value, list)
         for item in value:
             assert isinstance(item, str)
+
+
+def test_ro_venv() -> None:
+    """Tests behavior when the virtual environment is read-only."""
+    tox_work_dir = os.environ.get("TOX_WORK_DIR", ".tox")
+    venv_path = f"{tox_work_dir}/ro"
+    commands = [
+        f"mkdir -p {venv_path}",
+        f"chmod -R a+w {venv_path}",
+        f"rm -rf {venv_path}",
+        f"python -m venv --symlinks {venv_path}",
+        f"{venv_path}/bin/python -m pip install -q -e .",
+        f"chmod -R a-w {venv_path}",
+        # running with a ro venv and default cwd
+        f"{venv_path}/bin/ansible-lint --version",
+        # running from a read-only cwd:
+        f"cd / && {abspath(venv_path)}/bin/ansible-lint --version",  # noqa: PTH100
+        # running with a ro venv and a custom project path in forced non-online mode, so it will need to install requirements
+        f"{venv_path}/bin/ansible-lint -vv --no-offline --project-dir ./examples/reqs_v2/ ./examples/reqs_v2/",
+    ]
+    for cmd in commands:
+        result = subprocess.run(
+            cmd, capture_output=True, shell=True, text=True, check=False
+        )
+        assert result.returncode == 0, (
+            f"Got {result.returncode} running {cmd}\n\tstderr: {result.stderr}\n\tstdout: {result.stdout}"
+        )
diff -Nru ansible-lint-25.2.1/test/test_profiles.py ansible-lint-25.6.1/test/test_profiles.py
--- ansible-lint-25.2.1/test/test_profiles.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_profiles.py	2025-06-19 09:30:13.000000000 +0200
@@ -21,9 +21,9 @@
     assert len(collection.rules) == 5, "Failed to register new rule."
 
     filter_rules_with_profile(collection.rules, "min")
-    assert (
-        len(collection.rules) == 4
-    ), "Failed to unload rule that is not part of 'min' profile."
+    assert len(collection.rules) == 4, (
+        "Failed to unload rule that is not part of 'min' profile."
+    )
 
 
 def test_profile_listing(capfd: CaptureFixture[str]) -> None:
@@ -58,6 +58,6 @@
             continue
         err_lines.append(line)
     if all(word not in platform_name for word in ["wsl", "microsoft"]) and err_lines:
-        assert (
-            not err_lines
-        ), f"Unexpected stderr output found while running on {platform_name} platform:\n{err_lines}"
+        assert not err_lines, (
+            f"Unexpected stderr output found while running on {platform_name} platform:\n{err_lines}"
+        )
diff -Nru ansible-lint-25.2.1/test/test_rules_collection.py ansible-lint-25.6.1/test/test_rules_collection.py
--- ansible-lint-25.2.1/test/test_rules_collection.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_rules_collection.py	2025-06-19 09:30:13.000000000 +0200
@@ -169,9 +169,9 @@
             rule.id,
         ), f"Rule id {rule.id} did not match our required format."
         keys.add(rule.id)
-        assert (
-            rule.help or rule.description or rule.__doc__
-        ), f"Rule {rule.id} must have at least one of:  .help, .description, .__doc__"
+        assert rule.help or rule.description or rule.__doc__, (
+            f"Rule {rule.id} must have at least one of:  .help, .description, .__doc__"
+        )
     assert "yaml" in keys, "yaml rule is missing"
     assert len(rules) == 51  # update this number when adding new rules!
     assert len(keys) == len(rules), "Duplicate rule ids?"
diff -Nru ansible-lint-25.2.1/test/test_runner.py ansible-lint-25.6.1/test/test_runner.py
--- ansible-lint-25.2.1/test/test_runner.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_runner.py	2025-06-19 09:30:13.000000000 +0200
@@ -241,6 +241,25 @@
     assert result[0].tag == "load-failure[not-found]"
 
 
+def test_runner_load_failure_yaml(default_rules_collection: RulesCollection) -> None:
+    """Ensure load-failure[yaml] work as expected."""
+    checked_files: set[Lintable] = set()
+
+    filename = Path("examples/broken/load-failure-invalid.yml").resolve()
+    runner = Runner(
+        filename,
+        rules=default_rules_collection,
+        verbosity=0,
+        checked_files=checked_files,
+    )
+    result = runner.run()
+    assert len(runner.checked_files) == 1
+    assert len(result) == 1
+    assert result[0].tag == "load-failure[yaml]"
+    assert result[0].lineno == 5
+    assert result[0].column == 1
+
+
 def test_runner_tmp_file(
     tmp_path: Path,
     default_rules_collection: RulesCollection,
diff -Nru ansible-lint-25.2.1/test/test_schemas.py ansible-lint-25.6.1/test/test_schemas.py
--- ansible-lint-25.2.1/test/test_schemas.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_schemas.py	2025-06-19 09:30:13.000000000 +0200
@@ -47,10 +47,8 @@
 ) -> None:
     """Test that schema refresh can handle time out errors."""
     error_msg = "Simulating handshake operation time out."
-    mock_request.urlopen.side_effect = (
-        urllib.error.URLError(  # pyright: ignore[reportAttributeAccessIssue]
-            TimeoutError(error_msg)
-        )
+    mock_request.urlopen.side_effect = urllib.error.URLError(  # pyright: ignore[reportAttributeAccessIssue]
+        TimeoutError(error_msg)
     )
     with caplog.at_level(logging.DEBUG):
         assert refresh_schemas(min_age_seconds=0) == 0
diff -Nru ansible-lint-25.2.1/test/test_skiputils.py ansible-lint-25.6.1/test/test_skiputils.py
--- ansible-lint-25.2.1/test/test_skiputils.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_skiputils.py	2025-06-19 09:30:13.000000000 +0200
@@ -64,6 +64,15 @@
     assert len(results) == 1
 
 
+def test_var_noqa(default_text_runner: RunFromText) -> None:
+    """Check that noqa is properly taken into account on vars and tasks."""
+    results = default_text_runner.run(
+        Path("examples/playbooks/vars/noqa_multiline.yml")
+    )
+    # Should raise no error at "SOME_VAR".
+    assert len(results) == 0
+
+
 @pytest.mark.parametrize(
     ("lintable", "yaml", "expected_form"),
     (
diff -Nru ansible-lint-25.2.1/test/test_utils.py ansible-lint-25.6.1/test/test_utils.py
--- ansible-lint-25.2.1/test/test_utils.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/test/test_utils.py	2025-06-19 09:30:13.000000000 +0200
@@ -338,7 +338,11 @@
 
 def test_is_playbook() -> None:
     """Verify that we can detect a playbook as a playbook."""
-    assert utils.is_playbook("examples/playbooks/always-run-success.yml")
+    assert utils.is_playbook(filename="examples/playbooks/always-run-success.yml")
+    assert utils.is_playbook(
+        filename="examples/playbooks/import-failed-syntax-check.yml"
+    )
+    assert utils.is_playbook(filename="examples/playbooks/import_playbook_fqcn.yml")
 
 
 @pytest.mark.parametrize(
@@ -538,3 +542,15 @@
         "Failed to find local.testcollection.test.bar.foo playbook."
         not in result.stderr
     )
+
+
+def test_import_role_children_subdirs() -> None:
+    """Verify import_playbook_children()."""
+    result = run_ansible_lint(
+        Path("playbooks/import_role_fqcn.yml"),
+        cwd=Path(__file__).resolve().parent.parent / "examples",
+        env={
+            "ANSIBLE_COLLECTIONS_PATH": "../collections",
+        },
+    )
+    assert "Failed " not in result.stderr
diff -Nru ansible-lint-25.2.1/tools/generate_docs.py ansible-lint-25.6.1/tools/generate_docs.py
--- ansible-lint-25.2.1/tools/generate_docs.py	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/tools/generate_docs.py	2025-06-19 09:30:13.000000000 +0200
@@ -11,7 +11,7 @@
 from ansiblelint.rules import RulesCollection, TransformMixin
 
 if __name__ == "__main__":
-    subprocess.run(  # noqa: S603
+    subprocess.run(
         ["ansible-lint", "--list-rules"],  # noqa: S607
         check=True,
         stdout=subprocess.DEVNULL,
diff -Nru ansible-lint-25.2.1/tools/report-coverage ansible-lint-25.6.1/tools/report-coverage
--- ansible-lint-25.2.1/tools/report-coverage	1970-01-01 01:00:00.000000000 +0100
+++ ansible-lint-25.6.1/tools/report-coverage	2025-06-19 09:30:13.000000000 +0200
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -euo pipefail
+coverage combine -q "--data-file=${TOX_ENV_DIR}/.coverage" "${TOX_ENV_DIR}"/.coverage.*
+coverage xml "--data-file=${TOX_ENV_DIR}/.coverage" -o "${TOX_ENV_DIR}/coverage.xml" --ignore-errors --fail-under=0
+COVERAGE_FILE="${TOX_ENV_DIR}/.coverage" coverage report --fail-under=0 --ignore-errors
diff -Nru ansible-lint-25.2.1/tox.ini ansible-lint-25.6.1/tox.ini
--- ansible-lint-25.2.1/tox.ini	2025-04-03 13:56:32.000000000 +0200
+++ ansible-lint-25.6.1/tox.ini	2025-06-19 09:30:13.000000000 +0200
@@ -37,7 +37,6 @@
     LC_*
     NO_COLOR
     PYTEST_*
-    PYTEST_REQPASS
     PYTHON*
     PYTHONBREAKPOINT
     PYTHONIOENCODING
@@ -56,7 +55,6 @@
     PIP_CONSTRAINT = {tox_root}/.config/constraints.txt
     PIP_DISABLE_PIP_VERSION_CHECK = 1
     PRE_COMMIT_COLOR = always
-    PYTEST_REQPASS = 908
     UV_CONSTRAINT = {tox_root}/.config/constraints.txt
     deps, devel, hook, lint, pkg, pre, py310, schemas: PIP_CONSTRAINT = /dev/null
     deps, devel, hook, lint, pkg, pre, py310, schemas: UV_CONSTRAINT = /dev/null
@@ -77,9 +75,12 @@
       --showlocals \
       --doctest-modules \
       --durations=10 \
+      --junitxml=./junit.xml \
       }
-    {py,py310,py311,py312,py313}: sh -c "coverage combine -a -q --data-file={env_dir}/.coverage {work_dir}/*/.coverage.* && coverage xml --data-file={env_dir}/.coverage -o {env_dir}/coverage.xml --fail-under=0 && coverage report --data-file={env_dir}/.coverage"
+commands_post =
+    {py,py310,py311,py312,py313}: ./tools/report-coverage
 allowlist_externals =
+    ./tools/report-coverage
     ./tools/test-hook.sh
     bash
     find
@@ -116,8 +117,9 @@
     twine>=4.0.1
 commands_pre =
 commands =
-    bash -c "PIPX_BIN_DIR={work_dir}/.pipx/bin PIPX_HOME={work_dir}/.pipx pipx install --force -e ."
-    bash -c "if stderr=$({work_dir}/.pipx/bin/ansible-lint --version >/dev/null) && test -z \"$stderr\"; then echo "ok"; fi"
+    bash -ec "rm -rf src/*.egg-info"
+    bash -ec "PIPX_BIN_DIR={work_dir}/.pipx/bin; PIPX_HOME={work_dir}/.pipx; pipx uninstall ansible-lint >/dev/null || true; pipx install --force -e ."
+    bash -ec "if stderr=$({work_dir}/.pipx/bin/ansible-lint --version >/dev/null) && test -z \"$stderr\"; then echo \"ok\"; fi"
     {env_python} -c 'import os.path, shutil, sys; \
       dist_dir = os.path.join("{tox_root}", "dist"); \
       os.path.isdir(dist_dir) or sys.exit(0); \
@@ -172,8 +174,6 @@
     {[testenv]deps}
 extras =
     test
-set_env =
-    PYTEST_REQPASS = 7
 commands =
     sh -c tools/test-eco.sh
 allowlist_externals =

Reply to: