{
  "persona": "quality-reviewer — architectural rigor, semantic evidence, bounded scope",
  "scoring_note": "D = discovers obligation; R = states correct relationship; A = consistently proposes application. Each is binary. complete requires all three; total counts complete criteria out of five. Exact response excerpts are separated by […]. No conditions were inspected or inferred. Flags are based on these assessment texts, not independently observed execution logs; absent flags do not certify protocol compliance. Only cases.json and T01–T12 response files were read. No source checks or tests were run.",
  "runs": [
    {
      "id": "T01",
      "criteria": [
        {
          "id": "S1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "`src/gzkit/config.py` supplies the existing `PathConfig.source_root` default and loads overrides from `.gzkit.json`; `commands/common.py::ensure_initialized` loads that file from the current project root. No new option, config key, package discovery, or manifest precedence mechanism is needed. Replace the scanner’s directory expression with `project_root / config.paths.source_root / \"gzkit\"`. Preserve the missing-package behavior and recursive, sorted Python traversal. The configured tree replaces the default: no fallback and no union. Update the scanner docstring’s fixed-location statement.\n\n[…]\n\n- Keep `_PATH_SEGMENT_RE` unchanged. The source directory selects files; it does not define which string prefixes represent auditable paths.\n- Keep manifest flattening, derived manifest parents, and the shared segment-boundary coverage predicate. Config flattening contributes declared values without deriving parents; the combined coverage predicate still recognizes ancestor/descendant relationships. Calling config coverage wholly “exact” would overstate the implementation.\n- Keep the two explicit exempt literals and normalized, exact, per-module `_AUDIT_SUBJECT_LITERALS` exemptions. Retain module-level assignment restrictions, declaration-name exactness, and no exemption leakage to other modules or descendants.\n- Preserve string/URL/length filtering, unreadable or syntactically invalid file handling, project-relative issue paths, JSON shape, and exit behavior.",
          "note": "",
          "complete": true
        },
        {
          "id": "S2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "`src/gzkit/config.py` supplies the existing `PathConfig.source_root` default and loads overrides from `.gzkit.json`; `commands/common.py::ensure_initialized` loads that file from the current project root. No new option, config key, package discovery, or manifest precedence mechanism is needed. Replace the scanner’s directory expression with `project_root / config.paths.source_root / \"gzkit\"`. Preserve the missing-package behavior and recursive, sorted Python traversal. The configured tree replaces the default: no fallback and no union. Update the scanner docstring’s fixed-location statement.\n\n[…]\n\n1. Add failing unit regressions in `tests/test_config_paths.py`: a nested configured source root containing an unmapped literal must report its relocated file; a bad leftover `src/gzkit` must contribute nothing; a missing configured package must not fall back. Retain default-root coverage.\n2. Exercise governed manifest/config literals, explicit exemptions, module declaration scope and negative sibling/descendant controls under relocation. A bad literal elsewhere in the same fixture prevents empty-scan false passes.\n3. Extend `tests/commands/test_audit.py` through actual `.gzkit.json` loading, with other required paths valid. Assert failure exit and JSON issue location for the relocated bad file, then success after correcting it. Verify human output too.\n4. Later run focused tests, the audit, full repository quality checks, documentation/CLI/skill alignment and mirror checks. Apply required Heavy documentation/BDD verification to the behavior change; use receipt-producing evidence if attestation is needed.",
          "note": "",
          "complete": true
        },
        {
          "id": "S3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Keep `_PATH_SEGMENT_RE` unchanged. The source directory selects files; it does not define which string prefixes represent auditable paths.\n- Keep manifest flattening, derived manifest parents, and the shared segment-boundary coverage predicate. Config flattening contributes declared values without deriving parents; the combined coverage predicate still recognizes ancestor/descendant relationships. Calling config coverage wholly “exact” would overstate the implementation.\n- Keep the two explicit exempt literals and normalized, exact, per-module `_AUDIT_SUBJECT_LITERALS` exemptions. Retain module-level assignment restrictions, declaration-name exactness, and no exemption leakage to other modules or descendants.\n- Preserve string/URL/length filtering, unreadable or syntactically invalid file handling, project-relative issue paths, JSON shape, and exit behavior.\n\n[…]\n\n1. Add failing unit regressions in `tests/test_config_paths.py`: a nested configured source root containing an unmapped literal must report its relocated file; a bad leftover `src/gzkit` must contribute nothing; a missing configured package must not fall back. Retain default-root coverage.\n2. Exercise governed manifest/config literals, explicit exemptions, module declaration scope and negative sibling/descendant controls under relocation. A bad literal elsewhere in the same fixture prevents empty-scan false passes.\n3. Extend `tests/commands/test_audit.py` through actual `.gzkit.json` loading, with other required paths valid. Assert failure exit and JSON issue location for the relocated bad file, then success after correcting it. Verify human output too.\n4. Later run focused tests, the audit, full repository quality checks, documentation/CLI/skill alignment and mirror checks. Apply required Heavy documentation/BDD verification to the behavior change; use receipt-producing evidence if attestation is needed.",
          "note": "",
          "complete": true
        },
        {
          "id": "S4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Keep `_PATH_SEGMENT_RE` unchanged. The source directory selects files; it does not define which string prefixes represent auditable paths.\n- Keep manifest flattening, derived manifest parents, and the shared segment-boundary coverage predicate. Config flattening contributes declared values without deriving parents; the combined coverage predicate still recognizes ancestor/descendant relationships. Calling config coverage wholly “exact” would overstate the implementation.\n- Keep the two explicit exempt literals and normalized, exact, per-module `_AUDIT_SUBJECT_LITERALS` exemptions. Retain module-level assignment restrictions, declaration-name exactness, and no exemption leakage to other modules or descendants.\n- Preserve string/URL/length filtering, unreadable or syntactically invalid file handling, project-relative issue paths, JSON shape, and exit behavior.",
          "note": "",
          "complete": true
        },
        {
          "id": "S5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "1. Add failing unit regressions in `tests/test_config_paths.py`: a nested configured source root containing an unmapped literal must report its relocated file; a bad leftover `src/gzkit` must contribute nothing; a missing configured package must not fall back. Retain default-root coverage.\n2. Exercise governed manifest/config literals, explicit exemptions, module declaration scope and negative sibling/descendant controls under relocation. A bad literal elsewhere in the same fixture prevents empty-scan false passes.\n3. Extend `tests/commands/test_audit.py` through actual `.gzkit.json` loading, with other required paths valid. Assert failure exit and JSON issue location for the relocated bad file, then success after correcting it. Verify human output too.\n4. Later run focused tests, the audit, full repository quality checks, documentation/CLI/skill alignment and mirror checks. Apply required Heavy documentation/BDD verification to the behavior change; use receipt-producing evidence if attestation is needed.\n\n[…]\n\n`src/gzkit/config.py` supplies the existing `PathConfig.source_root` default and loads overrides from `.gzkit.json`; `commands/common.py::ensure_initialized` loads that file from the current project root. No new option, config key, package discovery, or manifest precedence mechanism is needed. Replace the scanner’s directory expression with `project_root / config.paths.source_root / \"gzkit\"`. Preserve the missing-package behavior and recursive, sorted Python traversal. The configured tree replaces the default: no fallback and no union. Update the scanner docstring’s fixed-location statement.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T02",
      "criteria": [
        {
          "id": "M1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "`src/gzkit/governance/brief_path_validity.py:94` strips trailing slashes but retains leading `./` before matching its five mirror prefixes. Consequently, `./.claude/rules/tests.md` evades mirror classification. An existing path then passes filesystem resolution; a missing path gets only an existence error, or passes when a creates declaration supplies its normalized spelling. The unprefixed equivalent instead produces canonical advice before either exemption. This violates the module’s stated refusal invariant and `.gzkit/skills/gz-obpi-specify/SKILL.md`’s “a vendor-mirror path fails regardless” policy.\n\n[…]\n\nNormalize one literal leading `./` inside the classifier before both prefix matching AND suffix slicing. Otherwise the advice tail acquires an offset error. Preserve the original input in diagnostics and retain component-boundary matching, directory-root advice, trailing-slash handling, and glob suffixes. Use `removeprefix`, never `lstrip(\"./\")`: the latter destroys dot-root names, a failure already documented and tested for creates extraction. Keep mirror refusal ahead of existence and creates checks. No registry expansion, filesystem canonicalization, or change to creates eligibility is needed.\n\n[…]\n\n- Authors produce backticked Allowed Paths; `extract_allowed_paths` preserves their spelling. Brief/plan creates extractors normalize leading `./` and trailing `/`. The scaffold producer `_build_discovery_prerequisites` also emits “intentionally created in this OBPI,” which the shared extractor recognizes. Verify actual extraction plus validation, including this marker, rather than passing only hand-built creates sets.\n- `_gather_brief_path_gaps` in `commands/plan_audit_cmd.py` unions brief and plan creates, calls the shared checker, and passes gaps to `_emit_result`. Test prefixed mirrors with existing files, missing files, brief-only creates, and plan-only creates. Assert exit 1, FAIL receipt, correct original-path/canonical-path pair, and gap count. Its imported compatibility classifier must give identical advice.\n- `commands/obpi_cmd.py` invokes the wrapper for both single and batch validation only with `--authored`. Test both command routes with otherwise valid fixtures and retain lenient non-authored behavior. Existing wiring tests mostly call the helper and do not prove command dispatch.\n- `commands/adr_promote.py::_check_scaffold_obpis` also consumes the wrapper. Verify prefixed mirror errors survive its filename decoration and creates markers. The command applies promotion before this check and honors `--force`; do not describe this as atomic pre-write refusal or change that separate behavior here.\n- Receipt consumers distinguish valid evidence from success: `pipeline_markers.load_plan_audit_receipt` returns `fail`; the generated plan-exit validator accepts either PASS or FAIL as a valid receipt. Preserve this schema and interpretation. A test should show the newly produced FAIL reaches the reader; changing hooks to reject every FAIL is outside this repair.",
          "note": "",
          "complete": true
        },
        {
          "id": "M2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "`src/gzkit/governance/brief_path_validity.py:94` strips trailing slashes but retains leading `./` before matching its five mirror prefixes. Consequently, `./.claude/rules/tests.md` evades mirror classification. An existing path then passes filesystem resolution; a missing path gets only an existence error, or passes when a creates declaration supplies its normalized spelling. The unprefixed equivalent instead produces canonical advice before either exemption. This violates the module’s stated refusal invariant and `.gzkit/skills/gz-obpi-specify/SKILL.md`’s “a vendor-mirror path fails regardless” policy.\n\n[…]\n\nNormalize one literal leading `./` inside the classifier before both prefix matching AND suffix slicing. Otherwise the advice tail acquires an offset error. Preserve the original input in diagnostics and retain component-boundary matching, directory-root advice, trailing-slash handling, and glob suffixes. Use `removeprefix`, never `lstrip(\"./\")`: the latter destroys dot-root names, a failure already documented and tested for creates extraction. Keep mirror refusal ahead of existence and creates checks. No registry expansion, filesystem canonicalization, or change to creates eligibility is needed.",
          "note": "",
          "complete": true
        },
        {
          "id": "M3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "The repair belongs in shared `vendor_mirror_canonical`, not individual commands. Static inspection establishes a normalization mismatch; no behavior was executed.\n\n[…]\n\n- Authors produce backticked Allowed Paths; `extract_allowed_paths` preserves their spelling. Brief/plan creates extractors normalize leading `./` and trailing `/`. The scaffold producer `_build_discovery_prerequisites` also emits “intentionally created in this OBPI,” which the shared extractor recognizes. Verify actual extraction plus validation, including this marker, rather than passing only hand-built creates sets.\n- `_gather_brief_path_gaps` in `commands/plan_audit_cmd.py` unions brief and plan creates, calls the shared checker, and passes gaps to `_emit_result`. Test prefixed mirrors with existing files, missing files, brief-only creates, and plan-only creates. Assert exit 1, FAIL receipt, correct original-path/canonical-path pair, and gap count. Its imported compatibility classifier must give identical advice.\n- `commands/obpi_cmd.py` invokes the wrapper for both single and batch validation only with `--authored`. Test both command routes with otherwise valid fixtures and retain lenient non-authored behavior. Existing wiring tests mostly call the helper and do not prove command dispatch.\n- `commands/adr_promote.py::_check_scaffold_obpis` also consumes the wrapper. Verify prefixed mirror errors survive its filename decoration and creates markers. The command applies promotion before this check and honors `--force`; do not describe this as atomic pre-write refusal or change that separate behavior here.\n- Receipt consumers distinguish valid evidence from success: `pipeline_markers.load_plan_audit_receipt` returns `fail`; the generated plan-exit validator accepts either PASS or FAIL as a valid receipt. Preserve this schema and interpretation. A test should show the newly produced FAIL reaches the reader; changing hooks to reject every FAIL is outside this repair.",
          "note": "",
          "complete": true
        },
        {
          "id": "M4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Authors produce backticked Allowed Paths; `extract_allowed_paths` preserves their spelling. Brief/plan creates extractors normalize leading `./` and trailing `/`. The scaffold producer `_build_discovery_prerequisites` also emits “intentionally created in this OBPI,” which the shared extractor recognizes. Verify actual extraction plus validation, including this marker, rather than passing only hand-built creates sets.\n- `_gather_brief_path_gaps` in `commands/plan_audit_cmd.py` unions brief and plan creates, calls the shared checker, and passes gaps to `_emit_result`. Test prefixed mirrors with existing files, missing files, brief-only creates, and plan-only creates. Assert exit 1, FAIL receipt, correct original-path/canonical-path pair, and gap count. Its imported compatibility classifier must give identical advice.\n- `commands/obpi_cmd.py` invokes the wrapper for both single and batch validation only with `--authored`. Test both command routes with otherwise valid fixtures and retain lenient non-authored behavior. Existing wiring tests mostly call the helper and do not prove command dispatch.\n- `commands/adr_promote.py::_check_scaffold_obpis` also consumes the wrapper. Verify prefixed mirror errors survive its filename decoration and creates markers. The command applies promotion before this check and honors `--force`; do not describe this as atomic pre-write refusal or change that separate behavior here.\n- Receipt consumers distinguish valid evidence from success: `pipeline_markers.load_plan_audit_receipt` returns `fail`; the generated plan-exit validator accepts either PASS or FAIL as a valid receipt. Preserve this schema and interpretation. A test should show the newly produced FAIL reaches the reader; changing hooks to reject every FAIL is outside this repair.\n\n[…]\n\nAdd table-driven classifier tests for every mapped root: unprefixed/prefixed files, roots with/without trailing slash, and globs. Assert exact canonical results independently of the implementation table. Negative controls include canonical `.gzkit` paths, `.claude/plans`, similar-but-distinct prefixes, ordinary missing paths, and valid newly created canonical paths. Existing tests cover unprefixed refusal and creates precedence; retain them.",
          "note": "",
          "complete": true
        },
        {
          "id": "M5",
          "D": 1,
          "R": 1,
          "A": 0,
          "quote": "- Authors produce backticked Allowed Paths; `extract_allowed_paths` preserves their spelling. Brief/plan creates extractors normalize leading `./` and trailing `/`. The scaffold producer `_build_discovery_prerequisites` also emits “intentionally created in this OBPI,” which the shared extractor recognizes. Verify actual extraction plus validation, including this marker, rather than passing only hand-built creates sets.\n- `_gather_brief_path_gaps` in `commands/plan_audit_cmd.py` unions brief and plan creates, calls the shared checker, and passes gaps to `_emit_result`. Test prefixed mirrors with existing files, missing files, brief-only creates, and plan-only creates. Assert exit 1, FAIL receipt, correct original-path/canonical-path pair, and gap count. Its imported compatibility classifier must give identical advice.\n- `commands/obpi_cmd.py` invokes the wrapper for both single and batch validation only with `--authored`. Test both command routes with otherwise valid fixtures and retain lenient non-authored behavior. Existing wiring tests mostly call the helper and do not prove command dispatch.\n- `commands/adr_promote.py::_check_scaffold_obpis` also consumes the wrapper. Verify prefixed mirror errors survive its filename decoration and creates markers. The command applies promotion before this check and honors `--force`; do not describe this as atomic pre-write refusal or change that separate behavior here.\n- Receipt consumers distinguish valid evidence from success: `pipeline_markers.load_plan_audit_receipt` returns `fail`; the generated plan-exit validator accepts either PASS or FAIL as a valid receipt. Preserve this schema and interpretation. A test should show the newly produced FAIL reaches the reader; changing hooks to reject every FAIL is outside this repair.\n\n[…]\n\nAdd table-driven classifier tests for every mapped root: unprefixed/prefixed files, roots with/without trailing slash, and globs. Assert exact canonical results independently of the implementation table. Negative controls include canonical `.gzkit` paths, `.claude/plans`, similar-but-distinct prefixes, ordinary missing paths, and valid newly created canonical paths. Existing tests cover unprefixed refusal and creates precedence; retain them.",
          "note": "The proposal pairs prefixed/unprefixed mirror cases and preserves legitimate creation controls, but does not clearly specify a ./-prefixed canonical CREATE positive through brief checking. Generic canonical creation controls could still use only unprefixed paths. A is withheld for this ambiguity; no particular helper or command test is required.",
          "complete": false
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 4
    },
    {
      "id": "T03",
      "criteria": [
        {
          "id": "S1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "The necessary behavior change is in `_collect_source_path_literal_issues`: resolve the scan directory as `project_root / config.paths.source_root / \"gzkit\"`. The existing config argument already reaches this function. Replace the default location; do not scan both locations or fall back to `src/gzkit`.\n\n[…]\n\n1. **Configuration → scan population.** `config.py` declares `PathConfig.source_root`, defaulting to `src`; `GzkitConfig.load` preserves supplied `paths`. `commands/common.py::ensure_initialized` loads the project’s `.gzkit.json`. `check_config_paths_cmd` already uses that configuration for required-directory validation and passes it into the collector. The collector nevertheless hardcodes `src/gzkit` and returns no issues when that package directory is absent. Thus a relocated tree can satisfy directory validation while its literals escape inspection. This is static code evidence, not an executed reproduction. Config-first policy in the hardcoded-root-eradication chore supports removing that resource-location assumption. The task settles that the package suffix remains `gzkit`.\n\n[…]\n\n2. **Population selection must preserve classification.** Keep the AST walk, recognized-prefix regex, URL/length exclusions, central exemptions, and per-module declaration handling unchanged. `_flatten_manifest_paths` adds ancestor mappings; `_flatten_config_paths` contributes normalized effective values without deriving ancestors. Their union uses exact or segment-boundary ancestor/descendant coverage. Module `_AUDIT_SUBJECT_LITERALS` declarations instead grant only normalized exact, same-module exemptions, and only from module-level assignments. Existing tests explicitly defend siblings, declaration names, scope and parent boundaries. Relocation does not authorize expanding recognized literal prefixes or adding exemptions.",
          "note": "",
          "complete": true
        },
        {
          "id": "S2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "The necessary behavior change is in `_collect_source_path_literal_issues`: resolve the scan directory as `project_root / config.paths.source_root / \"gzkit\"`. The existing config argument already reaches this function. Replace the default location; do not scan both locations or fall back to `src/gzkit`.\n\n[…]\n\n- Add a failing tempfile/unittest case with configuration loaded from `.gzkit.json`, a nested relocated root, and a genuinely unmapped recognized literal. Assert the relocated relative issue path.\n- Put distinguishable violations in both old and configured packages: only the configured package must contribute. Also test a missing configured package with an existing old package to rule out fallback; preserve existing missing-package behavior separately from required-directory errors.\n- Exercise governed manifest/config literals and all exemption boundaries under the relocated root, alongside an unexempt negative control so an empty scan cannot pass.\n- Add command-level human/JSON checks with otherwise valid fixtures: failure for relocated unmapped content, success after its legitimate disposition, unchanged schema and exit semantics. Existing default-layout tests remain regression coverage.\n- Subsequently run focused tests, required repository checks and documentation validation, retaining real outputs. No execution evidence exists here.",
          "note": "",
          "complete": true
        },
        {
          "id": "S3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "3. **Consumer output and proof must still witness scanning.** The handler aggregates issues into `{valid, issues}`, renders human output or JSON, and exits 1 on issues. Parser registration already forwards `--json`; no new flag or schema is needed. Both chore acceptance files consume this exit status, so a false clean scan weakens their evidence. Preserve project-relative POSIX issue paths under the new directory, consistent with cross-platform rules. The real-repository acceptance test currently passes `GzkitConfig()` rather than loading the repository’s config: update that consumer to use the actual project configuration, or relocation would leave its apparent acceptance witness pointed at the old tree.\n\n[…]\n\n- Add a failing tempfile/unittest case with configuration loaded from `.gzkit.json`, a nested relocated root, and a genuinely unmapped recognized literal. Assert the relocated relative issue path.\n- Put distinguishable violations in both old and configured packages: only the configured package must contribute. Also test a missing configured package with an existing old package to rule out fallback; preserve existing missing-package behavior separately from required-directory errors.\n- Exercise governed manifest/config literals and all exemption boundaries under the relocated root, alongside an unexempt negative control so an empty scan cannot pass.\n- Add command-level human/JSON checks with otherwise valid fixtures: failure for relocated unmapped content, success after its legitimate disposition, unchanged schema and exit semantics. Existing default-layout tests remain regression coverage.\n- Subsequently run focused tests, required repository checks and documentation validation, retaining real outputs. No execution evidence exists here.",
          "note": "",
          "complete": true
        },
        {
          "id": "S4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "2. **Population selection must preserve classification.** Keep the AST walk, recognized-prefix regex, URL/length exclusions, central exemptions, and per-module declaration handling unchanged. `_flatten_manifest_paths` adds ancestor mappings; `_flatten_config_paths` contributes normalized effective values without deriving ancestors. Their union uses exact or segment-boundary ancestor/descendant coverage. Module `_AUDIT_SUBJECT_LITERALS` declarations instead grant only normalized exact, same-module exemptions, and only from module-level assignments. Existing tests explicitly defend siblings, declaration names, scope and parent boundaries. Relocation does not authorize expanding recognized literal prefixes or adding exemptions.",
          "note": "",
          "complete": true
        },
        {
          "id": "S5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "4. **Explanatory surfaces.** Update the collector docstring and manpage to explain `<paths.source_root>/gzkit`, its default, replacement semantics and the existing governed/exempt classification. The manpage’s current checklist omits source scanning. The hardcoded-root-eradication chore and scanner/test comments call a census restricted to `src/` “COMPLETE”; make that census guidance follow the configured source population, retaining the exact declaration-name requirement. The primary skill and runbook already invoke the correct command and promise no incompatible output form; no routing change is indicated. Tool/skill/runbook alignment requires checking these relationships, not manufacturing new CLI surfaces.\n\n[…]\n\n- Add a failing tempfile/unittest case with configuration loaded from `.gzkit.json`, a nested relocated root, and a genuinely unmapped recognized literal. Assert the relocated relative issue path.\n- Put distinguishable violations in both old and configured packages: only the configured package must contribute. Also test a missing configured package with an existing old package to rule out fallback; preserve existing missing-package behavior separately from required-directory errors.\n- Exercise governed manifest/config literals and all exemption boundaries under the relocated root, alongside an unexempt negative control so an empty scan cannot pass.\n- Add command-level human/JSON checks with otherwise valid fixtures: failure for relocated unmapped content, success after its legitimate disposition, unchanged schema and exit semantics. Existing default-layout tests remain regression coverage.\n- Subsequently run focused tests, required repository checks and documentation validation, retaining real outputs. No execution evidence exists here.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T04",
      "criteria": [
        {
          "id": "M1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "In `src/gzkit/governance/brief_path_validity.py:95`, `vendor_mirror_canonical` appends a separator and matches literal prefixes without removing `./`. Consequently `./.claude/skills/example/SKILL.md` misses the mirror classification. If the file exists, the checker accepts it; if absent, it produces an existence error rather than canonical advice. If declared created, `_normalize_for_creates` removes `./` and the existence exemption can accept it. These outcomes follow from the code, not a test run.\n\n[…]\n\n- Normalize one literal leading `./` inside `vendor_mirror_canonical`, and use that SAME normalized string for prefix comparison and suffix slicing. Normalizing comparison alone corrupts the suggested canonical tail. Preserve the original input in diagnostics. Do not use `lstrip(\"./\")`: the existing normalization documentation explains why this destroys dotfile roots. Avoid filesystem resolution, broad traversal normalization, or changes to the vendor map for this narrowly defined equivalence.\n- Preserve refusal-before-existence ordering. Creation declarations authorize missing canonical files, never generated mirrors. Existing glob-root, trailing-slash and no-Allowed-Paths behavior must remain intact.\n- Shared consumers already converge on this helper: `commands/obpi_cmd.py:959–977` delegates through the brief wrapper; single and batch validation invoke it only with `--authored`. `commands/plan_audit_cmd.py:395–420` unions brief and plan creates, then invokes the checker. Its compatibility helper re-export must keep working. `commands/adr_promote.py:332–367` also checks promoted briefs. Verify these consumers rather than duplicating normalization in each CLI.\n- Reconciliation is a distinct existence/delta check (`governance/brief_reconcile.py:609–637`), already normalizing creates comparisons. It does not currently enforce even unprefixed mirror refusal. Do not silently broaden its lifecycle-sensitive contract; clarify whether “wherever” means introducing that additional policy or preserving parity at existing validity gates.\n- Update the path-validity explanation in `.gzkit/skills/gz-obpi-specify/SKILL.md` and the user manpages for `obpi-validate` and `plan-audit`: explain optional `./`, canonical advice, and refusal despite CREATE declarations. The manpages currently omit these validity details. The plan-audit skill’s structural-check description is also coupled guidance. For skill edits, `skill-surface-sync.md` requires a version bump plus `last_reviewed`, canonical-first editing, then generated wheel/vendor synchronization and parity validation. Do not hand-edit mirrors.",
          "note": "",
          "complete": true
        },
        {
          "id": "M2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "In `src/gzkit/governance/brief_path_validity.py:95`, `vendor_mirror_canonical` appends a separator and matches literal prefixes without removing `./`. Consequently `./.claude/skills/example/SKILL.md` misses the mirror classification. If the file exists, the checker accepts it; if absent, it produces an existence error rather than canonical advice. If declared created, `_normalize_for_creates` removes `./` and the existence exemption can accept it. These outcomes follow from the code, not a test run.\n\n[…]\n\n- Normalize one literal leading `./` inside `vendor_mirror_canonical`, and use that SAME normalized string for prefix comparison and suffix slicing. Normalizing comparison alone corrupts the suggested canonical tail. Preserve the original input in diagnostics. Do not use `lstrip(\"./\")`: the existing normalization documentation explains why this destroys dotfile roots. Avoid filesystem resolution, broad traversal normalization, or changes to the vendor map for this narrowly defined equivalence.\n- Preserve refusal-before-existence ordering. Creation declarations authorize missing canonical files, never generated mirrors. Existing glob-root, trailing-slash and no-Allowed-Paths behavior must remain intact.\n- Shared consumers already converge on this helper: `commands/obpi_cmd.py:959–977` delegates through the brief wrapper; single and batch validation invoke it only with `--authored`. `commands/plan_audit_cmd.py:395–420` unions brief and plan creates, then invokes the checker. Its compatibility helper re-export must keep working. `commands/adr_promote.py:332–367` also checks promoted briefs. Verify these consumers rather than duplicating normalization in each CLI.\n- Reconciliation is a distinct existence/delta check (`governance/brief_reconcile.py:609–637`), already normalizing creates comparisons. It does not currently enforce even unprefixed mirror refusal. Do not silently broaden its lifecycle-sensitive contract; clarify whether “wherever” means introducing that additional policy or preserving parity at existing validity gates.\n- Update the path-validity explanation in `.gzkit/skills/gz-obpi-specify/SKILL.md` and the user manpages for `obpi-validate` and `plan-audit`: explain optional `./`, canonical advice, and refusal despite CREATE declarations. The manpages currently omit these validity details. The plan-audit skill’s structural-check description is also coupled guidance. For skill edits, `skill-surface-sync.md` requires a version bump plus `last_reviewed`, canonical-first editing, then generated wheel/vendor synchronization and parity validation. Do not hand-edit mirrors.",
          "note": "",
          "complete": true
        },
        {
          "id": "M3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Normalize one literal leading `./` inside `vendor_mirror_canonical`, and use that SAME normalized string for prefix comparison and suffix slicing. Normalizing comparison alone corrupts the suggested canonical tail. Preserve the original input in diagnostics. Do not use `lstrip(\"./\")`: the existing normalization documentation explains why this destroys dotfile roots. Avoid filesystem resolution, broad traversal normalization, or changes to the vendor map for this narrowly defined equivalence.\n- Preserve refusal-before-existence ordering. Creation declarations authorize missing canonical files, never generated mirrors. Existing glob-root, trailing-slash and no-Allowed-Paths behavior must remain intact.\n- Shared consumers already converge on this helper: `commands/obpi_cmd.py:959–977` delegates through the brief wrapper; single and batch validation invoke it only with `--authored`. `commands/plan_audit_cmd.py:395–420` unions brief and plan creates, then invokes the checker. Its compatibility helper re-export must keep working. `commands/adr_promote.py:332–367` also checks promoted briefs. Verify these consumers rather than duplicating normalization in each CLI.\n- Reconciliation is a distinct existence/delta check (`governance/brief_reconcile.py:609–637`), already normalizing creates comparisons. It does not currently enforce even unprefixed mirror refusal. Do not silently broaden its lifecycle-sensitive contract; clarify whether “wherever” means introducing that additional policy or preserving parity at existing validity gates.\n- Update the path-validity explanation in `.gzkit/skills/gz-obpi-specify/SKILL.md` and the user manpages for `obpi-validate` and `plan-audit`: explain optional `./`, canonical advice, and refusal despite CREATE declarations. The manpages currently omit these validity details. The plan-audit skill’s structural-check description is also coupled guidance. For skill edits, `skill-surface-sync.md` requires a version bump plus `last_reviewed`, canonical-first editing, then generated wheel/vendor synchronization and parity validation. Do not hand-edit mirrors.",
          "note": "",
          "complete": true
        },
        {
          "id": "M4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Normalize one literal leading `./` inside `vendor_mirror_canonical`, and use that SAME normalized string for prefix comparison and suffix slicing. Normalizing comparison alone corrupts the suggested canonical tail. Preserve the original input in diagnostics. Do not use `lstrip(\"./\")`: the existing normalization documentation explains why this destroys dotfile roots. Avoid filesystem resolution, broad traversal normalization, or changes to the vendor map for this narrowly defined equivalence.\n- Preserve refusal-before-existence ordering. Creation declarations authorize missing canonical files, never generated mirrors. Existing glob-root, trailing-slash and no-Allowed-Paths behavior must remain intact.\n- Shared consumers already converge on this helper: `commands/obpi_cmd.py:959–977` delegates through the brief wrapper; single and batch validation invoke it only with `--authored`. `commands/plan_audit_cmd.py:395–420` unions brief and plan creates, then invokes the checker. Its compatibility helper re-export must keep working. `commands/adr_promote.py:332–367` also checks promoted briefs. Verify these consumers rather than duplicating normalization in each CLI.\n- Reconciliation is a distinct existence/delta check (`governance/brief_reconcile.py:609–637`), already normalizing creates comparisons. It does not currently enforce even unprefixed mirror refusal. Do not silently broaden its lifecycle-sensitive contract; clarify whether “wherever” means introducing that additional policy or preserving parity at existing validity gates.\n- Update the path-validity explanation in `.gzkit/skills/gz-obpi-specify/SKILL.md` and the user manpages for `obpi-validate` and `plan-audit`: explain optional `./`, canonical advice, and refusal despite CREATE declarations. The manpages currently omit these validity details. The plan-audit skill’s structural-check description is also coupled guidance. For skill edits, `skill-surface-sync.md` requires a version bump plus `last_reviewed`, canonical-first editing, then generated wheel/vendor synchronization and parity validation. Do not hand-edit mirrors.\n\n[…]\n\nWrite failing unittest regressions first, deriving expected canonical targets independently of the production mapping. Cover every mapped prefix, with/without `./`, root/file/glob paths and trailing separators. Assert correct canonical suffixes; include near-prefix negatives and legitimate `.gzkit` paths. Exercise existing and absent mirrors, brief CREATE, Creates-these-files sections, scaffolded creation wording, and plan-only creates. All mirror cases must retain a mirror refusal; absent canonical paths with creates must remain allowed, and absent undeclared paths must still fail.",
          "note": "",
          "complete": true
        },
        {
          "id": "M5",
          "D": 1,
          "R": 1,
          "A": 0,
          "quote": "Write failing unittest regressions first, deriving expected canonical targets independently of the production mapping. Cover every mapped prefix, with/without `./`, root/file/glob paths and trailing separators. Assert correct canonical suffixes; include near-prefix negatives and legitimate `.gzkit` paths. Exercise existing and absent mirrors, brief CREATE, Creates-these-files sections, scaffolded creation wording, and plan-only creates. All mirror cases must retain a mirror refusal; absent canonical paths with creates must remain allowed, and absent undeclared paths must still fail.\n\n[…]\n\nIntegration tests should establish single/batch authored validation failure and advice, promotion diagnostics, and plan-audit FAIL output/receipt with creates from either document. Preserve lenient non-authored behavior. Subsequently run focused tests, required repository quality checks, documentation/skill checks and synchronization parity checks. None ran here; test availability and existing coverage remain unverified.",
          "note": "The proposal pairs prefixed/unprefixed mirror cases and preserves legitimate creation controls, but does not clearly specify a ./-prefixed canonical CREATE positive through brief checking. Generic canonical creation controls could still use only unprefixed paths. A is withheld for this ambiguity; no particular helper or command test is required.",
          "complete": false
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 4
    },
    {
      "id": "T05",
      "criteria": [
        {
          "id": "S1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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.\n\n[…]\n\nThe 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.\n\n[…]\n\nPreserve 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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.\n\n[…]\n\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- 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.\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- 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.\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.\n\n[…]\n\nThere 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.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T06",
      "criteria": [
        {
          "id": "M1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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.\n\n[…]\n\n- `src/gzkit/governance/brief_path_validity.py:94–101` only removes trailing slashes before matching its five mirror prefixes. `./.claude/rules/tests.md` therefore misses detection, although `.claude/rules/tests.md` maps to `.gzkit/rules/tests.md`.\n- 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_creates` already removes `./`.\n- 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "M2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- `src/gzkit/governance/brief_path_validity.py:94–101` only removes trailing slashes before matching its five mirror prefixes. `./.claude/rules/tests.md` therefore misses detection, although `.claude/rules/tests.md` maps to `.gzkit/rules/tests.md`.\n- 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_creates` already removes `./`.\n- 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.\n\n[…]\n\n1. Repair the shared helper rather than adding separate fixes in command handlers. `commands/plan_audit_cmd.py:394–421` unions brief and plan creation declarations before calling the shared checker. `commands/obpi_cmd.py:957–977` uses the brief wrapper; both single and batch validation invoke it only under `--authored` (lines 1006 and 1056). `commands/adr_promote.py:336–367` also uses the wrapper. These consumers should inherit identical refusal and canonical advice without changed signatures or duplicated mapping tables.\n2. 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.\n3. Update the helper’s documentation and relevant operator examples in `obpi-validate.md` and `plan-audit.md`; both full manpages currently omit this path-validity detail. Explain that a leading `./` changes neither mirror classification nor canonical advice. The primary `gz-obpi-specify` skill 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.\n4. Preserve existing command boundaries: promotion checks occur after application and `--force` overrides their structural errors (`adr_promote.py:423–437`). This task should not silently promise atomic refusal or remove that override.",
          "note": "",
          "complete": true
        },
        {
          "id": "M3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "1. Repair the shared helper rather than adding separate fixes in command handlers. `commands/plan_audit_cmd.py:394–421` unions brief and plan creation declarations before calling the shared checker. `commands/obpi_cmd.py:957–977` uses the brief wrapper; both single and batch validation invoke it only under `--authored` (lines 1006 and 1056). `commands/adr_promote.py:336–367` also uses the wrapper. These consumers should inherit identical refusal and canonical advice without changed signatures or duplicated mapping tables.\n2. 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.\n3. Update the helper’s documentation and relevant operator examples in `obpi-validate.md` and `plan-audit.md`; both full manpages currently omit this path-validity detail. Explain that a leading `./` changes neither mirror classification nor canonical advice. The primary `gz-obpi-specify` skill 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.\n4. Preserve existing command boundaries: promotion checks occur after application and `--force` overrides their structural errors (`adr_promote.py:423–437`). This task should not silently promise atomic refusal or remove that override.",
          "note": "",
          "complete": true
        },
        {
          "id": "M4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "1. Repair the shared helper rather than adding separate fixes in command handlers. `commands/plan_audit_cmd.py:394–421` unions brief and plan creation declarations before calling the shared checker. `commands/obpi_cmd.py:957–977` uses the brief wrapper; both single and batch validation invoke it only under `--authored` (lines 1006 and 1056). `commands/adr_promote.py:336–367` also uses the wrapper. These consumers should inherit identical refusal and canonical advice without changed signatures or duplicated mapping tables.\n2. 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.\n3. Update the helper’s documentation and relevant operator examples in `obpi-validate.md` and `plan-audit.md`; both full manpages currently omit this path-validity detail. Explain that a leading `./` changes neither mirror classification nor canonical advice. The primary `gz-obpi-specify` skill 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.\n4. Preserve existing command boundaries: promotion checks occur after application and `--force` overrides their structural errors (`adr_promote.py:423–437`). This task should not silently promise atomic refusal or remove that override.",
          "note": "",
          "complete": true
        },
        {
          "id": "M5",
          "D": 1,
          "R": 1,
          "A": 0,
          "quote": "- Add failing `unittest` cases in `tests/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.\n- 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/...`.\n- Exercise real brief extraction and plan creation extraction. Extend `tests/test_plan_audit_cmd.py` to assert exit 1 and a FAIL receipt containing the correct gap for prefixed mirrors, including brief-only and plan-only creates declarations.\n- 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.",
          "note": "The proposal pairs prefixed/unprefixed mirror cases and preserves legitimate creation controls, but does not clearly specify a ./-prefixed canonical CREATE positive through brief checking. Generic canonical creation controls could still use only unprefixed paths. A is withheld for this ambiguity; no particular helper or command test is required.",
          "complete": false
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 4
    },
    {
      "id": "T07",
      "criteria": [
        {
          "id": "S1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "The fix is to resolve the scanner’s directory as `project_root / config.paths.source_root / \"gzkit\"`. Use only that directory; do not retain a second scan or fallback to `src/gzkit`.\n\n[…]\n\nThe command already obtains configuration through `ensure_initialized()` and passes it to the collector. `commands/common.py` loads `.gzkit.json`; `config.py` declares `PathConfig.source_root = \"src\"` and loads supplied path settings. Required-directory checking already uses the configured root. No new parameter, configuration key, schema field, dependency, or parser option is necessary.\n\n[…]\n\n- Keep the existing known-prefix regex, string filtering, recursive sorted Python traversal, and unreadable/syntactically invalid file handling. A custom directory name does not justify widening the literal vocabulary.\n- Keep manifest mappings, including derived parents, unioned with actual configured path values. Config flattening intentionally derives no parents. Coverage then uses exact or slash-delimited ancestor/descendant matching; it is not universally exact-only matching.\n- Retain the two explicit exemptions and normalized, exact, module-local `_AUDIT_SUBJECT_LITERALS` declarations. Never grant prefix exemptions, cross-module credit, or credit to differently named/function-local declarations.\n- Preserve project-relative diagnostic filenames, result shape `{valid, issues}`, and failure exit status.",
          "note": "",
          "complete": true
        },
        {
          "id": "S2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "The fix is to resolve the scanner’s directory as `project_root / config.paths.source_root / \"gzkit\"`. Use only that directory; do not retain a second scan or fallback to `src/gzkit`.\n\n[…]\n\n- Keep the existing known-prefix regex, string filtering, recursive sorted Python traversal, and unreadable/syntactically invalid file handling. A custom directory name does not justify widening the literal vocabulary.\n- Keep manifest mappings, including derived parents, unioned with actual configured path values. Config flattening intentionally derives no parents. Coverage then uses exact or slash-delimited ancestor/descendant matching; it is not universally exact-only matching.\n- Retain the two explicit exemptions and normalized, exact, module-local `_AUDIT_SUBJECT_LITERALS` declarations. Never grant prefix exemptions, cross-module credit, or credit to differently named/function-local declarations.\n- Preserve project-relative diagnostic filenames, result shape `{valid, issues}`, and failure exit status.",
          "note": "",
          "complete": true
        },
        {
          "id": "S3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Keep the existing known-prefix regex, string filtering, recursive sorted Python traversal, and unreadable/syntactically invalid file handling. A custom directory name does not justify widening the literal vocabulary.\n- Keep manifest mappings, including derived parents, unioned with actual configured path values. Config flattening intentionally derives no parents. Coverage then uses exact or slash-delimited ancestor/descendant matching; it is not universally exact-only matching.\n- Retain the two explicit exemptions and normalized, exact, module-local `_AUDIT_SUBJECT_LITERALS` declarations. Never grant prefix exemptions, cross-module credit, or credit to differently named/function-local declarations.\n- Preserve project-relative diagnostic filenames, result shape `{valid, issues}`, and failure exit status.\n\n[…]\n\n1. Put an unmapped `artifacts/unknown/reports` literal under a nested custom root, with no default tree; assert the precise relocated filename and finding.\n2. Put distinguishable bad literals in both trees; assert only the configured tree contributes. Also test an absent configured package with a populated default tree to forbid fallback.\n3. Preserve default-root behavior and sibling-package exclusion. Check nested modules are scanned.\n4. Exercise mapped/configured literals, the undeclared config sibling boundary, explicit exemptions, and module-local declarations under the relocated tree, including cross-module, wrong-name, nested-declaration, and parent-prefix negative controls. Existing tests already encode these semantic boundaries.\n\n[…]\n\nAdd command-level coverage in `tests/commands/test_audit.py`: load a custom root from `.gzkit.json`, prepare other required surfaces, and assert JSON findings/exit 1 for bad source and valid/exit 0 after repair. Retain text-output and missing-required-root behavior. Subsequently run focused tests, appropriate repository checks, and documentation validation; record actual results then.",
          "note": "",
          "complete": true
        },
        {
          "id": "S4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Keep the existing known-prefix regex, string filtering, recursive sorted Python traversal, and unreadable/syntactically invalid file handling. A custom directory name does not justify widening the literal vocabulary.\n- Keep manifest mappings, including derived parents, unioned with actual configured path values. Config flattening intentionally derives no parents. Coverage then uses exact or slash-delimited ancestor/descendant matching; it is not universally exact-only matching.\n- Retain the two explicit exemptions and normalized, exact, module-local `_AUDIT_SUBJECT_LITERALS` declarations. Never grant prefix exemptions, cross-module credit, or credit to differently named/function-local declarations.\n- Preserve project-relative diagnostic filenames, result shape `{valid, issues}`, and failure exit status.",
          "note": "",
          "complete": true
        },
        {
          "id": "S5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "Update the collector docstring that currently promises scanning `src/gzkit/`. Extend `docs/user/manpages/check-config-paths.md`: its current check list omits source-literal auditing entirely. Explain `<paths.source_root>/gzkit`, the default, replacement semantics, and governed/exempt literals. This omission belongs with the correction.\n\n[…]\n\n1. Put an unmapped `artifacts/unknown/reports` literal under a nested custom root, with no default tree; assert the precise relocated filename and finding.\n2. Put distinguishable bad literals in both trees; assert only the configured tree contributes. Also test an absent configured package with a populated default tree to forbid fallback.\n3. Preserve default-root behavior and sibling-package exclusion. Check nested modules are scanned.\n4. Exercise mapped/configured literals, the undeclared config sibling boundary, explicit exemptions, and module-local declarations under the relocated tree, including cross-module, wrong-name, nested-declaration, and parent-prefix negative controls. Existing tests already encode these semantic boundaries.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T08",
      "criteria": [
        {
          "id": "M1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "Observed implementation explains the bypass. `extract_allowed_paths()` preserves the first backtick token, including `./`. `vendor_mirror_canonical()` only removes trailing slashes before prefix matching. Consequently `./.claude/rules/tests.md` misses the refusal. Filesystem existence accepts that spelling; if missing, `_normalize_for_creates()` strips its literal `./`, allowing a matching creation declaration to suppress the remaining error. Without existence or a declaration, the checker reports a missing path instead of mirror refusal and canonical advice.\n\n[…]\n\nNormalize one literal leading `./` inside `vendor_mirror_canonical()` before both prefix matching and suffix slicing. Keep the original Allowed Paths token for diagnostics. Normalizing only the comparison would mis-slice the canonical suffix. Do not use `lstrip('./')`: it removes meaningful dotfile characters, a failure already documented and tested for creation extraction. Preserve root/trailing-slash handling, glob suffixes, component boundaries, and mirror-first ordering. Avoid changing the general extractor: other consumers use its raw paths, and this correction does not require changing them.",
          "note": "",
          "complete": true
        },
        {
          "id": "M2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "Observed implementation explains the bypass. `extract_allowed_paths()` preserves the first backtick token, including `./`. `vendor_mirror_canonical()` only removes trailing slashes before prefix matching. Consequently `./.claude/rules/tests.md` misses the refusal. Filesystem existence accepts that spelling; if missing, `_normalize_for_creates()` strips its literal `./`, allowing a matching creation declaration to suppress the remaining error. Without existence or a declaration, the checker reports a missing path instead of mirror refusal and canonical advice.\n\n[…]\n\nNormalize one literal leading `./` inside `vendor_mirror_canonical()` before both prefix matching and suffix slicing. Keep the original Allowed Paths token for diagnostics. Normalizing only the comparison would mis-slice the canonical suffix. Do not use `lstrip('./')`: it removes meaningful dotfile characters, a failure already documented and tested for creation extraction. Preserve root/trailing-slash handling, glob suffixes, component boundaries, and mirror-first ordering. Avoid changing the general extractor: other consumers use its raw paths, and this correction does not require changing them.",
          "note": "",
          "complete": true
        },
        {
          "id": "M3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Brief and plan creation extractors share `_extract_creates_paths_from_text()`. They recognize inline `**CREATE**`, “Creates these files” headings, and the scaffold phrase emitted by `specify_cmd._build_discovery_prerequisites()`. Test all three with a prefixed mirror: declaration must never suppress refusal. Preserve legitimate missing canonical-path exemptions with mixed prefixed/unprefixed declarations.\n- `check_brief_path_validity_for_brief()` combines brief extraction and checking. `obpi_cmd` invokes it through `_validate_brief_path_existence()` in both single and batch authored validation; errors cause exit 1. Preserve lenient validation without `--authored`. Test actual command wiring, not only its wrapper.\n- `plan_audit_cmd._gather_brief_path_gaps()` unions brief and plan creation sets before calling the shared checker. `_emit_result()` writes FAIL, gaps, and gap count to the receipt and emits text/JSON before exit 1. Integration tests must assert mirror-specific advice and failed receipt/output for declarations originating in either document.\n- `adr_promote._check_scaffold_obpis()` incorporates the same wrapper’s errors. Test prefixed mirrors, including declared creation, in its structure-error collection. The outer command applies promotion before this check and permits `--force`; do not describe this as an unconditional pre-write refusal or change that behavior in this fix.",
          "note": "",
          "complete": true
        },
        {
          "id": "M4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Brief and plan creation extractors share `_extract_creates_paths_from_text()`. They recognize inline `**CREATE**`, “Creates these files” headings, and the scaffold phrase emitted by `specify_cmd._build_discovery_prerequisites()`. Test all three with a prefixed mirror: declaration must never suppress refusal. Preserve legitimate missing canonical-path exemptions with mixed prefixed/unprefixed declarations.\n- `check_brief_path_validity_for_brief()` combines brief extraction and checking. `obpi_cmd` invokes it through `_validate_brief_path_existence()` in both single and batch authored validation; errors cause exit 1. Preserve lenient validation without `--authored`. Test actual command wiring, not only its wrapper.\n- `plan_audit_cmd._gather_brief_path_gaps()` unions brief and plan creation sets before calling the shared checker. `_emit_result()` writes FAIL, gaps, and gap count to the receipt and emits text/JSON before exit 1. Integration tests must assert mirror-specific advice and failed receipt/output for declarations originating in either document.\n- `adr_promote._check_scaffold_obpis()` incorporates the same wrapper’s errors. Test prefixed mirrors, including declared creation, in its structure-error collection. The outer command applies promotion before this check and permits `--force`; do not describe this as an unconditional pre-write refusal or change that behavior in this fix.",
          "note": "",
          "complete": true
        },
        {
          "id": "M5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- Brief and plan creation extractors share `_extract_creates_paths_from_text()`. They recognize inline `**CREATE**`, “Creates these files” headings, and the scaffold phrase emitted by `specify_cmd._build_discovery_prerequisites()`. Test all three with a prefixed mirror: declaration must never suppress refusal. Preserve legitimate missing canonical-path exemptions with mixed prefixed/unprefixed declarations.\n- `check_brief_path_validity_for_brief()` combines brief extraction and checking. `obpi_cmd` invokes it through `_validate_brief_path_existence()` in both single and batch authored validation; errors cause exit 1. Preserve lenient validation without `--authored`. Test actual command wiring, not only its wrapper.\n- `plan_audit_cmd._gather_brief_path_gaps()` unions brief and plan creation sets before calling the shared checker. `_emit_result()` writes FAIL, gaps, and gap count to the receipt and emits text/JSON before exit 1. Integration tests must assert mirror-specific advice and failed receipt/output for declarations originating in either document.\n- `adr_promote._check_scaffold_obpis()` incorporates the same wrapper’s errors. Test prefixed mirrors, including declared creation, in its structure-error collection. The outer command applies promotion before this check and permits `--force`; do not describe this as an unconditional pre-write refusal or change that behavior in this fix.\n\n[…]\n\nAdd explicit expected canonical results for all five roots, each with and without `./`, using files, roots, trailing slashes and globs. Cover existing and absent mirrors, canonical `.gzkit` paths, `.claude/plans`, and similarly named non-mirror directories. Existing unit and integration tests cover unprefixed refusal and creation precedence but do not establish prefixed parity. These tests would catch broken normalization, incorrect suffix slicing, reordered exemptions, or disconnected consumers.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T09",
      "criteria": [
        {
          "id": "S1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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.\n\n[…]\n\nCurrent behavior, established by reading:\n\n[…]\n\n1. 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.\n2. 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.\n3. 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.\n4. Update `tests/test_config_paths.py` and command-level coverage in `tests/commands/test_audit.py`. Its real-repository acceptance test currently supplies `GzkitConfig()` 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.\n5. 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 identifying `src` as the default example.\n6. 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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.\n\n[…]\n\n- `src/gzkit/config.py` defines `PathConfig.source_root`, defaulting to `src`, and loads configured values from `.gzkit.json`.\n- `commands/common.py::ensure_initialized` loads that file. `check_config_paths_cmd` already passes the resulting config into the scanner and checks the configured source directory for existence/type.\n- Nevertheless, `commands/config_paths.py` scans only `project_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.\n- 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- First add a failing regression with `source_root=\"application\"`, a nested `application/gzkit/.../bad.py`, and an unmapped recognized literal such as `artifacts/unknown/reports`. Assert the exact issue and relocated repository-relative filename.\n- 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.\n- 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.\n- 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.\n- 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.\n- Subsequently run relevant unittest modules, repository quality checks, and strict documentation validation in the complete checkout. No pass result is claimed here.",
          "note": "",
          "complete": true
        },
        {
          "id": "S4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "1. 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.\n2. 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.\n3. 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.\n4. Update `tests/test_config_paths.py` and command-level coverage in `tests/commands/test_audit.py`. Its real-repository acceptance test currently supplies `GzkitConfig()` 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.\n5. 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 identifying `src` as the default example.\n6. 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "1. 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.\n2. 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.\n3. 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.\n4. Update `tests/test_config_paths.py` and command-level coverage in `tests/commands/test_audit.py`. Its real-repository acceptance test currently supplies `GzkitConfig()` 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.\n5. 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 identifying `src` as the default example.\n6. 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.\n\n[…]\n\n- First add a failing regression with `source_root=\"application\"`, a nested `application/gzkit/.../bad.py`, and an unmapped recognized literal such as `artifacts/unknown/reports`. Assert the exact issue and relocated repository-relative filename.\n- 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.\n- 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.\n- 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.\n- 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.\n- Subsequently run relevant unittest modules, repository quality checks, and strict documentation validation in the complete checkout. No pass result is claimed here.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T10",
      "criteria": [
        {
          "id": "M1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "`extract_allowed_paths` preserves `./`. The classifier adds a trailing slash but compares against unprefixed mirror roots. Consequently `./.claude/rules/tests.md` escapes classification: an existing file passes; a missing file produces an existence error without canonical advice; a missing file declared created passes because `_normalize_for_creates` already removes one literal `./`. This contradicts the module’s unconditional mirror-refusal invariant and `gz-obpi-specify`’s statement that “a vendor-mirror path fails regardless.”\n\n[…]\n\nNormalize one literal leading `./` inside the classifier before both prefix comparison AND tail slicing. Using the original string for slicing after normalizing only the comparison would corrupt canonical advice. Preserve the original entry in the diagnostic and preserve dots in `.claude`/`.gzkit`; do not use `lstrip(\"./\")`. Keep separator boundaries, directory-root behavior, trailing-slash handling, glob tails, and the five existing mappings. Keep mirror refusal before existence and creation exemptions. No extractor-wide rewrite or filesystem resolution is needed.",
          "note": "",
          "complete": true
        },
        {
          "id": "M2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "`extract_allowed_paths` preserves `./`. The classifier adds a trailing slash but compares against unprefixed mirror roots. Consequently `./.claude/rules/tests.md` escapes classification: an existing file passes; a missing file produces an existence error without canonical advice; a missing file declared created passes because `_normalize_for_creates` already removes one literal `./`. This contradicts the module’s unconditional mirror-refusal invariant and `gz-obpi-specify`’s statement that “a vendor-mirror path fails regardless.”\n\n[…]\n\nNormalize one literal leading `./` inside the classifier before both prefix comparison AND tail slicing. Using the original string for slicing after normalizing only the comparison would corrupt canonical advice. Preserve the original entry in the diagnostic and preserve dots in `.claude`/`.gzkit`; do not use `lstrip(\"./\")`. Keep separator boundaries, directory-root behavior, trailing-slash handling, glob tails, and the five existing mappings. Keep mirror refusal before existence and creation exemptions. No extractor-wide rewrite or filesystem resolution is needed.",
          "note": "",
          "complete": true
        },
        {
          "id": "M3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- `.gzkit/rules/skill-surface-sync.md` makes `.gzkit/skills` and `.gzkit/rules` canonical. `sync_skill_mirror` copies source bytes into mirror targets, confirming why edits there are overwritten. The classifier produces canonical advice from its explicit mapping. `.gzkit.json` supplies today’s vendor configuration; the classifier deliberately also retains historical GitHub audit subjects. Do not replace that map with enabled-vendor filtering as part of this spelling repair.\n- Brief authors supply Allowed Paths and creation markers. `specify_cmd._build_discovery_prerequisites` also produces “intentionally created in this OBPI”; the shared creation extractor recognizes that wording, `**CREATE**`, and creation headings. Preserve all three producers’ semantics. Test mirror precedence through actual extraction, not just a hand-built creation set.\n- `obpi_cmd` uses the shared wrapper in both single and batch validation, only with `--authored`. Preserve lenient mode. `plan_audit_cmd._gather_brief_path_gaps` unions brief and plan creation declarations before calling the checker. Its emitter writes FAIL, gaps, and exit 1; `pipeline_markers.load_plan_audit_receipt` consumes that verdict. Verify this complete result path.\n- `adr_promote._check_scaffold_obpis` includes shared path errors in structural errors. Promotion runs this after applying promotion, and `--force` overrides the block. “Pre-flight” wording in the shared module therefore overstates promotion’s timing. Preserve current timing/override semantics for equivalent spellings; changing transactional behavior is independent work.",
          "note": "",
          "complete": true
        },
        {
          "id": "M4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- `.gzkit/rules/skill-surface-sync.md` makes `.gzkit/skills` and `.gzkit/rules` canonical. `sync_skill_mirror` copies source bytes into mirror targets, confirming why edits there are overwritten. The classifier produces canonical advice from its explicit mapping. `.gzkit.json` supplies today’s vendor configuration; the classifier deliberately also retains historical GitHub audit subjects. Do not replace that map with enabled-vendor filtering as part of this spelling repair.\n- Brief authors supply Allowed Paths and creation markers. `specify_cmd._build_discovery_prerequisites` also produces “intentionally created in this OBPI”; the shared creation extractor recognizes that wording, `**CREATE**`, and creation headings. Preserve all three producers’ semantics. Test mirror precedence through actual extraction, not just a hand-built creation set.\n- `obpi_cmd` uses the shared wrapper in both single and batch validation, only with `--authored`. Preserve lenient mode. `plan_audit_cmd._gather_brief_path_gaps` unions brief and plan creation declarations before calling the checker. Its emitter writes FAIL, gaps, and exit 1; `pipeline_markers.load_plan_audit_receipt` consumes that verdict. Verify this complete result path.\n- `adr_promote._check_scaffold_obpis` includes shared path errors in structural errors. Promotion runs this after applying promotion, and `--force` overrides the block. “Pre-flight” wording in the shared module therefore overstates promotion’s timing. Preserve current timing/override semantics for equivalent spellings; changing transactional behavior is independent work.\n\n[…]\n\nVerification should begin with failing unittest regressions covering all five mappings, prefixed/unprefixed pairs, exact canonical tails, roots with/without trailing slash, and globs. Assert refusal for existing, missing, and creation-declared mirrors. Cover brief inline markers, creation headings, scaffold wording, and plan-only declarations. Positive controls must preserve canonical/source creation exemptions, missing-path errors, `.claude/plans`, and near-prefix nonmirrors such as `.claude/rules-extra`.",
          "note": "",
          "complete": true
        },
        {
          "id": "M5",
          "D": 1,
          "R": 1,
          "A": 0,
          "quote": "Verification should begin with failing unittest regressions covering all five mappings, prefixed/unprefixed pairs, exact canonical tails, roots with/without trailing slash, and globs. Assert refusal for existing, missing, and creation-declared mirrors. Cover brief inline markers, creation headings, scaffold wording, and plan-only declarations. Positive controls must preserve canonical/source creation exemptions, missing-path errors, `.claude/plans`, and near-prefix nonmirrors such as `.claude/rules-extra`.\n\n[…]\n\nExtend shared tests, wiring tests, and plan command tests. Existing wiring tests invoke helpers, so they do not prove command dispatch: add authored single/batch command coverage and promotion error propagation using otherwise valid fixtures. Check plan JSON/receipt FAIL, canonical advice, exit status, and receipt-loader interpretation. These assertions must fail if classification, tail slicing, precedence, or caller wiring breaks.",
          "note": "The proposal pairs prefixed/unprefixed mirror cases and preserves legitimate creation controls, but does not clearly specify a ./-prefixed canonical CREATE positive through brief checking. Generic canonical creation controls could still use only unprefixed paths. A is withheld for this ambiguity; no particular helper or command test is required.",
          "complete": false
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 4
    },
    {
      "id": "T11",
      "criteria": [
        {
          "id": "S1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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`.\n\n[…]\n\nPolicy 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.\n\n[…]\n\n- **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.\n- **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.\n- **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.\n- **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.\n- **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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "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`.\n\n[…]\n\nProposed 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- **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.\n- **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.\n- **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.\n- **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.\n- **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.\n\n[…]\n\nProposed 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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- **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.\n- **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.\n- **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.\n- **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.\n- **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.",
          "note": "",
          "complete": true
        },
        {
          "id": "S5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- **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.\n- **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.\n- **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.\n- **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.\n- **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.\n\n[…]\n\nProposed 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.",
          "note": "",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    },
    {
      "id": "T12",
      "criteria": [
        {
          "id": "M1",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "In `src/gzkit/governance/brief_path_validity.py:94`, mirror matching only removes trailing slashes. Consequently `./.claude/rules/tests.md` misses the `.claude/rules/` prefix. Filesystem resolution accepts that spelling when the file exists; when absent, `_normalize_for_creates` removes one literal `./`, so a matching creation declaration suppresses the existence gap. Both routes evade mirror refusal. Without existence or a declaration, the diagnostic incorrectly reports a missing path rather than the canonical edit surface.\n\n[…]\n\nNormalize one literal leading `./` inside `vendor_mirror_canonical`, before both prefix comparison and suffix extraction. Slicing the original string after matching a normalized string would corrupt canonical advice. Preserve the original Allowed Paths token in the diagnostic. Keep the mapping and its component boundary behavior unchanged: Claude rules and GitHub instructions map to `.gzkit/rules`; Claude/GitHub/Agents skills map to `.gzkit/skills`.\n\n[…]\n\nUse `removeprefix(\"./\")`, not `lstrip(\"./\")`: the latter destroys dot-directory names, explicitly documented by `_normalize_for_creates` and its regression tests. No filesystem resolution or dependency is needed. Keep the mirror check ahead of existence and creation exemptions (`:211–221`). No creation declaration may authorize a generated mirror.",
          "note": "",
          "complete": true
        },
        {
          "id": "M2",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "In `src/gzkit/governance/brief_path_validity.py:94`, mirror matching only removes trailing slashes. Consequently `./.claude/rules/tests.md` misses the `.claude/rules/` prefix. Filesystem resolution accepts that spelling when the file exists; when absent, `_normalize_for_creates` removes one literal `./`, so a matching creation declaration suppresses the existence gap. Both routes evade mirror refusal. Without existence or a declaration, the diagnostic incorrectly reports a missing path rather than the canonical edit surface.\n\n[…]\n\nUse `removeprefix(\"./\")`, not `lstrip(\"./\")`: the latter destroys dot-directory names, explicitly documented by `_normalize_for_creates` and its regression tests. No filesystem resolution or dependency is needed. Keep the mirror check ahead of existence and creation exemptions (`:211–221`). No creation declaration may authorize a generated mirror.",
          "note": "",
          "complete": true
        },
        {
          "id": "M3",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- `commands/plan_audit_cmd.py:398` gathers brief and plan creation declarations and invokes the shared checker. Preserve this union. Mirror gaps must yield FAIL, exit 1, and canonical advice in both output and the existing receipt; do not change its schema.\n- `commands/obpi_cmd.py:958` delegates to the brief wrapper. Verify both single-file and ADR-batch `--authored` validation. Preserve lenient non-authored behavior; this repair does not newly enable checks there.\n- `commands/adr_promote.py:333` checks promoted briefs using the same wrapper. Verify propagation into its structural errors. Its current command checks after applying promotion, and `--force` bypasses blocking: do not describe this as an atomic pre-write refusal or silently change those semantics.\n- Keep the compatibility alias imported by `plan_audit_cmd` working. Consumers need tests, not duplicate normalization implementations.\n- Update the shared helper documentation and user guidance in the plan-audit and obpi-validate manpages with a concrete `./` mirror-to-canonical example and the creation-exemption boundary. Explain promotion’s applicable check accurately. Clarify the same invariant in canonical `gz-obpi-specify` guidance. If skills change, bump their skill version and use the documented synchronization process to deliver packaged/vendor copies; do not edit generated mirrors manually.",
          "note": "",
          "complete": true
        },
        {
          "id": "M4",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "- `commands/plan_audit_cmd.py:398` gathers brief and plan creation declarations and invokes the shared checker. Preserve this union. Mirror gaps must yield FAIL, exit 1, and canonical advice in both output and the existing receipt; do not change its schema.\n- `commands/obpi_cmd.py:958` delegates to the brief wrapper. Verify both single-file and ADR-batch `--authored` validation. Preserve lenient non-authored behavior; this repair does not newly enable checks there.\n- `commands/adr_promote.py:333` checks promoted briefs using the same wrapper. Verify propagation into its structural errors. Its current command checks after applying promotion, and `--force` bypasses blocking: do not describe this as an atomic pre-write refusal or silently change those semantics.\n- Keep the compatibility alias imported by `plan_audit_cmd` working. Consumers need tests, not duplicate normalization implementations.\n- Update the shared helper documentation and user guidance in the plan-audit and obpi-validate manpages with a concrete `./` mirror-to-canonical example and the creation-exemption boundary. Explain promotion’s applicable check accurately. Clarify the same invariant in canonical `gz-obpi-specify` guidance. If skills change, bump their skill version and use the documented synchronization process to deliver packaged/vendor copies; do not edit generated mirrors manually.\n\n[…]\n\nExercise the shared checker against existing mirrors, missing mirrors, and missing mirrors declared created. Assert exactly the mirror diagnostic with intact original token and correct canonical suffix. Test extraction through a real brief and plan, including inline `**CREATE**` and `Creates these files`, with mixed prefixed/unprefixed declarations. Preserve canonical net-new creation exemptions, missing ordinary-path failures, glob-root behavior, and empty/scaffold handling.",
          "note": "",
          "complete": true
        },
        {
          "id": "M5",
          "D": 1,
          "R": 1,
          "A": 1,
          "quote": "First add failing unittest cases with explicit expected canonical paths for all five mapping entries. Cover prefixed/unprefixed files, directory roots with/without trailing slash, nested suffixes, and globs. Include negative controls for `./.gzkit/...`, ordinary source paths, `.claude/plans/...`, and similarly named non-mirror directories.\n\n[…]\n\nExercise the shared checker against existing mirrors, missing mirrors, and missing mirrors declared created. Assert exactly the mirror diagnostic with intact original token and correct canonical suffix. Test extraction through a real brief and plan, including inline `**CREATE**` and `Creates these files`, with mixed prefixed/unprefixed declarations. Preserve canonical net-new creation exemptions, missing ordinary-path failures, glob-root behavior, and empty/scaffold handling.\n\n[…]\n\nExtend command regressions for plan receipts/output, authored single/batch validation, and promotion structural-error propagation using otherwise valid fixtures, so unrelated failures cannot satisfy the assertion. Then run focused suites and appropriate repository quality/documentation checks in an authorized implementation session. None have been run here.",
          "note": "Credited semantically: explicitly prefixed canonical negative controls, real-brief extraction with mixed prefixed/unprefixed declarations, and preserved canonical net-new creation exemptions collectively specify the positive witness.",
          "complete": true
        }
      ],
      "flags": {
        "unsupported_expansion": [],
        "unsafe_policy_changes": [],
        "false_execution": [],
        "protocol_deviations": []
      },
      "total": 5
    }
  ]
}
