---
name: straion-import-rules
description: >-
  Extract development rules from a repository's agent-instruction files
  (CLAUDE.md, AGENTS.md, AGENT.md), the markdown they reference, and known
  rule locations like .cursor/rules and CONTRIBUTING.md, then upload them via
  `straion import-rules`. Use when the user asks to "import rules", "analyze
  this repo", "extract coding standards", "scan for conventions", when
  starting on an unfamiliar repository, or when the `straion` CLI hands off
  to the agent as part of its import flow.
---

# Import Rules

Pipe rule collections extracted from this repo's instruction files to
`straion import-rules`. Rules describe _how_ code is written — never _what_
or _why_. Tell the user up front: **"Looking for rules…"**

## 1. Precheck

Skip if the invocation includes `--skip-precheck` or `--force`. Otherwise:

```bash
straion import-rules --precheck
```

- `No existing rules found` → continue.
- `Found N rule collection(s)` → ask verbatim:

  > This repository already has N rule collection(s). Do you want me to
  > re-import them? (y/n)

  On `y`, forward `--force` to step 4. Anything else, stop.

## 2. Discover sources

- **Seed:** `CLAUDE.md`, `AGENTS.md`, `AGENT.md` at repo root.
- **Follow references (≤ 2 hops):** local `.md`/`.mdc` reached via markdown
  links `[x](path)` or `@path` imports. Dedupe by absolute path.
- **Probe siblings:** `.cursor/rules/*.mdc`, `.cursorrules`, `.windsurfrules`,
  `.clinerules`, `.github/copilot-instructions.md`, `CONTRIBUTING.md`,
  `STYLEGUIDE.md`, `CODESTYLE.md` (root only).

Classify each:

- **Directive** (uses `must`/`should`/`never`/`always`/`do not`/`prefer`, or
  bulleted conventions) → include.
- **Narrative** (overviews, "why" docs, changelogs) → skip.
- **Ambiguous** (mixed, e.g. README with a Conventions section) → hold.

Print the set with ✓ / ? markers and ask which ambiguous files to include.
If the final set is empty, stop — do not invent rules from source code.

## 3. Extract

Group rules into **collections** by domain ("React Patterns", "Testing", …).
Emit one collection per JSON line (step 4); omit any field you have no information for:

```json
{
  "name": "React Patterns",
  "description": "Component, hook, and state conventions.",
  "meta": { "tags": ["style"], "frameworks": ["react"] },
  "rules": [
    {
      "statement": "MUST use function components; class components are not allowed.",
      "meta": { "tags": ["style"], "languages": ["typescript"] },
      "examples": [
        { "kind": "violating", "lang": "typescript", "code": "class Btn extends React.Component {}" },
        { "kind": "compliant", "lang": "typescript", "code": "const Btn = () => <button />" }
      ]
    }
  ]
}
```

- `name`: plain text ≤ 150 chars. `description` (required): GFM markdown —
  scope, when it applies, why it matters.
- `statement`: exactly **one** directive, beginning with the uppercase
  strength word `MUST` / `MUST NOT` / `SHOULD` / `SHOULD NOT` / `MAY`, then the
  imperative, ending in a period.
  - **Verb-first.** Source docs are subject-first ("Field names should be
    lowerCamelCase", "List must use GET"); drop the subject and fold it into
    the predicate → `SHOULD use lowerCamelCase for field names.` /
    `MUST use the HTTP GET method for the List method.`
  - **One directive per rule — never join clauses with "and".** Split every
    compound, including same-strength pairs and especially **mixed-strength**
    ones: validation only reads the first word, so
    `SHOULD avoid combination, MUST NOT use allOf` silently buries a
    `MUST NOT`. Emit two rules instead — a `SHOULD` and a `MUST NOT`.
  - **Preserve strength exactly.** Map synonyms `REQUIRED`/`SHALL`→`MUST`,
    `RECOMMENDED`→`SHOULD`, `OPTIONAL`→`MAY`. Capture `MAY`/optional
    directives too, not only `MUST`/`SHOULD`.
  - Fold any condition ("in test files, …") into the sentence.
- `meta.tags`: optional; include the ones that apply. Open vocab — e.g.
  architecture, security, performance, style, testing, documentation,
  accessibility, dependencies, observability.
- `meta.languages` / `meta.frameworks`: omit when language/framework-agnostic;
  set on the collection only when every rule shares that scope.
- `examples`: include when the source shows code —
  `{ "kind": "compliant"|"violating", "lang": "…", "code": "…", "explanation"?: "…" }`.
  `lang` is required — the code-fence language (`text` when the sample has no
  specific language). Keep code minimal; omit examples if none shown.
- Never emit `$schema`, `id`, `meta.rev`, or `provenance` — the CLI sets those.

Extract only from the discovered sources. Skip narrative paragraphs even
inside an included file.

Work one source file at a time. Scan each for every `MUST` / `MUST NOT` /
`SHOULD` / `SHOULD NOT` / `MAY` / `REQUIRED` / `SHALL` / `RECOMMENDED` /
`OPTIONAL` — each is at least one rule. Long enumerative files (header lists,
field tables, status-code sections) lose tail items, so before leaving a file
confirm every directive keyword in it maps to a rule. If two sources state
conflicting strengths for the same rule, capture both and flag the conflict to
the user instead of silently choosing one.

## 4. Upload

NDJSON on stdin, one collection per line. Add `--force` if step 1 required it.

```bash
straion import-rules <<'EOF'
{"name":"React Patterns","description":"…","meta":{"tags":["style"]},"rules":[…]}
{"name":"API Design","description":"…","meta":{"tags":["architecture"]},"rules":[…]}
EOF
```

The CLI validates each line and prints a per-collection summary. On failure,
fix the reported collections and re-run the **entire corrected set** with
`--force` — it replaces the previous import as a whole (never resend a subset:
collections left out of a `--force` run are removed). Unchanged collections
and rules keep their identity across re-imports.
