T11

The required repair is to resolve the scan directory as project_root / config.paths.source_root / "gzkit". Replace the default location; do not scan both trees or fall back to src/gzkit.

The trace supports these coupled obligations:

  • Configuration → scanner. PathConfig.source_root in config.py already defaults to src; GzkitConfig.load reads the project’s .gzkit.json. commands/common.py::ensure_initialized supplies that loaded configuration, and check_config_paths_cmd already passes it to the scanner. Nevertheless, _collect_source_path_literal_issues hardcodes src/gzkit and returns no issues when it is absent. Thus a relocated package can escape inspection while the separate required-directory check correctly checks the configured source root. No new option, schema field, or parameter is needed. Keep the fixed gzkit suffix, as the task explicitly establishes that package layout.
  • Scanner → classification. Preserve _PATH_SEGMENT_RE, manifest/config coverage, both central exemptions, and module-local _AUDIT_SUBJECT_LITERALS processing. Manifest flattening derives parents; config flattening deliberately does not. Coverage matching accepts equality and segment-bounded ancestor/descendant relationships. Subject declarations require the exact name, module-level assignment, and exact normalized literal; they cannot exempt another module or undeclared children. Changing the traversal root must not widen recognized literal prefixes or exemptions.
  • Scanner → evidence. tests/test_config_paths.py exercises the default layout, but its real-repository acceptance test constructs GzkitConfig() rather than loading project configuration. Change that consumer to load the project config and establish that the configured package contains Python source before accepting an empty issue list. Otherwise the acceptance test can remain green by scanning nothing after relocation. Keep the helper’s existing absent-package behavior for ordinary projects.
  • Issues → CLI and automation. check_config_paths_cmd aggregates source findings with other path checks, emits {valid, issues} JSON or human output, and exits 1 on issues. The parser already forwards --json. Both inspected chore acceptance.json files consume the command’s exit status. Preserve these contracts; they need verification, not new command registrations or altered acceptance thresholds.
  • Behavior → documentation. The scanner docstring fixes scope at src/gzkit; the manpage omits source scanning entirely. Update both, and explain configured scope in the runbook’s verification entry. docs/AGENTS.md requires documentation to track behavior in the same patch. The existing skill routes to the right command and promises no conflicting output form; assess its scope explanation alongside the manpage. Documentation coverage checks existence/references/docstrings, so passing them alone cannot establish semantic accuracy.

Proposed verification, not executed: use isolated unittest fixtures with a nested configured root and a recognized, genuinely unmapped literal such as artifacts/unknown/reports. Assert the finding’s relocated project-relative filename. Place a different violation in the old tree and prove it is ignored, including when the configured package is absent. Retain default-root coverage. Under relocation, verify manifest-governed and config-governed literals, exempt examples, undeclared siblings, and subject declaration scoping. Add CLI cases loading .gzkit.json, with otherwise valid layouts: parsed JSON must report the relocated finding and exit 1; removing it must produce success despite an old-tree violation. These cases distinguish real scanning from a vacuous pass.

Policy reconciliation: config-first resource resolution supports the repair; the chore’s explicit audit-subject carve-out prevents its broad “every resource path” wording from authorizing removal of exemptions. “Defaults” in scanner prose actually means values from the supplied config instance; preserve that behavior. Manifest generation prefers detected structure over config fallback, so manifest/config roots can disagree. The task settles scan selection in favor of configuration; retain the manifest’s separate coverage role. Manifest precedence, fixed-root CLI documentation scanning, and the fixed manifest loader are independent leads, not required repairs here.

No implementation, checks, or governance execution occurred. Runtime results, omitted governance/ADR material, and broader relocation support remain unverified. This bounded trace is not proof of completeness.

Read inventory: 9 shell/read calls, including task read and response write. Root: /tmp/gzkit-remedy-snapshot/. Full or partial reads: AGENTS.md; .gzkit.json; .gzkit/manifest.json; .gzkit/rules/{cli,tests,tool-skill-runbook-alignment}.md; .gzkit/skills/gz-check-config-paths/SKILL.md; docs/AGENTS.md; docs/user/{runbook.md,manpages/check-config-paths.md,skills/gz-check-config-paths.md}; src/gzkit/{config.py,sync.py,sync_surfaces.py,commands/{common,config_paths,init_cmd}.py,cli/parser_maintenance.py,doc_coverage/scanner.py,schemas/manifest.json}; src/gzkit/chores/{hardcoded-root-eradication,config-paths-remediation}/{CHORE.md,acceptance.json}; tests/{test_config_paths.py,commands/test_audit.py}. Some combined output was truncated. Additional operations: corpus-wide keyword searches/path inventories and a symbol search in src/gzkit/governance/trust_audits/cli.py; attempted .gzkit/rules/governance-core.md read failed. Task read: /tmp/gzkit-remedy-inputs/T11.md. Sole write: /tmp/gzkit-remedy-responses/T11.md.