---
name: harness-rules-guard
description:
  'Guards and guides the harness rules catalog — the project''s
  architectural/framework constraints. Triggers when an HR rule is cited or
  asked about by ID; when about to touch paths governed by an active HR rule;
  during /opsx:propose (declaring `## Harness rules applicable`); or when
  editing files under cliter/harness-rules/.'
license: MIT
metadata:
  author: aurora
  version: '1.0'
  auto_invoke:
    'Mentioning harness rules, HR-XXX-NNN, an architectural/framework
    constraint (shadow module, cross-BC, ports/adapters, generated code, dev
    modes, double cast); about to touch paths governed by an active HR rule;
    during /opsx:propose; files under cliter/harness-rules/.'
---

## When to Use

Invoke this skill when:

- The user references a **harness rule** by its identifier (`HR-MODULES-001`,
  `HR-BRIDGES-001`, `HR-ACL-001`, etc.).
- You are about to modify code under paths governed by an active HR rule (look
  up `cliter/harness-rules-index.json` by `byPath`, `byKeyword`, or `byId`).
- During `/opsx:propose`, you need to declare the `## Harness rules applicable`
  section in `proposal.md` (COMPLY / VIOLATE / DEROGATE per governing rule).
- You are editing a rule file under `cliter/harness-rules/<topic>.md` (or the
  bc-bound location).
- A write is blocked by the architecture checkpoint and its message names
  governing `HR-*` ids you must consult.

## Framing — HR are CONSTRAINTS, not post-implementation memory

This is the single most important difference from `business-rules-guard`. **Do
not** carry over the BR mental model.

| Aspect      | Business Rules (BR)                                  | Harness Rules (HR)                                          |
| ----------- | --------------------------------------------------- | ---------------------------------------------------------- |
| Nature      | Domain **invariants** — what the business is true   | Architectural / framework **constraints** — how code lives |
| Framing     | **Memory** + incoherence detector (post-hoc)        | **Constraint** you honor NOW, before/while you write       |
| Verb        | `mantiene` / `deroga` / `extiende`                  | **COMPLY** / **VIOLATE** / **DEROGATE**                    |
| Lifecycle   | Crystallized POST-archive via `/business-rules:promote` | **No promote lifecycle.** Stable; changes only by a deliberate architectural decision |
| In proposal | `## Business rules affected` (declares future rules) | `## Harness rules applicable` (records compliance with EXISTING rules) |

HR are **enforce-able architectural/framework constraints to honor (COMPLY) or
deliberately retire (DEROGATE via an architectural decision)**. They are NOT
documented after the fact to be promoted later — they govern the work you are
about to do.

## Step 0 — Three entry routes

First identify which **route** applies.

| Route                              | When it applies                                                                                  | What to do                                                                 |
| ---------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| **Consult before/while coding**    | About to touch a path an active HR governs, or a write was blocked citing an HR id               | Look up the index (`byPath`/`byKeyword`/`byId`), read the rule, COMPLY      |
| **Declare at propose time**        | During `/opsx:propose` — record `## Harness rules applicable` in `proposal.md`                   | Run the propose-time conflict detection (`enforcement.md`), declare per rule |
| **Edit the catalog**               | A convention genuinely changed and the rule must be derogated/replaced                           | Derogate + create a new rule with a NEW id; `pnpm hr:generate && hr:validate` |

There IS a `/harness-rules:audit` command (read-only health/drift: script
sections A-B + LLM section E — see `references/enforcement.md`). There is **no**
`/harness-rules:document` or `/harness-rules:promote` command, by design: HR are
not bootstrapped from an aggregate's code, nor crystallized per-change. Beyond
audit, HR enforcement is the prompt-time injection + propose-time detection +
checkpoint messaging + content-guard described in `references/enforcement.md`.

## How to consult the index

`cliter/harness-rules-index.json` is the consolidated, generated index (run
`pnpm hr:generate` to regenerate — never edit it by hand). Three lookups:

- **`byPath`** — array of `{ pattern, ruleIds }`. Find every entry whose glob
  `pattern` matches the file you are about to touch; the `ruleIds` are the rules
  that govern it. This is the primary lookup before writing code.
- **`byKeyword`** — map of `keyword → ruleIds`. Use when the task mentions a
  harness concept (`shadow module`, `cross-bc`, `ports`, `generated code`,
  `solution mode`, `double cast`) but you are unsure which paths it touches.
  Keywords are deliberately bilingual (Spanish + English).
