Some ComfyUI builds don't reliably submit optional widget values to execute(), leaving format='{}' (default) and emitting raw int strings via index_str. Moving format to required guarantees the user-entered template reaches the Python side.
Pytest treats the rootdir as a Package because the ComfyUI entry point
__init__.py lives there, and it inferred the rootdir's package name
from the dir name. In local checkouts the dir is `hold_counter`, which
clashed with our subpackage of the same name and caused
`import hold_counter.node` to resolve to the rootdir's __init__.py
(no `node` attribute). The CI runner sees a different dir name
(`ComfyUI-HoldCounter`), where the same machinery instead tried to
import the rootdir __init__.py standalone with no parent package and
exploded on the relative import.
Renaming the subpackage to `_impl/` (signalling it is internal) breaks
the name clash and makes pytest collection work in both environments.
Also adds `pythonpath = ["."]` and `--import-mode=importlib` to
pyproject's pytest config so the rootdir is importable without
sys.path hacks and pytest does not synthesise a Package collector.
Other CI hygiene (also folded in here):
* setup-uv@v3 -> @v6, actions/checkout@v4 -> @v5 to clear the GitHub
Node.js 20 deprecation warnings.
* setup-uv `cache-dependency-glob: pyproject.toml` (uv.lock is
gitignored, so the default **/uv.lock glob fails the job).
Public-facing surface unchanged (NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS, WEB_DIRECTORY remain at the rootdir
__init__.py, which is the only thing ComfyUI ever imports).