Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
75c68ac
Union per-surface excludes across overlapping surfaces in agent_disco…
cleverhoods May 6, 2026
cbb7b92
Relativize ruleset_map paths in scorecard.py surface classification
cleverhoods May 6, 2026
3e24bf5
Drop orphan .shared/knowledge/changelog.md (no longer used)
cleverhoods May 6, 2026
6ee4277
Promote skill-no-readme to CORE:S:0035 (cross-agent rule)
cleverhoods May 6, 2026
ea69b99
Promote skill-name-matches-directory to CORE:S:0036 (cross-agent rule)
cleverhoods May 6, 2026
8e0556c
Promote skill-description-length to CORE:S:0040 (cross-agent rule)
cleverhoods May 6, 2026
98c7004
Promote import-depth-within-limit to CORE:S:0033 with per-agent super…
cleverhoods May 6, 2026
70cfd72
Revert memory-file rule to CLAUDE:S:0011 (Claude-only file mechanic) …
cleverhoods May 6, 2026
f84a98e
Lower CLAUDE:S:0009 rule-snippet-length severity to low + topic-scatt…
cleverhoods May 6, 2026
e7de2f1
Add _FILE_TYPE_MATCH_ALIASES bandage so cross-agent rules match plura…
cleverhoods May 6, 2026
bf878bf
Update mcp/server.py explain-tool example to a current rule coordinate
cleverhoods May 6, 2026
bba13aa
Rename copilot/applyto-scope-declared to path-scope-declared (family …
cleverhoods May 6, 2026
575c6da
Add compact wire payload + per-tier byte-size preflight to CLI
cleverhoods May 6, 2026
3c6e76f
Consolidate UNRELEASED entries from this batch and sanitize wire-payl…
cleverhoods May 6, 2026
1a584ee
Switch skill-directory-kebab-case source URL to agentskills.io for co…
cleverhoods May 6, 2026
b253f8d
Bump version to 0.5.8
cleverhoods May 6, 2026
b65811c
Release 0.5.8: move UNRELEASED entries to CHANGELOG.md and make mappe…
cleverhoods May 6, 2026
b342339
Add CORE:C:0055 description-coherence rule; deep-link unknown_error b…
cleverhoods May 6, 2026
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
103 changes: 0 additions & 103 deletions .shared/knowledge/changelog.md

This file was deleted.

30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# Changelog

## 0.5.8

### Added

- [core/payload]: New `core/payload.py` module producing a compact wire payload for HTTP transport. Reduces request body size on large projects.
- [core/funnel]: New `WIRE_MAX_BYTES_BY_TIER` table and `preflight_byte_size()` function. Local preflight returns a `payload_too_large` `FunnelError` before transmission instead of an opaque server-side 4xx.
- [framework/rules/core/description-coherence]: New rule (`CORE:C:0055`) for files loaded on invocation (skills, subagents, slash commands) whose frontmatter `description:` doesn't match the body content. Server-execution rule. Replaces the previously-stale identifier the description-mismatch diagnostic had been pointing at (`prior-as-competitor`, an unrelated rule about default behavior competition).
- [core/funnel + formatters/text]: When the server returns an unrecognized error (`unknown_error` shape), the "Did you see an error?" exit ramp now deep-links to GitHub's new-issue form with the title, a triage-ready body (environment + reproduce skeleton), and a `bug` label prefilled — turning a generic `/issues` link into a one-click filed issue. Known funnel errors (rate limit, payload-too-large) keep the plain `/issues` index because they're usage signals, not bug reports.

### Changed

- [framework/rules]: Promoted `skill-name-matches-directory` to a cross-agent rule (CORE:S:0036). Skill `name` field must be kebab-case across every agent that loads `SKILL.md` entry points.
- [framework/rules]: Promoted `skill-no-readme` to a cross-agent rule (CORE:S:0035). Skill directories must keep all documentation in `SKILL.md` — a sibling `README.md` is never loaded.
- [framework/rules]: Promoted `skill-description-length` to a cross-agent rule (CORE:S:0040). The `description` field must be present in skill frontmatter; the open standard caps it at 1024 characters, with agent-specific caps acknowledged in the rule body.
- [framework/rules]: Promoted `import-depth-within-limit` to a cross-agent rule (CORE:S:0033) following the path-scope-declared supersede pattern. CORE carries a permissive absolute ceiling (max 10) as a sanity check; CLAUDE:S:0010 supersedes with Claude's documented 5-hop `@import` hard limit; CURSOR:S:0002 supersedes with `max: 1` reflecting Cursor's single-level `@filename` model. Codex and Copilot declare `CORE:S:0033` under `excludes:` in their `config.yml` because their instruction files do not honor `@<path>` syntax. Gemini inherits the CORE ceiling unchanged.
- [framework/rules/claude]: Renamed `memory-file-within-200-lines` to `memory-file-within-size-limit` (`CLAUDE:S:0011`) — slug no longer embeds the line number, since the threshold is fundamentally agent-defined. Stays in the CLAUDE namespace: Claude is the only agent with a dedicated `MEMORY.md` file the rule's `match: {type: memory}` can check (Gemini's memory is a section in `GEMINI.md`; Copilot's is system-managed with a 28-day TTL; Codex has none; Cursor's mechanic is undocumented). Promotion to CORE was reverted — it was forward-looking but in practice would have only fired on Claude.
- [framework/rules/claude]: Raised `rule-snippet-length` (`CLAUDE:S:0009`) threshold from 100 to 200 lines and dropped severity from `medium` to `low`. Added `see_also: [CORE:C:0044, CORE:S:0019]` cross-references — when a rule file follows topic-scatter and single-topic-per-section, 200 lines is comfortably enough.
- [framework/rules/copilot]: Renamed `applyto-scope-declared` to `path-scope-declared` for slug consistency with the cross-agent `path-scope-declared` family (Claude `paths:`, Cursor `globs:`, Copilot `applyTo:`). Rule body still describes Copilot's `applyTo:` mechanic; only the slug, title, and H1 heading change.
- [framework/rules/core]: Switched the `source:` URL for the three cross-agent skill rules (`skill-no-readme`, `skill-name-matches-directory`, `skill-directory-kebab-case`) from `code.claude.com/docs/en/skills` to `agentskills.io/specification`. The open standard is the canonical source for skill conventions; Claude's docs reflect the same conventions but aren't the universal reference.
- [core/api_client]: `_lint_remote` now sends the compact wire format by default.

