Why this rule
An agent that writes code in a language with no automated tests has no way to verify its own work. Tests are the agent’s exit condition — without them it can only produce a diff, not a proof. The AGENTS.md standard treats the test command as one of the highest-value pieces of context an agent can have. AE-TEST-001 checks that there is actually something to run — before AE-AUTO-001 checks that the command is discoverable.What triggers it
Charter detects active languages from manifest files committed to the repo:
A language is only active when its manifest is present and the repo contains at least one non-test source file for that language outside tooling directories (
scripts/, vendor/, node_modules/, dist/, build/).
For each active language, Charter checks whether at least one test file exists using standard naming conventions:
Files in directories named
test/, tests/, spec/, or __tests__/ also count, regardless of language.
Charter detects active languages by manifest, not by line count. A
go.mod with one .go source file (non-test) counts as an active language and requires at least one test file.Examples
- Failing
- Passing
A Go module with source files under A TypeScript project with source files but no test files:
internal/ but no *_test.go file anywhere:How to fix
Add a minimal test file for each active language that Charter flags. The test does not need comprehensive coverage — Charter checks for presence, not coverage percentage or pyramid shape.1
Identify the active languages
Run
charter doctor or charter explain AE-TEST-001 to see which languages are flagged and which manifest triggered each one.2
Add a minimal test file
Create at least one test file using the language’s standard naming convention. A single passing test satisfies the rule.
3
Verify the finding clears
Run
charter doctor again to confirm the finding no longer appears.Score impact
High (−10 per finding). No hard cap — caps are reserved for raw-secret and Blocker findings. If multiple active languages all lack tests, each fires a separate finding instance. See Scoring and caps.
Edge cases
Docs, config, and tooling-only repos
Docs, config, and tooling-only repos
AE-TEST-001 does not fire when no recognized code language is active. A repo containing only Markdown, YAML config, or tooling scripts is not penalized.
Embedded web assets in Go binaries
Embedded web assets in Go binaries
A
//go:embed’d web asset (e.g. a report.js embedded into a Go binary) is a bundled resource, not a language surface. It does not activate JavaScript/TypeScript even when a build-tooling package.json is present.Stray secondary-language files
Stray secondary-language files
A lone
*.rb Homebrew formula with no Gemfile, or a stray *.py helper with no pyproject.toml, is not an active language and does not require tests.Rust inline tests
Rust inline tests
Rust inline unit tests count via the
#[cfg(test)] / #[test] content signal — no separate tests/ directory is required.Related rules
AE-AUTO-001
Requires a discoverable command to run the tests that this rule checks for.
AE-CI-002
Requires CI to run those tests on every pull request.