---
name: 'HARNESS-RULES: Audit'
description: Run the harness-rules catalog audit (structural health/drift + semantic tensions).
category: Harness Rules
tags: [harness-rules, audit, drift, semantic]
---

Audit the harness-rules catalog. Two parts run back-to-back in the same session:

1. **Structural** — handled by `scripts/harness-rules/audit.ts`. Health counts, mechanical drift (dead globs, dead/too-broad `detect` patterns, uninstalled bc-bound BCs, scope↔bounded_contexts incoherence, orphan/zombie citations, stale assumption markers).
2. **Semantic** — handled by Claude in the continuation of this session. Pairwise tension analysis over the HR rule bodies to detect contradictions a glob/grep cannot: contradictory anchor patterns on overlapping paths, contradictory decision matrices, and a `detect.pattern` that is structurally too broad or too narrow to judge mechanically.

This follows the same script + LLM continuation pattern as `/business-rules:audit`: the script automates what is deterministic; Claude does what requires reasoning. The script is read-only and is NOT exposed as a `pnpm hr:*` alias (matching the BR audit convention) — the useful output is the integrated one with section E, which only this slash command produces. No SDK, no API key, no scheduled job.

---

**Input**: Optional flag forwarded to the structural script:

- `--json` → machine-consumable JSON for the structural report only.
- `--structural-only` (or saying so in the prompt) → skip the semantic step.

**Steps**

1. **Run the structural audit**

   ```bash
   npx tsx scripts/harness-rules/audit.ts
   ```

   Or for JSON:

   ```bash
   npx tsx scripts/harness-rules/audit.ts --json > /tmp/hr-audit.json
   ```

   The script reports two sections:

   - **A) Health** — rule counts (active/derogated/proposed/total), files, topics covered, estimated catalog size in tokens, size bucket (OK/INFO/WARN/SOFT_ERROR/REARCHITECT).
   - **B) Drift (mechanical)** —
     - **(1)** `paths` and `### Anchor patterns` globs matching ZERO files on disk (dead enforcement / too-narrow pattern). Prose placeholders (`<bc>`, `@(api|app|…)`, `…/...`) are skipped — they are illustrations, not globs.
     - **(2)** an active rule's `detect.pattern` matching NO governed file (dead teeth); a pattern with a very high match count is surfaced as "possibly too broad" with the judgment deferred to section E.
     - **(3)** a `scope: bc-bound` rule whose `cliter/<bc>/` directory is absent (uninstalled BC).
     - **(4)** `scope` ↔ `bounded_contexts` incoherence (project → empty, bc-bound → exactly 1, multi-bc → ≥2).
     - **(5)** orphan `@rule HR-…` citations in code (id not in the index) + zombie rules (active, >30 days, uncited). Empty today — no HR citations yet — but future-proof.
     - **(6)** stale `[VERIFICAR]` / `[ASUNCIÓN]` markers in rule bodies whose file `last_updated` is older than 30 days.

   Exit codes: 0 (clean), 2 (warnings present). The structural report is the input for step 2 (Claude needs the rule counts to decide whether the semantic sweep is warranted).

2. **Semantic tension sweep (Claude continues here)**

   Skip this step in any of these cases:
   - Total active + proposed rules == 0 (catalog empty).
   - Total active rules == 0 (only proposed scaffolds present, nothing to compare semantically).
   - The user explicitly asked for a structural-only audit (`--structural-only`, or said so in the prompt).

   Otherwise, perform the pairwise semantic analysis over the HR rule bodies:

   a. **Load the index**

      Read `cliter/harness-rules-index.json`. Build the working set as the union of `state: active` and `state: proposed` rules (skip derogated).

   b. **Pair rules to compare**

      Generate pairs (A, B) where A and B have a chance of tension. For HR the strongest signal is **overlapping `paths`**: two rules governing intersecting globs (e.g. both touching `backend/src/@app/**`). Also pair rules that share a `keywords` entry. Use `byPath`/`byKeyword` from the index to find these. Do NOT compare every rule against every other — most pairs are orthogonal by construction.

      With only a handful of rules the full set of overlapping pairs is small; analyze all of them. If the working set ever grows large (bucket `WARN`+), ask the user whether to scope by path/keyword cluster before the full sweep.

   c. **Read each pair's body**

      For every pair, read the rule body from the `filePath` in the index. The body is what carries the actual semantic content (Enunciado, the decision matrix in `### Casos exhaustivos`, `### Anchor patterns`). Frontmatter and the index alone are not enough.

   d. **Classify the pair** — HR-specific tensions to look for:

      For each pair, produce:
      - **Verdict**: `contradiction` | `extension` | `orthogonal` | `needs-review`.
      - **Confidence**: `0.0`–`1.0`.
      - **Explanation**: one or two sentences in Spanish describing the tension (or its absence).

      HR tension categories:
      - **Contradictory anchor patterns on overlapping paths** — two rules whose `### Anchor patterns` govern the same files but prescribe opposing actions (one says "must live here", the other "must not"). This is the canonical HR contradiction.
      - **Contradictory decision matrices** — the `### Casos exhaustivos` of A marks a situation `SÍ` that B marks `**NO**` for the same scenario, without one deferring to the other.
      - **`detect.pattern` too broad/narrow** — a pattern (flagged by section B(2) as high-count, or that you judge structurally) that would over-block legitimate code or that no longer matches the case the rule describes. Judge against the rule body, since the structural script cannot.

      Definitions:
      - `contradiction` — the rules cannot both hold simultaneously without one explicitly derogating or excepting the other. Report all of these.
      - `extension` — one rule extends/specializes the other (e.g. HR-PORTS-001 vs HR-BRIDGES-001: same dependency-inversion mechanic, different boundary). Report only if confidence < 0.7 (uncertain whether it is a clean extension or a hidden tension).
      - `orthogonal` — independent concerns. Do not report.
      - `needs-review` — too ambiguous to classify automatically. Report.

   e. **Print the semantic section**

      Append section **E) Semantic tensions** to the structural report:

      ```
      E) TENSIONES SEMÁNTICAS
        Pares analizados:    <N>
        Pares reportados:    <M>  (contradicciones <c>, needs-review <r>, extensiones dudosas <e>)

        - [HR-XXX-001] vs [HR-YYY-001] — contradiction (0.85)
          <one-sentence explanation in Spanish>

        - ...
      ```

      If no tensions are reported, print: `✓ Sin tensiones semánticas detectadas (analizados <N> pares).`

3. **Decide on actions**

   For each finding, propose one of three actions and state which:

   - **Structural**:
     - Dead glob (`paths` / anchor) → either the code moved (update the rule's `paths`/anchor) or the pattern is genuinely too narrow / aspirational (note it; consider narrowing or removing the anchor). Editing a broken `paths`/anchor is allowed without derogation.
     - Dead `detect.pattern` → the teeth match nothing governed; tighten `paths`, fix the pattern, or accept (the rule is purely advisory now).
     - Too-broad `detect.pattern` → would over-block; judge whether to narrow it or accept the breadth.
     - Uninstalled bc-bound BC → expected if the BC is not installed in this checkout; accept, or remove the rule if the BC is gone for good.
     - scope↔bounded_contexts incoherence → fix the frontmatter (`scope` or `bounded_contexts`) + `pnpm hr:generate`.
     - Orphan citation → fix the citation or restore the missing rule.
     - Zombie rule → the rule has no `@rule` cite and is old; note it is policy/architectural without code anchor (HR are often advisory), or add citations.
     - Stale assumption marker → resolve `[VERIFICAR]` / `[ASUNCIÓN]` and edit the rule in place.
   - **Semantic** — for each reported pair, propose exactly one:
     - **fix** — adjust an anchor pattern / decision matrix / `detect` so the tension disappears (a non-semantic correction; editing typos, paths, or anchors is allowed in place).
     - **derogate + replace** — if the contradiction is a genuine architectural change: derogate the superseded rule and author a NEW rule with a NEW id (HR ids are never reused), then `pnpm hr:generate && pnpm hr:validate`. This is the only path for a semantic change to a rule's `### Enunciado` or `### Casos exhaustivos`.
     - **accept** — the pair is a legitimate, declared relationship (e.g. HR-PORTS-001 ↔ HR-BRIDGES-001 cross-reference each other in `### Reglas relacionadas`); document the relationship if missing, otherwise no action.

4. **Commit fixes**

   Group related fixes into focused commits with `chore(harness-rules):` or `fix(harness-rules):` prefixes.

---

## Buckets de tamaño (estructural)

The size bucket from section A informs how to scope step 2:

- `OK` (< 150 active rules) — full semantic sweep is fine.
- `INFO` (150–249) — full sweep still feasible; consider scoping to a path/keyword cluster if noisy.
- `WARN` (250–499) — start filtering. Ask the user before running the full sweep.
- `SOFT_ERROR` (500–999) — filtering is mandatory. Do not run the full sweep without explicit user opt-in.
- `REARCHITECT` (≥ 1000) — pairwise no longer scales; recommend sub-catalogs/embeddings before running.

---

## Guardrails

- The structural script is read-only. Step 2 is also read-only; Claude must NEVER modify the catalog from inside this command — any catalog change is a deliberate follow-up (derogate + create new, or a path/typo fix), run separately with `pnpm hr:generate && pnpm hr:validate`.
- The semantic verdicts are **best-effort guidance**, not enforcement. Treat the report as input for human review, not as ground truth.
- A semantic change to a rule's `### Enunciado` or `### Casos exhaustivos` is **derogate + create new with a new id**, never an in-place edit (HR convention; see `references/format.md`).
- `/harness-rules:document` and `/harness-rules:promote` do NOT exist by design — HR are not bootstrapped from an aggregate's code, nor crystallized per-change. Do not look for them. See `.claude/skills/harness-rules-guard/references/enforcement.md`.
- Don't suppress findings without explicit reasoning; they are signals about catalog health.
- The semantic sweep uses the tokens of the active Claude Code subscription. There is no API key, no SDK call, no remote routine — the analysis happens in this session.