- **`byId`** — map of `id → rule entry` (with `state`, `severity`, `paths`,
  `keywords`, `filePath`, and an optional `detect`). Use when the user cites an
  id directly, and to read `severity` (`blocking` | `informational`) and `state`
  (only `active` rules govern).

Then open the rule file at `byId[id].filePath` for the full `### Enunciado`,
`### Casos exhaustivos` decision matrix, and `### Anchor patterns`.

## Identifier convention

```
Core:        HR-<TOPIC>-<NNN>            → HR-MODULES-001, HR-ACL-001
Bc-bound:    HR-<BC>-<TOPIC>-<NNN>       → HR-TOOLS-MIGRATIONS-001 (when one exists)
Multi-BC:    primary BC in the id; the rest declared in `bounded_contexts`
```

- **UPPERCASE**, deliberately — they stand out as references in code, prose, and
  PRs. Must match `[A-Z]{2,}-[A-Z0-9-]+`.
- `<NNN>` is sequential, zero-padded to 3 digits, unique within its topic prefix.
- **IDs are never reused.** A derogated rule keeps its id permanently.

## COMPLY / VIOLATE / DEROGATE semantics

When a rule governs the work, the change does exactly ONE of:

- **COMPLY** — the approach honors the rule. This is the default and the desired
  outcome. Record it so the analysis is auditable (e.g. in `## Harness rules
  applicable`).
- **VIOLATE** — the approach breaks the rule as written. For a `blocking` rule
  this HALTS `/opsx:propose` and requires a user decision (derogate / exception /
  justify no-conflict). For an `informational` rule it is surfaced but does not
  halt.
- **DEROGATE** — a deliberate architectural decision to retire or replace the
  rule. This is rare and is itself an architectural change (its own OpenSpec
  change), not a side effect of an ordinary proposal. It means editing the rule
  file (state → `derogated`) and creating a replacement with a new id.

There is no `mantiene / extiende` here, and there is **no** "new HR to be
created post-archive" — that vocabulary belongs to Business Rules only.

## Two-level enforcement (advisory vs content-blocked)

HR are NOT enforced uniformly. Know which level a rule sits at — full detail in
`references/enforcement.md`.

- **Content-blocked** — a rule that declares a `detect: { pattern, message }`
  field (propagated to `byId[id].detect`) is enforced by a `PreToolUse`
  content-guard that BLOCKS (exit 2) any `Write`/`Edit`/`MultiEdit` whose content
  matches the pattern under the rule's paths. **Today the ONLY content-blocked
  rule is `HR-ACL-001`** (`as unknown as`). An approach that needs that pattern
  is a hard VIOLATE.
- **Advisory** — the other five rules (`HR-MODULES-001`, `HR-BRIDGES-001`,
  `HR-PORTS-001`, `HR-CODEGEN-001`, `HR-MODES-001`) have NO `detect` field. They
  are surfaced via this skill, prompt-time injection, propose-time detection, and
  checkpoint messaging; the agent applies judgment. They are **never
  auto-blocked** — a path glob cannot distinguish a legitimate new flow from a
  shadow module, nor a within-BC adapter from a misplaced cross-BC one.

## Inviolable conventions

1. **Catalog lives at `cliter/harness-rules/<topic>.md`** (core) or
   `cliter/<bc>/harness-rules/<topic>.md` (bc-bound). The file name describes the
   **topic** (`modules`, `bridges`, `ports-adapters`), not an aggregate — HR are
   mostly procedural.
2. **IDs in UPPERCASE** (`HR-<TOPIC>-<NNN>`). **Never** reuse identifiers from
   derogated rules.
3. **Frontmatter in kebab-lowercase**; `bounded_contexts`, `keywords`, `paths`
   are arrays. `scope` (`project | bc-bound | multi-bc`) is an HR-only field BR
   does not have; `bounded_contexts` allows `minItems: 0` and `aggregates` is
   optional (both differ from BR).
4. **Deliberate language mix**: prose in Spanish, identifiers and citations in
   English, keywords bilingual. **NEVER "harmonize"**.
5. **JSON output keys in English**: `state`, `severity`, `scope`, `paths`,
   `keywords`, `detect`. The metadata table labels in the `.md` stay in Spanish
   (`Estado`, `Severidad`, `Origen`).
6. **Enum values in English**: `active | derogated | proposed` for state,
   `blocking | informational` for severity.