### Fixed

- [core/classification]: Cross-agent rules with `match: {type: scoped_rule}` and `match: {type: skill}` now fire correctly. Agent configs use plural keys (`rules:`, `skills:`) for human readability while rule-side match expressions use the singular concept names; without aliasing, those rules silently never matched any file. A `_FILE_TYPE_MATCH_ALIASES` map applied at `ClassifiedFile` construction normalizes the surface key to the match vocabulary while preserving the literal key for `surfaces.<agent>.<file_type>` lookup. Bandage solution — the proper fix is to align vocabulary in one direction (either agent configs use singular keys or rule-side `match.type` uses plural). Tracked as a follow-up.
- [core/agent_discovery]: `surfaces.<agent>.<file_type>.exclude` patterns now apply across every surface of the agent, not just the surface they were declared on. Two surfaces of the same agent commonly share patterns (e.g. `cursor.rules` and `cursor.bugbot_rules` both glob `.cursor/rules/**/*.mdc`) — declaring an exclude on one previously left the file surfaced from the other. Discovery now collects the union of all per-surface excludes for the agent and applies it once per surface.
- [formatters/text/scorecard]: `compute_surface_scores` relativizes `ruleset_map.files[*].path` against the project root before classification. Absolute paths from the mapper were being tagged `nested` purely because their leading filesystem components inflated the `parts` count, so a project with one root-level `CLAUDE.md` was rendered as `Main (1) ... Nested (1)`. Findings (which already carry relative paths) and the mapper's file list now classify consistently.
- [interfaces/mcp]: Updated `explain` tool example coordinate from `CLAUDE:S:0011` (promoted/renamed) to `CLAUDE:S:0005` so the MCP tool description references a current rule.
- [core/mapper/daemon]: Mapper daemon's 1-hour idle timeout is now opt-in via the `AILS_DAEMON_IDLE_S` env var instead of applied by default. Without the override the daemon stays running until `ails daemon stop` or an explicit kill — matching the user expectation that "background" means "doesn't go away on its own". The previous 1-hour default caused the daemon to terminate between dev sessions, so each subsequent `ails check` paid the cold-start cost.
- [framework/rules/core]: Four server-driven diagnostics that displayed unrelated rules via `ails explain` are now pointed at coherent rules. `description-mismatch` → new `CORE:C:0055` `description-coherence` (was the unrelated `prior-as-competitor`). `overall-strength` → `CORE:C:0053` `ideal-instruction`, the existing composite-rollup rule whose own Limitations describes it as such (was `compound-weakness`, which is per-atom multiplicative, not file-level). `named-coverage` → `CORE:C:0042` `specificity-gap` (was `specificity-shields`, which scopes itself to prose-heavy files; the diagnostic fires regardless of prose). `orphan` stays at `CORE:C:0053` (the existing mapping was correct — `ideal-instruction` Fix bullet #3 names the golden pattern explicitly). Also dropped two dead `RULE_ID_MAP` entries (`cross-conflict`, `cross-repetition`) that were never reachable — cross-file findings carry their own `finding_type` and never go through the diagnostic-label translation.

## 0.5.7

### 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.7)
# Reporails CLI (v0.5.8)

> **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
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ checks:
type: mechanical
check: import_depth
args:
max: 3
max: 5
28 changes: 12 additions & 16 deletions framework/rules/claude/import-depth-within-limit/rule.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ category: structure
type: mechanical
severity: medium
match: {type: main}
supersedes: CORE:S:0033
source: https://code.claude.com/docs/en/memory#import-additional-files
---

# Import Depth Within Limit

Import chains should not exceed 3 levels deep. Deep import hierarchies increase context loading time and create fragile dependency chains — a change to a deeply nested file can silently break the import resolution of files several levels up.
Claude Code's `CLAUDE.md` `@import` chains have a documented hard limit of **5 hops**. Imports beyond depth 5 are not resolved — content past the cutoff is silently dropped. This stub supersedes the more permissive CORE ceiling with Claude's actual documented threshold so the agent-specific cap is enforced when the project is scanned with `--agent claude` or when Claude is auto-detected.

## Antipatterns

- **Transitive chaining.** `CLAUDE.md` imports `docs/setup.md`, which imports `docs/details/config.md`, which imports `docs/details/advanced/tuning.md`, which imports a 5th file. The chain exceeds 3 levels and any broken link silently drops content.
- **Circular imports.** File A imports B, B imports C, C imports A. The resolver must detect and break the cycle, but the author likely didn't intend it.
- **Transitive chaining past 5.** `CLAUDE.md` imports `docs/setup.md`, which imports `docs/details/config.md`, and the chain continues past depth 5. Claude Code stops following imports at the 5-hop boundary and the deeper content is not in context.
- **Circular imports.** File A imports B, B imports C, C imports A. Claude Code's resolver detects and breaks the cycle, but the author likely didn't intend it.
- **Import as organization substitute.** Using `@import` chains to simulate a file hierarchy instead of structuring content into focused files that the agent loads directly.

## Pass / Fail
Expand All @@ -26,12 +27,14 @@ Import chains should not exceed 3 levels deep. Deep import hierarchies increase
~~~~markdown
<!-- CLAUDE.md (depth 0) -->
@import docs/testing.md
@import docs/formatting.md

<!-- docs/testing.md (depth 1) -->
@import docs/fixtures.md
@import docs/style/formatting.md

<!-- docs/fixtures.md (depth 2) — within limit -->
<!-- docs/style/formatting.md (depth 2) -->
@import docs/style/fixtures.md

<!-- docs/style/fixtures.md (depth 3) — well within Claude's 5-hop limit -->
# Test Fixtures
Use `conftest.py` for shared setup.
~~~~
Expand All @@ -41,17 +44,10 @@ Use `conftest.py` for shared setup.
~~~~markdown
<!-- CLAUDE.md (depth 0) -->
@import docs/overview.md

<!-- docs/overview.md (depth 1) -->
@import docs/details.md

<!-- docs/details.md (depth 2) -->
@import docs/internals.md

<!-- docs/internals.md (depth 3) -->
@import docs/deep/config.md ← depth 4, exceeds limit
<!-- docs/overview.md → docs/details.md → docs/internals.md →
docs/deep/a.md → docs/deep/b.md → docs/deep/c.md ← depth 6, exceeds Claude's 5 -->
~~~~

## Limitations

Counts import depth from the root instruction file. Does not evaluate whether deep imports are justified by project complexity. Only follows `@import` syntax — other inclusion mechanisms are not detected.
Counts depth from the root `CLAUDE.md`. Does not evaluate whether the chain is justified by project complexity. Only follows `@<path>` syntax — other inclusion mechanisms are not detected. The 5-hop ceiling is Claude Code's documented hard truncation; future Claude Code versions may revise it.
50 changes: 0 additions & 50 deletions framework/rules/claude/memory-file-within-200-lines/rule.md

This file was deleted.

50 changes: 50 additions & 0 deletions framework/rules/claude/memory-file-within-size-limit/rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
id: CLAUDE:S:0011
slug: memory-file-within-size-limit
title: Memory File Within Size Limit
category: structure
type: mechanical
severity: medium
match: {type: memory}
source: https://code.claude.com/docs/en/memory#auto-memory
---

# Memory File Within Size Limit

`MEMORY.md` should stay under the host agent's memory truncation threshold. Claude Code loads only the first 200 lines or 25KB of `MEMORY.md` (whichever comes first); content past either cutoff is silently dropped from the agent's context. Other agents that adopt a memory surface may set different caps. Keep the index concise — store detail in linked memory files, not inline.

## Antipatterns

- **Inline memory content.** Writing full memory entries directly in `MEMORY.md` instead of linking to separate `.md` files. Each entry should be a one-line pointer, not a paragraph.
- **Stale accumulation.** Never pruning old or outdated memory entries. Over time, `MEMORY.md` grows past the threshold and the newest entries (at the bottom) are the ones truncated.
- **Verbose link descriptions.** Writing multi-line descriptions for each memory link instead of keeping each entry under ~150 characters as a scannable index.

## Pass / Fail

### Pass

~~~~markdown
# Memory

- [User role](user_role.md) — Senior engineer, Go + React
- [Testing preference](feedback_testing.md) — Integration tests, no mocks
- [Deploy process](project_deploy.md) — CI/CD via GitHub Actions
~~~~

### Fail

~~~~markdown
# Memory

## User Profile
The user is a senior software engineer with 10 years of experience
in Go and 2 years in React. They prefer integration tests over unit
tests because of a past incident where mocked tests passed but the
production migration failed. Their deploy process uses GitHub Actions
with a staging environment...
[... 250 lines of inline content]
~~~~

## Limitations

The 200-line limit enforced here is Claude Code's documented `MEMORY.md` truncation threshold; the parallel 25KB byte cap (whichever comes first per Claude's docs) is not enforced because line_count is the simpler signal. The rule lives in the CLAUDE namespace because the file-system mechanic it checks (a dedicated `MEMORY.md` file under `~/.claude/projects/<project>/memory/`) is Claude-specific: Gemini's "memory" is a section appended to user `GEMINI.md` rather than a separate file; Copilot's memory is a system-managed GitHub repo setting with a 28-day TTL, not on disk; Codex has no memory mechanic; Cursor's memory mechanic is undocumented. If future Claude Code versions change the threshold, or another agent adopts a comparable file-system memory surface, the rule can be promoted to CORE with per-agent supersedes. Counts total lines including blank lines and headings.
2 changes: 1 addition & 1 deletion framework/rules/claude/rule-snippet-length/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ checks:
type: mechanical
check: line_count
args:
max: 100
max: 200
Loading
Loading