Summary
Netsuke has Python infrastructure in scripts/ and tests/workflow_contracts/.
PYTHON_SOURCES in Makefile defines this scope.
make lint runs make lint-python. That target runs Ruff, Pylint,
df12-python-lints, and ambrleaks. It has no docstring-coverage stage.
interrogate appears in neither Makefile nor pyproject.toml.
Ruff enforces docstring format and Pydoclint checks documented contracts.
Neither tool measures docstring coverage across the owned Python source set.
Add a pinned interrogate gate so the repository has an explicit, repeatable
coverage requirement for its Python infrastructure.
Scope
Include these repository-owned Python sources:
scripts/
tests/workflow_contracts/
Keep the existing exclusions for estate-synchronised spelling helpers explicit.
Do not treat Netsuke as a Python distribution. pyproject.toml deliberately
has no [project] or [build-system] table.
Required work
-
Measure the current baseline with interrogate==1.7.0.
Record the command, source scope, coverage percentage, and missing-definition
count in this issue before selecting the initial gate threshold.
-
Define the gate scope and exclusions.
Use the existing PYTHON_SOURCES ownership boundary unless a documented,
path-specific exception is required.
-
Add a pinned Makefile tool definition in the established uv-driven form:
INTERROGATE_VERSION ?= 1.7.0
INTERROGATE = $(UV_ENV) $(UV) tool run --from 'interrogate==$(INTERROGATE_VERSION)' \
interrogate --fail-under 100
Adjust the target arguments only where the measured source layout requires
them. Do not use an unpinned Interrogate version.
-
Add the Interrogate command to lint-python, and update the target comment
and developer documentation.
-
Close the missing docstring gaps required by the selected gate.
Keep public entrypoint contracts documented. Use narrow, documented
exclusions only where a source construct cannot carry a docstring.
-
Add workflow-contract coverage for the new pin and Makefile command.
Extend tests/workflow_contracts/python_toolchain_sync_test.py, or add a
focused contract test, so the pin remains exact and CI/local configuration
cannot drift.
-
Triage test-only and helper-only gaps separately when they need a distinct
policy for nested closures or test functions.
Overload limitation
The repository configures typing with the typ alias. @typ.overload stubs
cannot carry docstrings because Ruff D418 forbids them. Interrogate 1.7.0
recognises only the literal typing.overload and overload spellings for
--ignore-overloaded-functions. It does not recognise typ.overload.
If overload stubs enter the scanned scope, use a targeted --ignore-regex
workaround for those stubs. Do not weaken the general rule. Ruff's
undocumented-public-function rule must continue to guard the real
implementation.
Acceptance criteria
Context
This work aligns Netsuke with the estate's docstring-coverage policy while
respecting its Rust-first architecture and uv-driven Python tooling.
Requested by @leynos in PR #641:
#641
Summary
Netsuke has Python infrastructure in
scripts/andtests/workflow_contracts/.PYTHON_SOURCESinMakefiledefines this scope.make lintrunsmake lint-python. That target runs Ruff, Pylint,df12-python-lints, andambrleaks. It has no docstring-coverage stage.interrogateappears in neitherMakefilenorpyproject.toml.Ruff enforces docstring format and Pydoclint checks documented contracts.
Neither tool measures docstring coverage across the owned Python source set.
Add a pinned
interrogategate so the repository has an explicit, repeatablecoverage requirement for its Python infrastructure.
Scope
Include these repository-owned Python sources:
scripts/tests/workflow_contracts/Keep the existing exclusions for estate-synchronised spelling helpers explicit.
Do not treat Netsuke as a Python distribution.
pyproject.tomldeliberatelyhas no
[project]or[build-system]table.Required work
Measure the current baseline with
interrogate==1.7.0.Record the command, source scope, coverage percentage, and missing-definition
count in this issue before selecting the initial gate threshold.
Define the gate scope and exclusions.
Use the existing
PYTHON_SOURCESownership boundary unless a documented,path-specific exception is required.
Add a pinned Makefile tool definition in the established uv-driven form:
Adjust the target arguments only where the measured source layout requires
them. Do not use an unpinned Interrogate version.
Add the Interrogate command to
lint-python, and update the target commentand developer documentation.
Close the missing docstring gaps required by the selected gate.
Keep public entrypoint contracts documented. Use narrow, documented
exclusions only where a source construct cannot carry a docstring.
Add workflow-contract coverage for the new pin and Makefile command.
Extend
tests/workflow_contracts/python_toolchain_sync_test.py, or add afocused contract test, so the pin remains exact and CI/local configuration
cannot drift.
Triage test-only and helper-only gaps separately when they need a distinct
policy for nested closures or test functions.
Overload limitation
The repository configures
typingwith thetypalias.@typ.overloadstubscannot carry docstrings because Ruff
D418forbids them. Interrogate 1.7.0recognises only the literal
typing.overloadandoverloadspellings for--ignore-overloaded-functions. It does not recognisetyp.overload.If overload stubs enter the scanned scope, use a targeted
--ignore-regexworkaround for those stubs. Do not weaken the general rule. Ruff's
undocumented-public-functionrule must continue to guard the realimplementation.
Acceptance criteria
interrogate==1.7.0baseline for theselected Netsuke Python source scope.
MakefilepinsINTERROGATE_VERSIONto an exact version.make lint-pythonruns Interrogate against the documented source scope.threshold.
typ.overloadexclusion uses a narrow--ignore-regexrule.docs/developers-guide.mddocuments the gate, source scope, andexceptions.
make lintandmake test-workflow-contractspass.Context
This work aligns Netsuke with the estate's docstring-coverage policy while
respecting its Rust-first architecture and uv-driven Python tooling.
Requested by @leynos in PR #641:
#641