From c4281ae1910be1a84c831be3f918989d0ee720b5 Mon Sep 17 00:00:00 2001 From: mhenrixon Date: Sat, 19 Sep 2026 18:17:49 +0200 Subject: [PATCH] chore(rtk): AGENTS.md as the shared instruction file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLAUDE.md becomes a one-line stub importing AGENTS.md. Merges the project rules that lived in CLAUDE.md (tech stack, critical rules, architecture, testing, deploy) into AGENTS.md alongside the existing cross-tool authoring guide, adds a screenshots-on-PRs section (docs-kit is a visual product), and repoints internal CLAUDE.md references to AGENTS.md. No .rtk/filters.toml: bundle exec rspec/rubocop are already rtk-rewritten, bun run build:css is already rtk-rewritten, and bundle exec rake's noise is RSpec's documentation-format example list, which can't be safely line-stripped without risking a hidden failure — AGENTS.md now recommends running rspec and rubocop separately instead of through rake. --- .claude/commands/github-review-comments.md | 6 +- .claude/commands/plan.md | 4 +- .claude/rules/agents.md | 2 +- AGENTS.md | 203 ++++++++++++++++----- CLAUDE.md | 125 +------------ spec/spec_helper.rb | 2 +- 6 files changed, 169 insertions(+), 173 deletions(-) diff --git a/.claude/commands/github-review-comments.md b/.claude/commands/github-review-comments.md index ca1f3f2..d5b9ef8 100644 --- a/.claude/commands/github-review-comments.md +++ b/.claude/commands/github-review-comments.md @@ -101,7 +101,7 @@ For each unresolved comment, read the full body and categorise it: 2. Check if the suggestion is technically correct for THIS codebase 3. Check if it would break existing functionality (a consuming docs site) 4. Check if existing patterns/conventions contradict the suggestion -5. Check CLAUDE.md rules -- project conventions override reviewer preferences +5. Check AGENTS.md rules -- project conventions override reviewer preferences --- @@ -220,7 +220,7 @@ When pushing back: - Use technical reasoning grounded in the actual codebase - Reference existing patterns if the suggestion contradicts them -- Reference CLAUDE.md rules when applicable +- Reference AGENTS.md rules when applicable - Explain what would break or what edge case the reviewer missed - If the suggestion is valid in principle but wrong for this context, say so @@ -231,7 +231,7 @@ When pushing back: - Always read the actual code before evaluating a comment -- reviewers sometimes misread diffs - If a comment reveals a genuine bug you missed, fix it without defensiveness - If multiple comments suggest the same change, implement it once and reference the fix in all replies -- Bot reviewers (CodeRabbit, etc.) sometimes suggest changes that conflict with project conventions -- verify against CLAUDE.md +- Bot reviewers (CodeRabbit, etc.) sometimes suggest changes that conflict with project conventions -- verify against AGENTS.md - If a new round of review comments appears after your push (from re-review), report that to the user rather than entering an infinite loop Now begin by determining the PR number from `$ARGUMENTS` or the current branch. diff --git a/.claude/commands/plan.md b/.claude/commands/plan.md index 60f15d7..051c537 100644 --- a/.claude/commands/plan.md +++ b/.claude/commands/plan.md @@ -29,7 +29,7 @@ Protect this session's context: delegate mechanical exploration to cheaper subag 1. Fan out Explore agents (`model: haiku`) for file discovery and naming-convention sweeps; use `model: sonnet` agents when a subsystem needs to be read and summarized. Launch independent explorations in parallel. 2. Read the load-bearing files yourself — the ones the design decision actually hinges on. Don't design from subagent summaries alone. For docs-kit that usually means `lib/docs_kit/configuration.rb`, the relevant `app/components/docs_ui/*.rb`, `lib/docs_kit/engine.rb`, and the install generator under `lib/generators/docs_kit/install/`. -3. Read `CLAUDE.md` and the `.claude/rules/` files — the project invariants live there. +3. Read `AGENTS.md` and the `.claude/rules/` files — the project invariants live there. 4. Check `git log` for recent related work; the design should extend it, not fight it. ## Phase 2 — Surface the unknowns (blindspot pass + interview) @@ -41,7 +41,7 @@ Investigation tells you what the codebase says; this phase finds what the REQUES - edge cases the codebase makes possible that the request never mentions - anything with no precedent in this repo — flag it explicitly as unknown-unknown territory 2. **Interview the user** with AskUserQuestion, one question at a time, prioritized by blast radius: architecture-changing answers first, then public API / config surface, then UX. Rules: - - Skip anything the codebase, CLAUDE.md, or an existing issue already answers. + - Skip anything the codebase, AGENTS.md, or an existing issue already answers. - 2–5 questions is the sweet spot; zero is fine when the request is genuinely unambiguous — say so rather than inventing questions. - Every question offers concrete options with a recommended default, never an open-ended essay prompt. 3. **Record the answers** in the plan's Decision section as `Settled in interview:` bullets — constraints the executor must not re-litigate. diff --git a/.claude/rules/agents.md b/.claude/rules/agents.md index 10d9760..6949a5f 100644 --- a/.claude/rules/agents.md +++ b/.claude/rules/agents.md @@ -23,7 +23,7 @@ When spawning subagents for **mechanical** work (file finding, pattern scans, naming-convention sweeps), pass a cheaper model explicitly (`model: haiku`) rather than letting them inherit the session model. Use `model: sonnet` when a subsystem must be read and summarized. Keep the expensive model for judgment in -the main session. See `CLAUDE.md` for the tier convention. +the main session. See `.claude/README.md` for the tier convention. ## Parallel Execution diff --git a/AGENTS.md b/AGENTS.md index 200147c..dcf5ac5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,41 +1,62 @@ # AGENTS.md -Guidance for AI coding agents working in the **docs-kit** repository. This is the -cross-tool convention file (Claude Code, Cursor, Copilot, Aider, …). Claude Code -users also have `.claude/commands/` and `.claude/rules/`; see `CLAUDE.md` for the -full project brief. This file is the fast orientation. +The instruction file for every AI coding agent working in docs-kit — Claude +Code imports it (`CLAUDE.md` is a one-line `@AGENTS.md` stub); Cursor, +Copilot, Aider, Codex and others read it directly. Claude Code also has +`.claude/commands/` and `.claude/rules/` for slash-command workflows, listed +below; this file stays the shared source of project conventions. docs-kit is a Rails engine that ships the shared Phlex/daisyUI **chrome** for -documentation sites — the shell, sidebar, code blocks, theme switcher, page kit — -so many docs sites look identical and are maintained in one place. The gem also -**dogfoods itself**: its own docs site lives under `docs/`. +documentation sites — the shell, sidebar, code blocks, theme switcher, page +kit — so many docs sites look identical and are maintained in one place. The +gem also **dogfoods itself**: its own docs site lives under `docs/`. + +## Tech Stack + +- **Ruby**: >= 3.2 | **Rails**: >= 7.1 (engine) +- **Rendering**: phlex-rails (Phlex 2) — the chrome is `DocsUI::` components +- **Styling**: daisyUI (via the `daisyui` gem) on Tailwind CSS v4, built with the standalone CLI (Bun) +- **Icons**: lucide via `rails_icons` +- **Highlighting**: Rouge (~200 languages), inline theme CSS +- **Client**: ONE Stimulus controller (`docs-nav`) auto-pinned by the engine +- **Autoloading**: zeitwerk +- **Testing**: RSpec (component render + registry + generator) +- **Linting**: RuboCop (`rubocop`) + +## Critical Rules + +### Never Do +1. **NO raw daisyUI markup** — the chrome is composed from `DocsUI::` Phlex components; a site never hand-writes drawer/menu HTML +2. **NO hardcoded site-specific values in a component** — brand, themes, nav, version badge come from `DocsKit.configuration` +3. **NO JS-required pages** — the server renders a working, fully-expanded page; the `docs-nav` controller only *enhances* (collapse persistence, auto-TOC). It must work with JS off +4. **NO per-feature Stimulus controllers** — there is exactly ONE (`docs-nav`), auto-pinned by the engine +5. **NO theme in `config.themes` that the CSS build never generated** — the switcher list MUST match the `@plugin "daisyui" { themes: ... }` block +6. **NO new emitted class without a CSS scan** — Tailwind scans Ruby; render-time classes (Drawer) need `@source inline(...)` +7. **NO `raw`/`html_safe` on config free text** — let Phlex escape text; only gem-authored trusted markup may bypass the escape +8. **NO required setup documented in the README alone** — wire it into the install generator AND the `docs-kit new` template, or new sites don't get it +9. **NO manual `gem push`** — release via `rake release[X.Y.Z]` + +### Always Do +1. **TDD**: write the failing spec first — `spec/docs_kit/**` (config/registry, no boot), `spec/docs_ui/**` (component render), `spec/generators/install_generator_spec.rb` (generator, plain Thor) — then the minimum code (RED → GREEN → REFACTOR) +2. **Read config, with a default** — a new knob lives on `DocsKit::Configuration` with a sensible default so existing sites keep working (backwards compatible) +3. **Compose from the kit** — new chrome is a `DocsUI::` component, not markup +4. **Render through a real view context** — `#render_page` renders with `layout: false` because `DocsUI::Shell` IS the whole document; CSRF, `dom_id`, url helpers, and (on reactive sites) the token signer must still work +5. **Keep the switcher and the CSS in sync** — themes offered == themes built +6. **Wire setup into the install path** — the generator templates and `docs-kit new` template, both +7. **Assert on semantics, not snapshots** — a component spec checks an active link / a present theme / a config-driven value, not a brittle full-HTML string ## The two things you'll be asked to do ### A. Change the gem (a component, config knob, generator, the engine) -Read `CLAUDE.md` first — it has the layer map and the critical rules. The -non-negotiables: - -- **Compose from `DocsUI::` Phlex components** — never hand-write raw daisyUI markup. -- **Site-specific values come from `DocsKit.configuration`**, never hardcoded in a - component. A new knob lands on `DocsKit::Configuration` with a sensible default - (backwards compatible). -- **The page works with JavaScript off.** The server renders it fully; the one - `docs-nav` Stimulus controller only *enhances* (collapse persistence, auto-TOC). -- **Themes offered must exist in the CSS build** — `config.themes` must match the - `@plugin "daisyui" { themes: … }` block. -- **Required setup wires into BOTH** the install generator - (`lib/generators/docs_kit/install/`) **and** the `docs-kit new` template - (`lib/docs_kit/templates/new_site.rb`) — never the README alone. -- **TDD**: write the failing spec first (`spec/docs_kit`, `spec/docs_ui`, - `spec/generators`), then the minimum code. Assert on semantics, not HTML snapshots. +Follow Critical Rules above. Read the load-bearing file for the layer you're +touching before writing code — see Architecture below for the layer map. ### B. Write a docs page for docs-kit's own docs site (under `docs/`) The dogfood site is itself a docs-kit site. Its registry is -`docs/app/models/doc.rb`; its pages are `docs/app/views/docs/pages/`. To document -a feature of the gem: +`docs/app/models/doc.rb`; its pages are `docs/app/views/docs/pages/`. To +document a feature of the gem: **1. Scaffold** (from the `docs/` app): @@ -43,31 +64,121 @@ a feature of the gem: cd docs && bin/rails g docs_kit:page "Getting Started" --group=Guide ``` -That writes `docs/app/views/docs/pages/getting_started.rb` **and** injects the -required `page "Getting Started", group: "Guide"` line into `Doc`. Overrides: -`--slug`, `--view`, `--eyebrow`, `--registry`. The registry line is **required** — -no line, no page. - -**2. Write `#content` — Markdown first.** Prose is `md` with a **single-quoted** -heredoc (`<<~'MD'`) so `#{…}` stays literal (Phlex escapes author text — never -`html_safe` or interpolate). `DocsUI::Section` owns page structure and the TOC; -never use a Markdown `##` for structure. The primary arg is positional, modifiers -are keywords: `Section("Title", description:)`, `Code(source, filename:)`. For no -positional arg use the lowercase helpers `md` / `prose` / `example`. Reference -material has dedicated helpers: `DocsUI::PropTable`, `DocsUI::FieldTable`, -`DocsUI::RequestExample`, `DocsUI::Callout(:note | :tip | :warning)`. +That writes `docs/app/views/docs/pages/getting_started.rb` **and** injects +the required `page "Getting Started", group: "Guide"` line into `Doc`. +Overrides: `--slug`, `--view`, `--eyebrow`, `--registry`. The registry line is +**required** — no line, no page. + +**2. Write `#content` — Markdown first.** Prose is `md` with a +**single-quoted** heredoc (`<<~'MD'`) so `#{…}` stays literal (Phlex escapes +author text — never `html_safe` or interpolate). `DocsUI::Section` owns page +structure and the TOC; never use a Markdown `##` for structure. The primary +arg is positional, modifiers are keywords: `Section("Title", description:)`, +`Code(source, filename:)`. For no positional arg use the lowercase helpers +`md` / `prose` / `example`. Reference material has dedicated helpers: +`DocsUI::PropTable`, `DocsUI::FieldTable`, `DocsUI::RequestExample`, +`DocsUI::Callout(:note | :tip | :warning)`. The always-current, worked example of the whole contract is -`docs/app/views/docs/pages/authoring.rb` (rendered at `/docs/authoring`). Read it -before writing a page. +`docs/app/views/docs/pages/authoring.rb` (rendered at `/docs/authoring`). +Read it before writing a page. + +## Commands + +```bash +bundle exec rspec # Suite (component render + registry + config + generator); SimpleCov enforces an 80% minimum +bundle exec rubocop # Lint (rubocop -A to autocorrect) +bundle exec rake # spec + rubocop, together — mixes both tools' raw output, so prefer running the two commands above separately when you need to read the result +bun run build:css # Rebuild the Tailwind/daisyUI CSS (in the docs/ app, or a consuming site) +``` + +Command output is condensed by rtk (PreToolUse hook). Write commands in +hook-rewritable shapes: no `for`/subshell wrappers, no `| head` on +rtk-handled commands, `bundle exec rubocop` not `bin/rubocop`. + +Never `gem push` by hand — release via `rake release[X.Y.Z]`. + +## Architecture + +``` +Layer 4: Client runtime app/javascript/docs_kit/controllers/docs_nav_controller.js (ONE controller: collapse persistence + auto-TOC + scroll-spy) +Layer 3: Components app/components/docs_ui/*.rb (Shell, Sidebar, ThemeSwitcher, Icon, Code, Page, Header, Section, Prose, Callout, Example, OnThisPage) +Layer 2: Registry + values lib/docs_kit/registry.rb (in-memory docs registry mixin), lib/docs_kit/nav_item.rb (sidebar link value object) +Layer 1: Config + controller lib/docs_kit/configuration.rb (per-site knobs), lib/docs_kit/controller.rb (#render_page) +Layer 0: Core + engine lib/docs_kit.rb, lib/docs_kit/engine.rb (auto-pins docs-nav, mounts the controller assets) + Install path lib/generators/docs_kit/install/ (install generator + templates), lib/docs_kit/templates/new_site.rb, exe/docs-kit (docs-kit new) + Deploy .github/workflows/deploy.yml (reusable), deploy-docs.yml (thin caller); dash + GHCR + Cloudflare Tunnel +``` + +## The mental model + +> Every docs site gets the SAME chrome. What differs between two sites is +> **configuration**, not markup. A component reads `DocsKit.configuration`; +> the server renders a working page; the one `docs-nav` controller enhances +> it. + +Client interactivity is client-only UX polish (which `
` you left +open, the "on this page" TOC) — there is no server round-trip. See +`README.md`. + +## Testing + +- Unit specs (`spec/docs_kit/`) cover the config surface and the registry — no Rails boot. +- Component specs (`spec/docs_ui/`) render a `DocsUI::` component and assert on the produced markup's semantics (an active link, a present theme option, a config-driven value). +- Generator specs (`spec/generators/install_generator_spec.rb`) run `docs_kit:install` against a throwaway destination root (a tmp app skeleton, plain Thor — no Rails boot) and assert the file manifest + key contents. +- Coverage: SimpleCov enforces `minimum_coverage 80` from within the suite (`bundle exec rspec` / `rake` fails below it); 100% aspired for `DocsKit::Configuration` and `DocsKit::Registry` (the public API sites depend on). +- CI: `.github/workflows/ci.yml` runs `bundle exec rake` on Ruby 3.2/3.3/3.4 for every push to `main` and every PR. +- See `.claude/rules/testing.md`. + +## Deploy + +The build + deploy is defined **once** in this gem's reusable workflow +(`.github/workflows/deploy.yml`). `docs-kit new` scaffolds a thin caller. The +naming invariant: `image`/`service` must be the calling repo's `OWNER/REPO` +so `GITHUB_TOKEN` can push (build) and pull (deploy) the auto-linked GHCR +package. See the README "Deploy a new docs site" section for the five wiring +points and the naming note. + +## Screenshots on PRs and issues (always) -## Verify before you finish (every change) +`gh` ≥ 2.99 uploads images and videos itself. A change to `DocsUI::` chrome +(Shell, Sidebar, ThemeSwitcher, Page, Callout, …) or to a docs page's rendered +output ships with before/after pictures **on the PR**, attached from the +terminal. Never a local path, a base64 blob, or "screenshot available on +request". ```bash -bundle exec rspec # the suite (SimpleCov enforces 80% minimum) -bundle exec rubocop # lint — no offenses (rubocop -A to autocorrect) -bundle exec rake # both, together +gh pr create --attach './after.png#Sidebar collapsed on mobile' --title … --body … # picture in hand already +gh pr comment --attach './after.png#Sidebar collapsed on mobile' --body 'Before/after for the sidebar.' +gh pr comment --attach ./before.png --attach ./after.png # repeat the flag, up to 50 files +gh issue comment --attach ./repro.mp4 # video renders as a player ``` -For CSS-affecting changes (a new emitted class), rebuild in the `docs/` app: -`bun run build:css`. Never `gem push` by hand — release via `rake release[X.Y.Z]`. +- Quote the whole argument: the alt text has spaces and bare `<`/`>` would + redirect. `#` sets the alt text; without it the filename is + used. A body that already references the file (`![alt](./after.png)`) gets + that reference rewritten to the uploaded asset, so images can sit inline; + unreferenced attachments are appended at the end. +- `create`, `edit` and `comment` all take `--attach` (all three landed in gh + 2.99). Attach at create time when the picture already exists; comment when + it comes later, as it does after a verification run. +- Capture with `agent-browser screenshot ` or the Playwright MCP + `browser_take_screenshot`, pointed at the `docs/` dogfood app (`bin/dev`) or + a consuming site. Save under the scratchpad, never in the repo. +- No `--attach` flag means an old `gh`: `brew upgrade gh`. + +## Claude Code specifics + +Slash commands (`.claude/commands/`) and rules (`.claude/rules/`) drive +autonomous work: `/plan`, `/lfg`, `/tdd`, `/architect`, `/security`, +`/review-pr`, `/github-review-pr`, `/github-review-failures`, +`/github-review-comments`. Full purpose + model tier per command, and the +model-tier convention (`haiku`/`sonnet`/`opus`/`fable`) for subagents: +`.claude/README.md`. + +## More Documentation + +- `.claude/commands/` — slash command definitions +- `.claude/rules/` — coding style, git workflow, testing, agents +- `.claude/README.md` — command index + model tiers +- `README.md` — the full install/configure/render/deploy guide diff --git a/CLAUDE.md b/CLAUDE.md index 6b6a017..acdecb5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,122 +1,7 @@ -# docs-kit +# docs-kit — Claude Code entry point -Shared [Phlex](https://www.phlex.fun) chrome for documentation sites built on -[daisyUI](https://daisyui.com) — the shell, sidebar, code blocks, theme switcher, -and page kit extracted into one gem so multiple docs sites look identical and are -maintained in one place. +@AGENTS.md -## Tech Stack - -- **Ruby**: >= 3.2 | **Rails**: >= 7.1 (engine) -- **Rendering**: phlex-rails (Phlex 2) — the chrome is `DocsUI::` components -- **Styling**: daisyUI (via the `daisyui` gem) on Tailwind CSS v4, built with the standalone CLI (Bun) -- **Icons**: lucide via `rails_icons` -- **Highlighting**: Rouge (~200 languages), inline theme CSS -- **Client**: ONE Stimulus controller (`docs-nav`) auto-pinned by the engine -- **Autoloading**: zeitwerk -- **Testing**: RSpec (component render + registry + generator) -- **Linting**: RuboCop (`rubocop`) - -## Critical Rules - -### Never Do -1. **NO raw daisyUI markup** — the chrome is composed from `DocsUI::` Phlex components; a site never hand-writes drawer/menu HTML -2. **NO hardcoded site-specific values in a component** — brand, themes, nav, version badge come from `DocsKit.configuration` -3. **NO JS-required pages** — the server renders a working, fully-expanded page; the `docs-nav` controller only *enhances* (collapse persistence, auto-TOC). It must work with JS off -4. **NO per-feature Stimulus controllers** — there is exactly ONE (`docs-nav`), auto-pinned by the engine -5. **NO theme in `config.themes` that the CSS build never generated** — the switcher list MUST match the `@plugin "daisyui" { themes: ... }` block -6. **NO new emitted class without a CSS scan** — Tailwind scans Ruby; render-time classes (Drawer) need `@source inline(...)` -7. **NO `raw`/`html_safe` on config free text** — let Phlex escape text; only gem-authored trusted markup may bypass the escape -8. **NO required setup documented in the README alone** — wire it into the install generator AND the `docs-kit new` template, or new sites don't get it -9. **NO manual `gem push`** — release via `rake release[X.Y.Z]` - -### Always Do -1. **TDD**: Write tests BEFORE implementation (RED → GREEN → REFACTOR) -2. **Read config, with a default** — a new knob lives on `DocsKit::Configuration` with a sensible default so existing sites keep working (backwards compatible) -3. **Compose from the kit** — new chrome is a `DocsUI::` component, not markup -4. **Render through a real view context** — `#render_page` renders with `layout: false` because `DocsUI::Shell` IS the whole document; CSRF, `dom_id`, url helpers, and (on reactive sites) the token signer must still work -5. **Keep the switcher and the CSS in sync** — themes offered == themes built -6. **Wire setup into the install path** — the generator templates and `docs-kit new` template, both -7. **Assert on semantics, not snapshots** — a component spec checks an active link / a present theme / a config-driven value, not a brittle full-HTML string - -## Commands - -```bash -bundle exec rspec # Suite (component render + registry + config + generator) -bundle exec rubocop # Lint (rubocop -A to autocorrect) -bundle exec rake # spec + rubocop -bun run build:css # Rebuild the Tailwind/daisyUI CSS (in a consuming site) -``` - -## Slash Commands - -| Command | Purpose | -|---------|---------| -| `/plan` | Fable-powered planning → GitHub issue or `docs/plans/` markdown (read-only; execute with `/lfg`) | -| `/lfg` | Full autonomous workflow: branch → understand → explore → plan → TDD → verify → PR | -| `/tdd` | Enforce RED → GREEN → REFACTOR | -| `/architect` | Coordinate a change across config → registry → components → client → generator → CSS | -| `/security` | Security audit (HTML escaping, config trust, the render path, generated files, deploy secrets) | -| `/review-pr` | Review a PR for pattern compliance | -| `/github-review-pr` | Full PR pass: fix CI failures, then resolve review comments (in that order) | -| `/github-review-failures` | Fix failing CI checks until green | -| `/github-review-comments` | Process unresolved PR review comments | - -## Architecture - -``` -Layer 4: Client runtime app/javascript/docs_kit/controllers/docs_nav_controller.js (ONE controller: collapse persistence + auto-TOC + scroll-spy) -Layer 3: Components app/components/docs_ui/*.rb (Shell, Sidebar, ThemeSwitcher, Icon, Code, Page, Header, Section, Prose, Callout, Example, OnThisPage) -Layer 2: Registry + values lib/docs_kit/registry.rb (in-memory docs registry mixin), lib/docs_kit/nav_item.rb (sidebar link value object) -Layer 1: Config + controller lib/docs_kit/configuration.rb (per-site knobs), lib/docs_kit/controller.rb (#render_page) -Layer 0: Core + engine lib/docs_kit.rb, lib/docs_kit/engine.rb (auto-pins docs-nav, mounts the controller assets) - Install path lib/generators/docs_kit/install/ (install generator + templates), lib/docs_kit/templates/new_site.rb, exe/docs-kit (docs-kit new) - Deploy .github/workflows/deploy.yml (reusable), deploy-docs.yml (thin caller); dash + GHCR + Cloudflare Tunnel -``` - -## The mental model - -> Every docs site gets the SAME chrome. What differs between two sites is -> **configuration**, not markup. A component reads `DocsKit.configuration`; the -> server renders a working page; the one `docs-nav` controller enhances it. - -Client interactivity is client-only UX polish (which `
` you left open, -the "on this page" TOC) — there is no server round-trip. See `README.md`. - -## Model tiers (for Claude Code commands & agents) - -Commands and agents pin a model **tier** via frontmatter aliases, not a full -model ID — aliases track the latest model in each tier, so pins never go stale: - -- `haiku` — mechanical/config work, diff pattern-scans -- `sonnet` — layer specialists / pattern-following implementation (the default for `/tdd`, the review-comment/failure runbooks) -- `opus` — orchestration, security, production/PR review (`/lfg`, `/architect`, `/security`, `/review-pr`, `/github-review-pr`) -- `fable` — pinned only on `/plan` (read-only planning that hands execution to cheaper models); otherwise choose it per-session with `/model` for architecture and the hardest debugging - -When spawning subagents for mechanical work (file finding, pattern scans), pass a -cheaper model explicitly (`model: haiku`) rather than letting them inherit the -session model. See `.claude/rules/agents.md`. - -## Testing - -- Unit specs (`spec/docs_kit/`) cover the config surface and the registry — no Rails boot. -- Component specs (`spec/docs_ui/`) render a `DocsUI::` component and assert on the produced markup's semantics (an active link, a present theme option, a config-driven value). -- Generator specs (`spec/generators/install_generator_spec.rb`) run `docs_kit:install` against a throwaway destination root (a tmp app skeleton, plain Thor — no Rails boot) and assert the file manifest + key contents. -- Coverage: SimpleCov enforces `minimum_coverage 80` from within the suite (`bundle exec rspec` / `rake` fails below it); 100% aspired for `DocsKit::Configuration` and `DocsKit::Registry` (the public API sites depend on). -- CI: `.github/workflows/ci.yml` runs `bundle exec rake` on Ruby 3.2/3.3/3.4 for every push to `main` and every PR. -- See `.claude/rules/testing.md`. - -## Deploy - -The build + deploy is defined **once** in this gem's reusable workflow -(`.github/workflows/deploy.yml`). `docs-kit new` scaffolds a thin caller. The -naming invariant: `image`/`service` must be the calling repo's `OWNER/REPO` so -`GITHUB_TOKEN` can push (build) and pull (deploy) the auto-linked GHCR package. -See the README "Deploy a new docs site" section for the five wiring points and -the naming note. - -## More Documentation - -- `.claude/commands/` — slash command definitions -- `.claude/rules/` — coding style, git workflow, testing, agents -- `README.md` — the full install/configure/render/deploy guide +`AGENTS.md` is the single project-instruction file, shared with Cursor, +Copilot, Aider and Codex. Claude-only material lives in `.claude/` +(`rules/` auto-load; commands, skills) — see `.claude/README.md`. diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2ce8567..e582dae 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Coverage. Start SimpleCov BEFORE requiring docs_kit so every lib/ file loaded -# below is tracked. CLAUDE.md sets the 80% floor; enforce it here so `rake` fails +# below is tracked. AGENTS.md sets the 80% floor; enforce it here so `rake` fails # locally and in CI when coverage regresses. The generators/ tree is the install # generator, exercised by spec/generators/**. require "simplecov"