T06
The repair should normalize one literal leading ./ inside the shared vendor_mirror_canonical helper, using the normalized string for both prefix matching and suffix extraction. Preserve the original Allowed Paths spelling in diagnostics. Do not use lstrip("./"): it removes meaningful leading dots, as the existing creates normalizer explicitly explains.
Current behavior, inferred from source rather than executed:
src/gzkit/governance/brief_path_validity.py:94–101only removes trailing slashes before matching its five mirror prefixes../.claude/rules/tests.mdtherefore misses detection, although.claude/rules/tests.mdmaps to.gzkit/rules/tests.md.- At lines 197–222, mirror refusal precedes existence and creation exemptions. A prefixed existing mirror passes the filesystem check; a missing prefixed mirror ordinarily produces only a missing-file error. If declared for creation, it can pass entirely because
_normalize_for_createsalready removes./. - The map covers Claude rules/skills, GitHub skills/instructions, and agents skills. Normalize before computing the tail; changing only the prefix comparison would corrupt canonical advice by slicing the original string at the wrong offset. Preserve root-directory, trailing-slash, nested-path, and glob suffix behavior.
Coupled obligations:
- Repair the shared helper rather than adding separate fixes in command handlers.
commands/plan_audit_cmd.py:394–421unions brief and plan creation declarations before calling the shared checker.commands/obpi_cmd.py:957–977uses the brief wrapper; both single and batch validation invoke it only under--authored(lines 1006 and 1056).commands/adr_promote.py:336–367also uses the wrapper. These consumers should inherit identical refusal and canonical advice without changed signatures or duplicated mapping tables. - Retain refusal before creation exemptions. Cover inline
**CREATE**, “Creates these files” sections, and the scaffolded “intentionally created in this OBPI” hint. Canonical net-new paths must remain exempt from existence errors. - Update the helper’s documentation and relevant operator examples in
obpi-validate.mdandplan-audit.md; both full manpages currently omit this path-validity detail. Explain that a leading./changes neither mirror classification nor canonical advice. The primarygz-obpi-specifyskill already states mirrors fail regardless of creation; any explanatory addition belongs in the primary skill and its generated distribution/mirrors, not a hand-edited vendor copy. - Preserve existing command boundaries: promotion checks occur after application and
--forceoverrides their structural errors (adr_promote.py:423–437). This task should not silently promise atomic refusal or remove that override.
Proposed verification, not performed:
- Add failing
unittestcases intests/governance/test_brief_path_validity.py: independently specified canonical results for all five mappings, with/without./, root with/without trailing slash, nested file, and glob. Assert exact canonical tails. - Exercise shared checking with existing mirrors, missing mirrors, and creation declarations. Require a mirror diagnostic containing the original input and correct canonical destination, rather than accepting any error. Pair with canonical and unrelated-path controls, including
./.claude/plans/...and prefix lookalikes such as.claude/rules-extra/.... - Exercise real brief extraction and plan creation extraction. Extend
tests/test_plan_audit_cmd.pyto assert exit 1 and a FAIL receipt containing the correct gap for prefixed mirrors, including brief-only and plan-only creates declarations. - Verify authored single/batch validation and promotion’s wrapper retain that diagnostic. Keep lenient validation and legitimate creation behavior unchanged. Run focused tests first, then applicable repository quality/docs checks during authorized implementation; no results are claimed here.
Uncertainty: reconciliation is a separate existence/drift engine (governance/brief_reconcile.py) and does not refuse even unprefixed mirrors. Making it enforce a new mirror policy would broaden this spelling-equivalence repair and requires an explicit scope decision. I have not established live work ownership from the intentionally excluded briefs/history, nor exhaustively inspected every validation surface.
Read inventory: /tmp/gzkit-remedy-inputs/T06.md; under /tmp/gzkit-remedy-snapshot/, full reads of src/gzkit/governance/{brief_path_validity,brief_reconcile}.py, tests/governance/test_brief_path_validity.py, and docs/user/manpages/{obpi-validate,plan-audit,adr-promote}.md; excerpts/search matches from src/gzkit/commands/{plan_audit_cmd,obpi_cmd,adr_promote}.py, tests/{test_plan_audit_cmd,test_obpi_template}.py, docs/user/manpages/plan.md, .gzkit/skills/{gz-plan-audit,gz-obpi-specify}/SKILL.md. Also performed snapshot file inventory and symbol searches across supplied source/tests/user-docs/primary-skills/rules; search matches were not whole-file reads. Some attempted filenames did not exist. Actual shell/read call count: 11, including task read and this output write. No checks or source edits executed.