T09
The repair is to select project_root / config.paths.source_root / "gzkit" in _collect_source_path_literal_issues. The configured directory replaces src; do not scan both or introduce fallback discovery.
Current behavior, established by reading:
src/gzkit/config.pydefinesPathConfig.source_root, defaulting tosrc, and loads configured values from.gzkit.json.commands/common.py::ensure_initializedloads that file.check_config_paths_cmdalready passes the resulting config into the scanner and checks the configured source directory for existence/type.- Nevertheless,
commands/config_paths.pyscans onlyproject_root / "src" / "gzkit". If absent, it returns no literal issues. Thus a relocated package escapes inspection, and a leftover default tree can be inspected incorrectly. - The scanner recursively reads sorted Python files, parses AST string constants, and reports repository-relative file paths. It skips missing scan roots and unreadable or syntactically invalid files. Preserve these behaviors for this bounded repair.
Necessary coupled obligations:
- Update the scanner’s
src/gzkit/docstring to describe<paths.source_root>/gzkit. Keep its existing config parameter and CLI wiring; no new configuration field, parser flag, or schema is needed. - Preserve classification: known-prefix regex, whitespace handling, URL/length exclusions, global explicit exemptions, manifest coverage and config coverage. Manifest extraction derives parents; config extraction uses configured values without deriving parents. Both feed the existing segment-aware equality/ancestor/descendant matcher. Calling config coverage simply “exact matching” would misdescribe that matcher.
- Preserve
_AUDIT_SUBJECT_LITERALS: exact declaration name, module-level assignments only, normalized exact literal exemption, scoped to the declaring file. Do not widen the regex to include arbitrary configured source names: relocating the inspected files does not change which literals the audit recognizes. - Update
tests/test_config_paths.pyand command-level coverage intests/commands/test_audit.py. Its real-repository acceptance test currently suppliesGzkitConfig()instead of loading project configuration. Make that acceptance witness inspect the actual configured package and establish that it exists/contains Python inputs; otherwise a relocation could leave a vacuous green assertion. Preserve the helper’s legitimate missing-package behavior for adopter projects. - Extend
docs/user/manpages/check-config-paths.md: its “What It Checks” currently omits source literal scanning entirely. Explain configured package scope, default, replacement behavior, and governed/exempt meaning. Update hardcoded exemption-census examples in scanner/test commentary to describe the configured source tree while identifyingsrcas the default example. - The canonical skill and user skill page describe a generic command workflow; they need no forced behavioral rewrite. If clarifying scope there, edit
.gzkit/skills/gz-check-config-paths/SKILL.md, bump skill version/review date, and regenerate package/vendor copies per.gzkit/rules/AGENTS.md; do not manually edit mirrors.
Proposed verification, not executed:
- First add a failing regression with
source_root="application", a nestedapplication/gzkit/.../bad.py, and an unmapped recognized literal such asartifacts/unknown/reports. Assert the exact issue and relocated repository-relative filename. - Plant distinguishable violations in both relocated and default package trees. Expect only the relocated violation. Repeat with the configured package absent and a violating default tree present: expect no source issues, proving no fallback.
- Retain default-root detection and add a nested configured source directory case. Keep fixtures’ manifest/config coverage separate from scan selection so accidental broad exemptions cannot make tests green.
- Exercise mapped manifest paths, config-only discovery-index coverage, undeclared siblings, explicit exemptions, and all module-declaration scope boundaries under the relocated root. Include a positive violation alongside exemption cases to prove scanning occurred.
- Use an initialized command fixture with persisted custom configuration and otherwise valid required paths. Verify JSON
valid, issue fields, exit 1 for a source violation, and success after its removal; verify human output too. Retain existing missing-path and legacy-OBPI tests. - Subsequently run relevant unittest modules, repository quality checks, and strict documentation validation in the complete checkout. No pass result is claimed here.
Uncertainty: absolute/outside-project paths and symlinks are not specified; existing relative reporting may constrain them. Do not silently add a containment policy. Historical ownership, release routing, and complete-checkout execution remain unassessed.
Read inventory (snapshot-relative): full content of src/gzkit/commands/config_paths.py, tests/test_config_paths.py, src/gzkit/config.py, .gzkit.json, .gzkit/skills/gz-check-config-paths/SKILL.md, docs/user/manpages/check-config-paths.md, docs/user/skills/gz-check-config-paths.md; excerpts of src/gzkit/commands/common.py, src/gzkit/cli/parser_maintenance.py, tests/commands/test_audit.py, docs/user/runbook.md, .gzkit/rules/AGENTS.md (output truncated). Searches inspected matching lines across snapshot Python/JSON/config/skill files and .gzkit/rules, docs/user; broad output was truncated. Attempted .gzkit/rules/config-paths.md was missing. Also read /tmp/gzkit-remedy-inputs/T09.md.
Actual shell/read calls: 7, including task read and this response write. No checks or source edits executed.