7. **Semantic changes = derogate + create new**, never edit the `### Enunciado`
   or the `### Casos exhaustivos` matrix in place. Editing typos, broken paths,
   or `last_updated` IS allowed.
8. **HR are stable constraints.** There is no `/harness-rules:promote`; a
   proposal records compliance with the EXISTING catalog, it does not declare HR
   to be created later.
9. **`cliter/harness-rules-index.json` and `docs/harness-rules/INDEX.md` are
   generated.** Never edit them by hand — run `pnpm hr:generate`.
10. **Modifying `openspec/`**: only `openspec/config.yaml` (the Harness Rules
    guidance folded into its `context:` block and `rules.proposal` list — the
    keys OpenSpec injects into `/opsx:propose`). Nothing else under `openspec/`.

## How to work with each route

Read the reference file that applies:

- **Exact rule-file format** (frontmatter, `detect`, metadata table, decision
  matrix, anchor patterns) → `references/format.md`.
- **The three activation layers + advisory-vs-content-blocked split** →
  `references/enforcement.md`.

For high-level system context (rationale, dual location, scope semantics, ID
policy, format-vs-BR differences), read `docs/harness-rules/README.md`. It is the
canonical catalog convention doc — this skill references it, it does not
duplicate it.

## Anti-patterns (do not do)

1. **Treating HR like BR memory.** HR are constraints you honor while writing,
   not documentation crystallized post-archive. Do not look for a `promote`
   step; there is none.
2. **Using `mantiene / deroga / extiende` or a `Nuevas` subsection in a
   proposal.** That is BR vocabulary. HR use COMPLY / VIOLATE / DEROGATE against
   the existing catalog.
3. **Editing the semantics of a rule in place** (the `### Enunciado` or the
   `### Casos exhaustivos` results) without derogating. Semantic change =
   derogate + create new with a new id.
4. **Reusing derogated identifiers.** Compromises historical traceability of
   citations in code and PRs.
5. **"Harmonizing" the language mix** to a single language. It is deliberate and
   documented in `docs/harness-rules/README.md` and `CLAUDE.md`.
6. **Hand-editing `cliter/harness-rules-index.json` or
   `docs/harness-rules/INDEX.md`.** They are generated; run `pnpm hr:generate`.
7. **Declaring `aggregates` on a procedural HR** just out of BR habit. It is
   optional; omit it unless the rule is aggregate-specific.
8. **Citing a path in `### Implementa` that does not resolve on disk.** Causes
   `pnpm hr:validate` exit 2; cite only verified paths or reference the source in
   prose.
9. **Expecting the content-guard to block semantic rules.** Only rules with a
   `detect` field block (today only `HR-ACL-001`). MODULES/BRIDGES/PORTS/
   CODEGEN/MODES are advisory — the agent's judgment is the enforcement.
10. **Skipping the `## Harness rules applicable` section in a proposal that
    touches governed paths.** Write `None` only when no active rule governs any
    touched path.

## Available commands

The only HR slash command is **`/harness-rules:audit`** (read-only health/drift:
script sections A-B + LLM section E; not exposed as a `pnpm hr:*` alias — run via
the slash command or `npx tsx scripts/harness-rules/audit.ts`, `--json` for
tooling). `/harness-rules:document` and `/harness-rules:promote` do NOT exist by
design (HR are not bootstrapped from code / not crystallized per-change). Operate
the catalog with the pnpm scripts:

| Command                | Function                                                        |
| ---------------------- | --------------------------------------------------------------- |
| `pnpm hr:generate`     | Regenerate `cliter/harness-rules-index.json` and `INDEX.md`.    |
| `pnpm hr:validate`     | Validate format and consistency (exit `0` / `1` / `2`).         |
| `pnpm hr:check`        | Targeted validation (topic, rule, branch, PR, working tree).    |
| `/harness-rules:audit` | Read-only health/drift report + semantic-tension continuation.  |

`hr:validate` exit codes: `0` valid, `1` structural errors (invalid frontmatter,
duplicate ids, missing/unknown Estado/Severidad), `2` warnings only (typically a
`### Implementa` path that no longer resolves on disk).

## Quick verification after any catalog change

```bash
pnpm hr:generate && pnpm hr:validate
```

If this fails, **do not commit** until you fix it. The pre-commit hook
regenerates the index automatically when `cliter/harness-rules/**/*.md` (or
`cliter/*/harness-rules/**/*.md`) changes; if regeneration fails, the commit is
aborted. A BR-only change does NOT trigger HR regeneration (and vice versa).
