# Conflict Matrix — Rule-Pair Pass A

> Chore: `control-surface-rule-conflicts` (Lite lane, audit-only)
> Schema: `ADR-pool.control-surface-rule-pair-conflict-audit` § Audit-row schema (GHI #448)
> Each row carries a concrete worked example, a resolvable evidence reference, and a severity classification per CHORE.md § Workflow step 3.

| # | Rule A + § | Rule B + § | Worked Example | Evidence | Mechanical Winner | Suggested Resolution | Severity |
|---|------------|------------|----------------|----------|-------------------|----------------------|----------|
| 1 | `tests.md` § Red-Green-Refactor / Invariant 6f — *"Tests assert semantics, not strings. Assertions derive from the REQ or skill contract, not from a run of the code."* | `tool-skill-runbook-alignment.md` § Invariant 3 — *"Destination verb's default output form must honor the routing skill's Output Contract"* | A skill declares Output Contract = `table`. To verify Invariant 3, a test must observe the verb's default output and assert structural table-form (Unicode box-drawing chars and column count). That assertion is *of-the-string-form*, which Invariant 6f forbids when derived from REQ semantics rather than the contract. | GHI #448 | `tests.md` — explicit Output-form fixture carve-out: *"Output-form assertions are permitted in dedicated fixture tests per `.gzkit/rules/tool-skill-runbook-alignment.md` § Invariant 3. Keep them in separate test classes from REQ-derived unit tests."* | Already-mitigated. Verify the carve-out is mirrored from `tests.md` into `tool-skill-runbook-alignment.md` § "When to apply" so a reader landing on Invariant 3 first does not need to discover the exception via `tests.md`. | theoretical |
| 2 | `AGENTS.md` § PRIME DIRECTIVE 4 — *"SCOPE EXPANSION IS NOT SCOPE CREEP. If fixing requires updating 3 docs, do it."* | `AGENTS.md` § Defect-fix routing — *"OBPI ceremony is required when ANY hold: Crosses brief boundaries / Adds/changes CLI surface, schema, or runtime contract / …"* | An agent implementing OBPI-X.Y.Z-04 under brief A discovers a 5-line bug in module M outside brief A's `Allowed Paths`. PD 4 reads as license to expand (*"if fixing requires touching 3 surfaces, do it"*). Defect-fix routing reads as fail-closed: cross-boundary work triggers ceremony. | GHI #195 | Defect-fix routing — `Allowed Paths` is the structural boundary, mechanically enforced by brief gates; PD 4 is a posture rule with no enforcement surface. | Add a one-line qualifier to PD 4: *"Scope expansion stays within the active brief's `Allowed Paths`. Cross-boundary fixes route per § Defect-fix routing."* Adds the missing pointer at the place where the rule lives. | blocking |
| 3 | `governance-core.md` § Required workflow order — 6-step OBPI sequence (`gz state` → `gz status` → implement → `gz implement` → `gz gates` → `gz adr audit-check`) | `AGENTS.md` § Defect-fix routing § Direct fix — *"Diff size ≤10 source lines OR ≤2 source files / Single named module / `git log --grep='^fix('` ≥3 commits / Unit test validates without new BDD scenario"* | An 8-line typo fix in `src/gzkit/commands/foo.py` surfaces mid-session. governance-core reads as mandatory full sequence. Defect-fix routing prescribes a single direct commit `fix(foo): … (GHI #N)`. | GHI #195 | governance-core's own scope clause — *"Scope: planned OBPI implementation under an active ADR. For in-flight defect fixes meeting the thresholds in AGENTS.md § Defect-fix routing, take the direct path instead — this workflow does not apply."* | Already-mitigated by the scope clause added in `governance-core.md` 0.2.0. Verify the same scope clause is mirrored at the head of `.claude/rules/governance-core.md` (the runtime-loaded copy). | theoretical |
| 4 | `AGENTS.md` § STDLIB-FIRST DOCTRINE, claim 1 — *"The default is stdlib. When a capability exists in stdlib, that path is chosen absent named rationale to depart."* | `.gzkit/rules/models.md` — *"Use Pydantic BaseModel for all data models; no stdlib dataclasses."* | Authoring a new immutable governance domain model. Stdlib offers `@dataclass(frozen=True)` (zero dependency cost). STDLIB-First claim 1 prefers stdlib; `models.md` forbids dataclasses outright. | 42c91a89 | `models.md` — STDLIB-First claim 2 (*"Departures are foundation-attested"*) explicitly accepts `models.md` as the named departure; AGENTS.md § Existing canonical applications cites Pydantic as the canonical worked example of a named departure. | Already-mitigated by AGENTS.md's own cross-reference. Verify `models.md` rule body cites the AGENTS.md § STDLIB-First named-departure clause explicitly, so a reader landing on `models.md` first sees the doctrinal anchor. | theoretical |
| 5 | `chores.md` § Core Principles — *"Lite by default: Run `uv run -m unittest -q` (unit tier only); no `behave`, no network, no external services."* | `tests.md` § Two runners, one test surface — *"`gz test` runs `unittest` over `tests/` then `behave` over `features/`. Both gates must pass for `gz check`."* | A Lite-lane chore runs `unittest`, passes acceptance criteria, and a maintainer treats "chore validated" as "project-validated." `gz check` (full pipeline) would fail until behave runs separately. | GHI #276 | `chores.md` § Lane policy — chore-lane validation is explicitly narrower than `gz check`; the chore's acceptance.json names the exact commands, not the full `gz check` pipeline. | Add one sentence to `tests.md` § Two runners: *"Chore-lane validation under `chores.md` is a strict subset; it is not equivalent to `gz check`, which gates on both runners."* Removes the failure mode where the lane scope is conflated. | theoretical |
| 6 | `cli.md` § Output Contracts — *"Default: Human-readable (tables, colors, progress); `--json`: Machine-readable to stdout; `--plain`: One record per line"* | `tool-skill-runbook-alignment.md` § Invariant 3 — *"The CLI verb in the skill's `gz_command` must produce that form as its default human-readable output."* | A skill declares Output Contract = `JSON`. Per Invariant 3 the verb's default must be JSON. Per `cli.md` the verb's default must be human-readable; `--json` is the opt-in machine mode. | GHI #327 | Invariant 3 closes the gap textually (*"default human-readable output"*) — JSON cannot be declared as a skill's primary form without violating cli.md. The skill schema today does not mechanically restrict the enum. | Restrict skill `Output Contract` enum to `{table, tree, plain, prose}` in the skill JSON Schema. Skills that need JSON output must invoke the verb with `--json` explicitly and declare the human-readable form as their primary contract. | episodic |
| 7 | `gate5-runbook-code-covenant.md` § Required updates when behavior changes — *"Update command docs and examples. Update runbook flows and verification commands."* | `AGENTS.md` § Gate Covenant § Lane Rules — *"lite: Gates 1, 2 required"* (Gate 3 = "Docs updated" not in lite-lane required set) | A Lite-lane fix changes a `gz` command's output format. gate5-runbook-code-covenant demands docs+runbook update in the same patch set; lite-lane gate matrix marks Gate 3 optional. An agent reading only the lane matrix ships the fix without doc update. | GHI #428 | `AGENTS.md` § DO IT RIGHT, Invariant 1a — *"Coupled-surface coherence: When a change touches a surface another surface reads/validates, verify the consumer's check in the same commit."* — sides with gate5-runbook for any output-shape change. | Amend `AGENTS.md` § Lane Rules: *"lite: Gates 1, 2 required; Gate 3 required whenever the change touches a surface documented under `docs/user/manpages/**` or `docs/**/runbook*.md` (per `gate5-runbook-code-covenant.md`)."* Aligns the lane matrix with the always-on coupled-surface rule. | episodic |
| 8 | `complexity-thresholds.md` § Operator-amendable mapping protocol — *"Amendments to `(metric, band, trigger)` mappings flow through the doctrine-amendment-protocol stub (ADR-0.0.27 OBPI-02). Silent edits are forbidden by the validator."* | `skill-surface-sync.md` § Non-negotiable rules, claim 2 — *"Bump the version on every edit. Increment the version marker before saving."* | An agent corrects a typo in `complexity-thresholds.md` prose (clarifies what `block` means). `skill-surface-sync` requires a `<!-- rule-version: X.Y.Z -->` bump and ordinary sync. `complexity-thresholds` reads as: "amendments require ADR-0.0.28 ceremony" — implying any edit needs a ceremony. | GHI #426 | `complexity-thresholds.md` itself — the amendment protocol explicitly scopes *"`(metric, band, trigger)` mappings"* (the JSON data file), not the prose body. The narrative file is governed by the ordinary rule-version protocol. | Add an explicit scope sentence to `complexity-thresholds.md` § Operator-amendable mapping protocol: *"This protocol governs the JSON data file. Editorial changes to this narrative file follow the ordinary `skill-surface-sync` version-bump protocol."* | episodic |
| 9 | `model-selection.md` § Operative claims 2 — *"Default to the lowest tier that closes the decision space."* | `CLAUDE.md` § Opus 4.7 tuning — *"Default effort: `xhigh` for gzkit agentic work; `high`/`medium` for lookups; reserve `max` for genuinely hard problems."* | An agent spawns a subagent for a routine code-search task. `model-selection.md` routes lookups to Haiku (lowest tier). CLAUDE.md reads as "default xhigh" if the subscoping clause is missed. | GHI #409 | `model-selection.md` — CLAUDE.md's own conditional clause (*"`high`/`medium` for lookups"*) reconciles with the routing matrix on careful reading; the matrix is the structural authority. | Add a cross-reference in CLAUDE.md § Opus 4.7 tuning: *"See `.gzkit/rules/model-selection.md` § Routing matrix for the per-task tier map; this section governs only the main-session default effort."* Closes the misread surface. | theoretical |
| 10 | `AGENTS.md` § Behavior Rules § Never #1 — *"Bypass Gate 5 (human attestation)"* | `AGENTS.md` § Gate Covenant § Lane Rules — *"lite: Gates 1, 2 required"* (Gate 5 not in the lite-lane required set when kind=feature, sensitivity=absent) | A feature-kind, lite-lane, sensitivity=absent OBPI completes evidence collection. Behavior Rule Never #1 reads absolute. The Lane × Kind × Sensitivity matrix permits self-close (no Gate 5 required) for `feature × lite × absent`. | GHI #357 | The Lane × Kind × Sensitivity matrix (canonical predicate `_requires_human_obpi_attestation`) — the matrix names the exact cells where Gate 5 is and isn't required. Behavior Rule Never #1 must be read as "never bypass when required by the matrix." | Reword Behavior Rule Never #1: *"Bypass Gate 5 (human attestation) when the Lane × Kind × Sensitivity matrix requires it (see § OBPI Acceptance Protocol)."* Removes the absolute reading that mismatches the matrix. | episodic |
| 11 | `pythonic.md` § Size Limits & Refactoring — *"Functions <=50 lines / Modules <=600 lines / Classes <=300 lines"* | `complexity-thresholds.md` § Invariant — *"gzkit publishes one canonical threshold table whose every entry is a `(metric, percentile-band, absolute-number, trigger-semantic)` tuple cited from the current distilled-characteristics document. A new threshold authority appearing anywhere else is doctrine drift by another name."* | A function ships at 65 LLOC. `pythonic.md` cites a hard cap of 50. `complexity-thresholds.md` § `radon_raw_lloc` / `lizard_nloc` declares per-metric `block` bands cited from the corpus distillation — the canonical authority. | GHI #426 | `complexity-thresholds.md` — explicit invariant: "a new threshold authority appearing anywhere else is doctrine drift by another name." The 50/600/300 absolutes in `pythonic.md` are by definition the older drifted authority. | Demote `pythonic.md` § Size Limits to authoring-time guidance: *"These limits are author-time guides; the canonical block/warn/advise bands live in `complexity-thresholds.md` and `complexity-thresholds.json`."* Or remove the absolutes and cite the threshold-table sections directly. | episodic |

## Notes on resolution categorization

- **Already-mitigated** rows (1, 3, 4, 5, 9) carry a worked example that fires on a *misread*, not on the canonical reading. The mitigation usually lives in one rule's scope clause that the conflicting rule fails to reference back. Each one is a candidate for a one-line cross-reference, not a doctrinal change.
- **Live conflicts** (2, 7, 8, 10, 11) require a rule-body amendment to one side. Each maps to a single mechanical-promotion or rule-edit GHI sized for direct-fix routing per AGENTS.md § Defect-fix routing.
- **Doctrine-clarification** (6) requires a schema change (skill `Output Contract` enum restriction) rather than prose edits — sized for a small OBPI under an existing skill-schema-governing ADR.

The cross-reference back to GHIs surfaces only acceptance gating in `--offline` mode (shape-only). Each row's GHI was selected as the locus where the underlying surface evolution is recorded; full linkage will land in `summary.md` § Prioritized follow-up.
