T05

The necessary runtime change is to select project_root / config.paths.source_root / "gzkit" in _collect_source_path_literal_issues. The configured directory replaces src; there should be no fallback or combined scan. This is an assessment from source inspection, not executed evidence.

The governing chain is concrete: the task requires relocation support; the config-first chore says variable resource locations belong in configuration; PathConfig.source_root already defaults to src; GzkitConfig.load reads the nested paths object; ensure_initialized loads the project’s .gzkit.json; the CLI handler passes that configuration to the collector. The collector nevertheless constructs project_root / "src" / "gzkit". Consequently a relocated package can escape auditing, while obsolete files under src/gzkit remain audited. The handler already checks existence/type of the configured source directory. No new configuration field, flag, or parameter threading is needed.

Preserve the classification pipeline. Manifest mappings include derived parents; configured path values do not gain derived parents. Their union feeds the existing segment-boundary coverage matcher. Retain its exact/ancestor/descendant matching, fixed recognized prefixes, explicit exempt literals, AST traversal and filtering, and module-local _AUDIT_SUBJECT_LITERALS declarations. Declaration names and normalized literal matches remain exact; declarations must not leak between modules. The chore expressly distinguishes resource resolution from audit subjects: labeling the scan location an exempt subject would not repair configuration-driven resource selection.

There are wording disagreements to reconcile without changing semantics. _flatten_config_paths describes its collection as exact, but the downstream matcher also grants ancestor/descendant coverage; “exact” means no derived-parent expansion here. The collector describes declared defaults, but actually uses the supplied configuration’s current values. Its matching helper mentions suffixes, whereas the implementation checks segment-aligned ancestry, not arbitrary suffixes. Update these explanations alongside the collector’s hardcoded src/gzkit scope description. Do not broaden coverage or union in default configuration values under cover of this fix.

Coupled obligations and proposed verification:

  • Add deterministic unittest fixtures under both default and custom, including nested, source roots. Plant an ungoverned recognized literal such as artifacts/unknown/reports in the configured package. Assert its issue and project-relative POSIX file path. A red test must fail because scanning misses that file, not because setup fails.
  • Plant a separate offending file in the old default package and prove it is ignored when configuration selects another root. With the configured package absent, retain the collector’s empty result even if the old package exists. Preserve recursive Python-only scanning and existing parse/read-error handling.
  • Exercise positive governed/exempt cases alongside negative controls in the relocated tree: manifest mapping, configured value, explicit exemptions, local declarations, undeclared sibling, declaration borrowing, and parent-only declarations. Positive-only empty-result tests could pass with scanning disabled.
  • Through the actual CLI parser and handler, load a custom source_root from disk, inspect JSON valid/issues and exit 1 for an offending literal, then verify clean exit 0. Keep other required paths valid. Test differing manifest/config source roots: configuration selects the scan; manifest mappings still participate in classification.
  • Repair test_the_real_repository_reports_no_unmapped_literals to load project configuration rather than constructing GzkitConfig(). Its current default masks relocation. Keep default-layout unit fixtures intentionally defaulted.
  • Document the source-literal audit and configured package scope in the manpage. Review the chore’s claimed “COMPLETE exemption census” rooted at src/ so relocation does not hide declarations. The inspected skill/runbook retain the same command and output expectations; no new routing or registration is required.

Independent leads: manifest generation prioritizes detected structure over configured paths, and common manifest loading hardcodes its location. These are not prerequisites to fixing scanner selection; record them for separate assessment. Absolute/outside-project roots and unreadable-source policy remain unresolved beyond this task’s relocation premise. Governance history and omitted doctrine files were unavailable; no checks, tests, or workflows were executed, and completeness is not proven.

Read inventory: paths below are relative to /tmp/gzkit-remedy-snapshot; some reads were excerpts or output-truncated. src/gzkit/commands/{config_paths,common}.py; src/gzkit/{config,sync,sync_surfaces}.py; src/gzkit/cli/{parser_maintenance,parser_handler_manifest}.py; src/gzkit/schemas/manifest.json; src/gzkit/chores/hardcoded-root-eradication/CHORE.md; tests/{test_config_paths,test_config}.py; tests/commands/test_audit.py; .gzkit.json; .gzkit/rules/{cli,tests,tool-skill-runbook-alignment}.md; .gzkit/skills/gz-check-config-paths/SKILL.md; docs/user/{manpages/check-config-paths,skills/gz-check-config-paths,runbook}.md. Also read /tmp/gzkit-remedy-inputs/T05.md; searched source, tests, data, rules, skills and user-doc trees. Failed reads: .gzkit/rules/governance-core.md, docs/governance/{trust-doctrine,state-doctrine}.md; one unmatched shell glob. Actual shell/read call count: 13, including task read and this output write.