Skip to content

Latest commit

 

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rule-architect

Release License: MIT

npx skills add moveju112/rule-architect -g

An agent skill that generates a production-grade, runtime-neutral rule set for a project: one slim AI_RULES.md index, runtime entry files that resolve to it, and on-demand docs/*.md rule files — all verified by a script and a quiz test before it calls itself done.

Works in English and Korean. Triggers are registered in both languages, and the generated rules follow the project's existing docs language (or yours, if the project has none).


⚠️ Required: model tier

This skill runs on judgment. A weak model produces a broken rule set. --update in particular must honor "diff-edit only the changed sections". A weak model regenerates whole files instead and destroys hand-written rules.

Tool Minimum Recommended Do not use
Claude Code Sonnet 5 (fresh generation only) Opus 5 / Fable 5 + effort high Haiku tier
Codex CLI / GPT GPT-5 flagship tier GPT-5 Codex + reasoning high mini · nano tiers

Never run --update at the minimum tier. Use Opus 5 / Fable 5 on Claude, or a flagship tier on GPT. And commit your existing rule files first — that way a bad run is one git checkout away from undone.

Model-independent: scripts/verify_rules.py. Line budgets, link integrity, and citation-freshness checks are deterministic, so the model tier does not affect them.


What it generates

  • AI_RULES.md (≤60 lines) — the runtime-neutral slim index: Core Rules + run commands + a Routing table.
    • The Routing table maps "situation/task → file to read", not "topic → file". Rows without a concrete trigger are rejected.
  • CLAUDE.md + AGENTS.md — relative symlinks to AI_RULES.md on Linux/WSL/POSIX projects.
    • Repositories that must work without symlink support receive two short regular-file pointers instead.
    • Both entries use the same mode; neither contains rule bodies or points at the other.
  • docs/*.md (≤150 lines each) — topic rule docs, loaded only when the topic comes up.
    • Always: ARCHITECTURE.md, CODING_RULES.md, PITFALLS.md
    • Conditional: CONTROLLER_RULES.md, ENUM_CODES.md, RESPONSE_KEYS.md, DB_RULES.md, DEPLOY.md
  • docs/tasks/*.md (≤80 lines each) — playbooks for recurring tasks: numbered steps, each citing file:line evidence.
    • Generated only for tasks where git log shows the same file set changed together ≥3 times (e.g. ADD_API.md, ADD_MODEL.md).
    • Cross-file couplings are recorded as playbook steps, not as standalone rules.

Rule format

Every rule carries a grade, a reason, and a contrasting pair of examples.

- **[MUST|NEVER|PREFER]** <rule, one line>
  - why: <one line>
  - ❌ <a real violation from THIS project — file:line or snippet>
  - ✅ <the correct form — real project code>

Conflict priority: NEVER > MUST > PREFER. PITFALLS.md uses symptom → cause → fix, with the symptom quoting the error message verbatim so it stays greppable.

Core principle

Record only what the code cannot tell you. Anything one ls, one file read, or one grep would reveal is not a rule. Cross-file couplings, required ordering, forbidden actions, in-flight migrations — those are rules.

Language

The rule set is written in one language per run, chosen in this order:

  1. The project's existing AI_RULES.md / legacy rule index / docs/*.md / README language.
  2. The language you are writing in.
  3. English.

Structural tokens never change: MUST / NEVER / PREFER, why:, the ❌/✅ markers, UPPERCASE file names, and the <!-- generated by rule-architect --> marker stay as-is in every language.

Install

npx skills add moveju112/rule-architect -g

Works with Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, and the other agents the Skills CLI supports. Drop -g to install into the current project instead of user-level.

As a Claude Code plugin instead:

claude plugin marketplace add moveju112/rule-architect
claude plugin install rule-architect@rule-architect

Or from inside a Claude Code session:

/plugin marketplace add moveju112/rule-architect
/plugin install rule-architect@rule-architect

By hand:

git clone https://github.com/moveju112/rule-architect.git ~/.claude/skills/rule-architect

# optional — register the slash command
ln -s ~/.claude/skills/rule-architect/commands/rule-architect.md ~/.claude/commands/

Without the symlink the /rule-architect slash command is not registered, but the skill still fires on natural-language triggers.

Usage

/rule-architect [project-path]
/rule-architect [project-path] --update   # diff-update an existing rule set

Natural language, either language:

English Korean
"make rules for this project" "이 프로젝트 룰 만들어줘"
"generate AI rules" "AI 룰 만들어"
"upgrade the project rules" "프로젝트 룰 고도화해줘"

Verification

Two gates, and the rule set is not done until both pass.

scripts/verify_rules.py <project-root> — the form gate. Strict by default: exceeding a target budget fails rather than warns. --lenient demotes target overruns to warnings; hard limits fail either way. It checks:

  • bidirectional link integrity, and that ARCHITECTURE.md, CODING_RULES.md, and PITFALLS.md exist and are linked
  • line budgets: AI_RULES.md ≤60 (hard 80), docs ≤150 (hard 190), playbooks ≤80 (hard 100)
  • both runtime entries are valid relative symlinks to AI_RULES.md, or both are portable pointers
  • Core Rules ≤10 bullets, and routing rows whose trigger is neither empty nor a restatement of the file name
  • every graded rule carries a why: line and a ✅ example
  • placeholder scan, UPPERCASE naming
  • citation freshness — a cited src/db.py:42 fails both when the file is gone and when the file is shorter than 42 lines, which is how a rule that quietly survived a refactor gets caught. Dockerfile, Makefile, and dotfiles count as citations; bare naming patterns like UPPERCASE.md do not.

Quiz test — the content gate. A fresh subagent answers 5 questions given ONLY AI_RULES.md once and the generated docs, with no source access:

  • 3 recall — "Where does a new model have to be registered?"
  • 1 judgment — "I want to do X; is approach Y allowed?" (measures application, not recall)
  • 1 negative — something the rules do not cover. It passes only if the agent says "not in the rules, check the source" instead of inventing an answer.
  • Pass = ≥4 correct AND the negative question passed.

scripts/quiz.py builds the isolation prompt and grades the run, archiving it to .rule-architect/quiz/<run-id>.json. It deliberately does not execute a model — the skill dispatches the isolated subagent, and a quiz "pass" with no archived run does not count.

Update safety

scripts/manifest.py records a SHA-256 for each generated regular file and records the type and target for each runtime symlink. It merges into the existing manifest (--replace records a complete set instead). Before an update run, manifest.py check compares the working tree against those records:

Exit Meaning Policy
0 generated files unchanged safe to regenerate
1 a file was hand-edited, or is missing conflict — never overwrite, report and ask
2 no manifest (legacy project) treat every rule file as hand-written; add only

This is what replaces "commit your rule index first and hope". The old single marker at the bottom of a rule index could not tell a hand-written rule from a stale generated one; a per-file hash can, and the policy on ambiguity is to stop rather than guess.

Reproducibility

scripts/scan.py <root> prints a JSON manifest of the measured signals — stack, layer directories, enum-defining files, deploy artifacts, git co-change groups — the conditional-doc decisions derived from them, each with its evidence. It also reports brokenRuleLinks, which blocks an update before a damaged entry is mistaken for a new project. Same commit in, same manifest out. Git history is scoped to the project directory, so a project nested inside a larger repository does not inherit that repository's commits.

Every traversal is bounded (--max-files, --max-bytes, --max-commits), vendor and build directories are skipped, and hitting a cap sets a truncated flag, so a partial scan can never be mistaken for a complete one.

Harvested rules

A repo scan knows what the project contains. It cannot know what the agent kept getting wrong in it. scripts/harvest.py <root> reads this project's past session transcripts and prints your own corrections — recency-ordered, credential-redacted, with a table of the terms that recur across different corrections. Corrections are the highest-yield rule source there is: someone already paid for each one.

The script only measures. A candidate is promoted to a rule only when it repeats (≥2 corrections), is recent, belongs to this project, and still agrees with the current code — then it cites file:line evidence like any other rule. Nothing from the harvest lands in a rule file verbatim.

python3 scripts/harvest.py <root> --days 180 --limit 60

Hook promotion

Rules a machine can enforce — forbidden calls, forbidden imports, banned paths — are not written into the docs. Prose depends on the agent having loaded and honoured it; a hook does not. They are listed in the final report as hook promotion candidates, and emitted only when you explicitly ask:

python3 scripts/hookgen.py emit <root> --rules spec.json            # spec + guard, prints the settings entry
python3 scripts/hookgen.py emit <root> --rules spec.json --write    # also merges it into .claude/settings.json
python3 scripts/hookgen.py check <root>                             # what is already installed

Two rule shapes: forbid matches a regex against the text a call would write; deny blocks a path outright for the tools it lists (["Read", "Grep", "Glob"] keeps an off-limits directory unread — a repo-wide grep with no path is the one case it cannot attribute).

emit installs .rule-architect/hooks.json (the rules) and .claude/hooks/rule_guard.py (a generic PreToolUse guard that reads them). The guard blocks the call and tells the agent which rule it broke; it fails open on any internal error, so a guard bug can never wedge a session. --write edits your harness config, so it is never passed on its own.

Only rules whose violation a regex can name get promoted. Anything needing type information, call graphs, or judgement stays prose.

Optional integration

If the md-en-kr skill is installed, the run offers English compression at the end. It is an offer, never automatic.

Development

python3 tests/test_rules.py   # clones the fixture per case, breaks one contract, asserts the failure

Layout:

scripts/     scan.py, harvest.py, manifest.py, verify_rules.py, quiz.py,
             hookgen.py, rule_guard.py (copied into projects, not run here)
tests/       test_rules.py + fixtures/good/ (a rule set that passes strict)
docs/adr/    decisions and their consequences
archive/     dated records from earlier builds — not the current contract

Repository notes

archive/ holds dated internal records from the original build, kept in Korean as written. They are not the current contract and are known to have drifted from it; archive/README.md names the drift.

License

MIT — see LICENSE.

About

Claude Code skill that builds a project's AI rule set — slim CLAUDE.md index + AGENTS.md pointer + on-demand docs/*.md rules, with link/budget verification and a quiz test

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages