Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .ails/config.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
default_agent: claude
exclude_dirs:
- fixtures
- research
- _archive
- _archived
- .venv
- docs
- specs
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ framework/rules/**/tests/**/.claude/
# Bundled ONNX embedding model — fetched by scripts/fetch_bundled_model.py
# (dev-only, not committed; populated on clone and in CI before hatch build)
src/reporails_cli/bundled/models/

# npm packaging — README.md is copied from the repo root by the prepack
# script in packages/npm/package.json before `npm pack` / `npm publish`.
# Keeping the file gitignored avoids the maintenance drift of two committed
# READMEs while sidestepping the npmjs.com per-version display bug that the
# previous symlink approach hit.
packages/npm/README.md
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Changelog

## 0.5.7

### Added

- [framework/schemas/project.schema.yml]: New `surfaces` and `agents` keys for `.ails/config.yml`. `surfaces.<agent>.<file_type>.include` / `.exclude` adjusts which globs each agent surface scans without modifying bundled configs. `agents.<id>.fallback_filenames` mirrors Codex `project_doc_fallback_filenames` so per-project alternative instruction filenames (e.g. `TEAM_GUIDE.md`) are picked up by the validator.
- [core/config]: `.ails/config.local.yml` (gitignored) layers on top of committed `.ails/config.yml` for personal/CI overrides — object keys merge recursively, array keys extend, scalars replace.
- [interfaces/cli/config_command]: `ails config set` writes `.ails/.gitignore` listing `.gitignore` itself and `config.local.yml` whenever `.ails/config.yml` is created/updated, so layered local config stays out of version control by default.
- [framework/rules]: `nested_context` declarations for codex / cursor / copilot / generic agents so per-package `**/AGENTS.md` files in monorepos are surfaced under the agent's on-demand loading model rather than skipped.
- [formatters/text]: Surface classifier distinguishes `main` (root-level instruction file) from `nested` (subdirectory copies). Scorecard shows a separate "Nested" section; nested file paths display the full relative path (`packages/web/CLAUDE.md`) so users can locate them.

### Changed

- [framework/schemas]: Added `scope: nested` to the `agent.schema.yml` and `rule.schema.yml` enums. Captures surfaces whose subtree applicability comes from file LOCATION (subdirectory CLAUDE.md / AGENTS.md / GEMINI.md) rather than from in-file frontmatter. Replaces the previous overload of `scope: path_scoped` for these surfaces.
- [core/agent_discovery]: Project root for `ails check <path>` is now `<path>` itself — no walking up. Files outside the targeted subtree are out of scope, regardless of `.git` or `.ails/backbone.yml` location. `engine_helpers._find_project_root` continues to walk up for cache key derivation only and now also recognizes IDE workspace markers (`.vscode/`, `.idea/`, `.github/`) as project-root signals.
- [core/agent_discovery + core/agents]: Filename matching for agent instruction files is now case-sensitive, matching Codex's source (`codex-rs/core/src/agents_md.rs` — `DEFAULT_AGENTS_MD_FILENAME = "AGENTS.md"`, `LOCAL_AGENTS_MD_FILENAME = "AGENTS.override.md"`) and the agents.md spec. A file named `agents.md` (lowercase, no leading dot) is no longer falsely surfaced as a Codex AGENTS.md candidate.
- [framework/rules/cursor]: `cursor.rules` corrected to `scope: path_scoped` (frontmatter-based path filtering); `cursor.bugbot_rules` to `scope: global` (BugBot decides applicability).

### Fixed

- [core/classification + core/agent_discovery]: Instruction-file discovery and classification now correctly distinguish `main` files at the user's target from `nested_context` / `child_instruction` files in subdirectories. Per-package CLAUDE.md / AGENTS.md / GEMINI.md files in monorepos are classified as `nested_context` rather than `main`, so size and other `match: {type: main}` rules no longer false-positive on per-package nested files. Bug surfaced against [activepieces/activepieces](https://github.com/activepieces/activepieces).
- [core/registry]: `depends_on` resolves through supersession. When `CODEX:S:0003 supersedes CORE:S:0027`, rules that depend on `CORE:S:0027` (e.g., `CORE:S:0030`, `CORE:G:0006`) are satisfied by `CODEX:S:0003` instead of warning that the dependency is "not loaded". `_apply_supersession` returns a `{superseded_id: successor_id}` map; `_validate_depends_on` consults it before emitting the missing-dependency warning.
- [core/classification]: `_location_matches_mode` distinguishes "loose" leaf patterns (`**/CLAUDE.md`, bare `CLAUDE.md`) from "tight" path-prefixed patterns (`.github/copilot-instructions.md`). Path-prefixed patterns already constrain location via the prefix, so the ancestor-chain check is skipped — fixes false-negative classification of Copilot's `.github/copilot-instructions.md`.
- [tests/unit/test_scan_scope]: `test_codex_fallback_filenames_surface` now creates `.codex/config.toml` in the fixture so codex passes the codex/generic disambiguation deterministically — was HOME-dependent (locally `~/.codex/` let codex through, fresh CI runners without `~/.codex/` dropped codex and the fallback patterns never fired).

## 0.5.6

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Reporails CLI (v0.5.6)
# Reporails CLI (v0.5.7)

> **AI Instruction Diagnostics for coding agents. Validates the entire agentic instruction system against 92+ rules across six categories. Supports Claude, Codex, Copilot, Cursor, and Gemini.**
>
Expand Down
62 changes: 60 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "Configuration"
description: "Disabling rules, project / global config, exclude paths"
version: "0.5.6"
last_updated: 2026-05-04
version: "0.5.7"
last_updated: 2026-05-06
---

# Configuration
Expand Down Expand Up @@ -96,6 +96,64 @@ For one-off runs, pass `--exclude-dirs` on the command line:
ails check --exclude-dirs examples --exclude-dirs third_party
```

## Per-surface include / exclude

Each agent has a set of *surfaces* — `main` (the primary instruction file), `nested_context` (subdirectory variants), `rules`, `skills`, `agents`, etc. The `surfaces` key lets you adjust the glob patterns each surface scans, without modifying the bundled framework configs:

```yaml
# .ails/config.yml
surfaces:
cursor.rules:
exclude: ["**/draft/**"] # drop matches under draft/ from Cursor rules
claude.skills:
include: [".github/skills/**/SKILL.md"] # also scan .github/skills/ for Claude
codex.main:
exclude: ["**/legacy/AGENTS.md"] # drop legacy AGENTS.md from Codex's main candidates
```

Keys are `<agent_id>.<file_type>` (e.g. `cursor.rules`, `claude.main`, `codex.nested_context`). Each entry may set:

- `include`: additional glob patterns to scan **on top of** the agent's bundled patterns.
- `exclude`: glob patterns whose matches are dropped from the surface's results.

Patterns match relative to the project root (the directory you ran `ails check` from).

## Codex fallback filenames

Codex supports `project_doc_fallback_filenames` in its own `~/.codex/config.toml` to recognize alternative instruction filenames (e.g. `TEAM_GUIDE.md`, `.agents.md`). Reading that user-home config from the validator is fragile — CI users have different homes — so Reporails reads the same setting from the project's own `.ails/config.yml`:

```yaml
# .ails/config.yml
agents:
codex:
fallback_filenames: ["TEAM_GUIDE.md", ".agents.md"]
```

These filenames are added as `**/<filename>` to Codex's `main` surface — they classify the same way `AGENTS.md` does and pick up the same rules.

## Local overrides — `.ails/config.local.yml`

Personal or CI-specific config that should not be committed goes in `.ails/config.local.yml`. The file is layered on top of `.ails/config.yml`:

- Object keys merge recursively.
- Array keys extend (the local list is appended to the committed list).
- Scalar keys are replaced.

```yaml
# .ails/config.local.yml — gitignored
surfaces:
claude.main:
exclude: ["**/legacy/CLAUDE.md"] # I personally don't care about legacy/
```

When `ails config set …` writes `.ails/config.yml`, it also writes `.ails/.gitignore` listing `config.local.yml` and `.gitignore` itself — the gitignore is per-machine scaffolding (recreated on the next `ails config set`) and doesn't need to be committed. If you create `.ails/` manually, add the two lines yourself:

```
# .ails/.gitignore
.gitignore
config.local.yml
```

## Severity overrides

Severity is what makes a finding "critical" vs "info". Default severity comes from the rule itself; you can override it per project:
Expand Down
11 changes: 7 additions & 4 deletions framework/rules/claude/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ file_types:
maintainer: human

child_instruction:
# Subdirectory CLAUDE.md files. Path-scoping comes from file LOCATION
# (no frontmatter filter). scope: nested captures this — the file's
# subtree applicability is implicit in where the file lives.
source: https://code.claude.com/docs/en/memory#how-claude-md-files-load
format: freeform
scope: path_scoped
cardinality: collection
scope: nested
cardinality: hierarchical
lifecycle: static
loading: on_demand
scopes:
Expand Down Expand Up @@ -184,8 +187,8 @@ file_types:
maintainer: human

hooks:
# Hooks configured in settings.json, skill/agent frontmatter, plugin hooks.json
# 28+ events, 5 types (command/HTTP/mcp_tool/prompt/agent)
# Hooks configured in settings.json, skill/agent frontmatter, plugin hooks/hooks.json
# 27 events, 5 types (command/HTTP/mcp_tool/prompt/agent). Verified 2026-05-06.
source: https://code.claude.com/docs/en/hooks
format: schema_validated
scope: global
Expand Down
116 changes: 106 additions & 10 deletions framework/rules/codex/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
# AGENTS.md is a cross-agent standard (agents.md) — its presence alone
# does not indicate a Codex project. Detection requires .codex/ markers
# (config.toml, rules/, agents/, hooks.json) or AGENTS.override.md.
#
# Synced from .claude/skills/audit-agent/assets/registry/codex/config.yml
# Last verified: 2026-05-06
#
# Items intentionally NOT included here (cannot be statically measured):
# - fallback_main: project_doc_fallback_filenames is user-configurable in
# ~/.codex/config.toml; the validator cannot statically know what filenames
# a user has declared.
# - plugins: marketplace install path not documented in stable form.
# - scheduled_tasks: Codex Desktop Automations on-disk path not documented.
# - cloud-managed requirements / macOS MDM preferences (not flat files).

agent: codex
version: "0.5.0"
Expand All @@ -12,9 +23,13 @@ name: OpenAI Codex

file_types:
main:
# AGENTS.md walked from project root to cwd, concatenated (chain).
# Per-directory order: AGENTS.override.md > AGENTS.md > project_doc_fallback_filenames.
# Combined byte cap: project_doc_max_bytes (32 KiB default).
source: https://developers.openai.com/codex/guides/agents-md/
format: freeform
scope: global
cardinality: singleton
cardinality: chain
lifecycle: static
loading: session_start
scopes:
Expand All @@ -27,12 +42,16 @@ file_types:
patterns: ["~/.codex/AGENTS.md", "~/.codex/AGENTS.override.md"]
precedence: user
vcs: external
cardinality: singleton
maintainer: human

override:
# AGENTS.override.md — same walk as main, checked first at each directory level.
# Also recognized at ~/.codex/AGENTS.override.md (declared on `main.user` above).
source: https://developers.openai.com/codex/guides/agents-md/
format: freeform
scope: global
cardinality: optional
cardinality: chain
lifecycle: mutable
loading: session_start
scopes:
Expand All @@ -42,7 +61,30 @@ file_types:
vcs: committed
maintainer: human

nested_context:
# Per-package AGENTS.md in subdirectories below cwd. Codex's chain walk goes
# project-root → cwd, so files BELOW cwd aren't eagerly loaded — but a user
# who cd's into those subdirectories will pick them up. scope: nested
# captures the subtree-by-location semantic without overloading `global`.
source: https://developers.openai.com/codex/guides/agents-md/
format: freeform
scope: nested
cardinality: hierarchical
lifecycle: static
loading: on_demand
scopes:
project:
patterns: ["**/AGENTS.md"]
precedence: project
vcs: committed
maintainer: human

skills:
# 6 discovery scopes per Codex docs: CWD .agents/skills, parent ../.agents/skills,
# repo root .agents/skills, user ~/.agents/skills + ~/.codex/skills, admin
# /etc/codex/skills (Linux/macOS) or %ProgramData%\OpenAI\Codex\skills (Windows),
# and system bundled (no on-disk path).
source: https://developers.openai.com/codex/skills/
format: [frontmatter, freeform]
scope: task_scoped
cardinality: hierarchical
Expand All @@ -60,16 +102,19 @@ file_types:
vcs: external
maintainer: human
system:
patterns: ["/etc/codex/skills/**/SKILL.md"]
patterns:
- "/etc/codex/skills/**/SKILL.md"
- "C:/ProgramData/OpenAI/Codex/skills/**/SKILL.md"
precedence: managed
vcs: external
maintainer: system

skill_metadata:
# Per-skill optional: display info, policy, MCP dependencies
# Per-skill optional: zero or one openai.yaml per skill
source: https://developers.openai.com/codex/skills/
format: schema_validated
scope: task_scoped
cardinality: collection
cardinality: optional
lifecycle: static
loading: on_invocation
scopes:
Expand All @@ -80,6 +125,7 @@ file_types:
maintainer: human

agents:
source: https://developers.openai.com/codex/subagents
format: schema_validated
scope: task_scoped
cardinality: collection
Expand All @@ -98,6 +144,9 @@ file_types:
maintainer: human

rules:
# Starlark .rules — execution control via prefix_rule(). Both project and
# user scopes documented.
source: https://developers.openai.com/codex/rules
format: schema_validated
scope: global
cardinality: collection
Expand All @@ -109,13 +158,22 @@ file_types:
precedence: project
vcs: committed
maintainer: human
user:
patterns: ["~/.codex/rules/*.rules"]
precedence: user
vcs: external
maintainer: human

hooks:
# 6 events: SessionStart, PreToolUse, PostToolUse, PermissionRequest,
# UserPromptSubmit, Stop. Requires [features] codex_hooks = true.
# Hooks can also live inline in [hooks] table inside config.toml.
source: https://developers.openai.com/codex/hooks
format: schema_validated
scope: global
cardinality: singleton
cardinality: collection
lifecycle: static
loading: session_start
loading: on_demand
scopes:
project:
patterns: [".codex/hooks.json"]
Expand All @@ -129,10 +187,13 @@ file_types:
maintainer: human

config:
# contains harness settings AND attention-channel instructions/developer_instructions fields
# User-level singleton: ~/.codex/config.toml.
# Project-level chain: .codex/config.toml walked from project root to cwd
# (closest wins). Trusted projects only.
source: https://developers.openai.com/codex/config-advanced/
format: schema_validated
scope: global
cardinality: singleton
cardinality: chain
lifecycle: static
loading: session_start
scopes:
Expand All @@ -146,8 +207,43 @@ file_types:
precedence: user
vcs: external
maintainer: human
cardinality: singleton

mcp:
# MCP servers in [mcp_servers.<id>] tables. Both user and project config.toml
# accept the section; project scope requires trusted-project status.
source: https://developers.openai.com/codex/mcp
format: schema_validated
scope: global
cardinality: collection
lifecycle: static
loading: session_start
scopes:
project:
patterns: [".codex/config.toml"]
precedence: project
vcs: committed
maintainer: human
user:
patterns: ["~/.codex/config.toml"]
precedence: user
vcs: external
maintainer: human

enterprise:
# Admin-enforced requirements.toml. Constrains approval policy, sandbox,
# MCP allowlists, hooks, command rules, filesystem permissions.
source: https://developers.openai.com/codex/enterprise/managed-configuration
format: schema_validated
scope: global
cardinality: singleton
lifecycle: static
loading: session_start
scopes:
system:
patterns: ["/etc/codex/requirements.toml"]
patterns:
- "/etc/codex/requirements.toml"
- "C:/ProgramData/OpenAI/Codex/requirements.toml"
precedence: managed
vcs: external
maintainer: system
Expand Down
Loading
Loading