Meu-Agent / tests
AGENTS.md0 starsChanged 10 days agoMITView on GitHub
Applies on top of the root AGENTS.md. Read it before adding or changing any test. ALWAYS use scripts/run_tests.sh, never bare pytest. It enforces CI parity: credential vars unset, TZ=UTC, LANG=C.UTF-8, HERMES_HOME → temp dir, and per-file subprocess isolation via scripts/run_tests_parallel.py (no xdist; workers scale with CPU count) so module-level dicts/ContextVars cannot leak between files. Direct pytest on a big machine with API keys set has caused repeated "works locally, fails in CI" incidents (and the reverse). Prepare a test interpreter…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository57 other files it gives its agents.
- agent/AGENTS.mdAGENTS.md
- AGENTS.mdAGENTS.md
- cron/AGENTS.mdAGENTS.md
- gateway/AGENTS.mdAGENTS.md
- hermes_cli/AGENTS.mdAGENTS.md
- hermes_platform/AGENTS.mdAGENTS.md
- plugins/AGENTS.mdAGENTS.md
- pm/AGENTS.mdAGENTS.md
- skills/AGENTS.mdAGENTS.md
- tools/AGENTS.mdAGENTS.md
- tui_gateway/AGENTS.mdAGENTS.md
- web/AGENTS.mdAGENTS.md
- apple-notesSkill
- apple-remindersSkill
- findmySkill
- imessageSkill
- claude-codeSkill
- codexSkill
- computer-useSkill
- hermes-agentSkill
- architecture-diagramSkill
- ascii-videoSkill
- baoyu-infographicSkill
- claude-designSkill
- humanizerSkill
- local-pngSkill
- manim-videoSkill
- p5jsSkill
- popular-web-designsSkill
- songwriting-and-ai-musicSkill
- sdlc-reviewSkill
- email-inbox-triageSkill
- himalayaSkill
- youtube-contentSkill
- obsidianSkill
- document-to-action-itemsSkill
- google-workspaceSkill
- mapsSkill
- meeting-action-itemsSkill
- microsoft-officeSkill
- pdfSkill
- product-price-monitorSkill
- teams-meeting-pipelineSkill
- weekly-review-planningSkill
- arxivSkill
- competitor-news-monitorSkill
- grounded-citationsSkill
- xurlSkill
- codebase-inspectionSkill
- dogfoodSkill
- githubSkill
- requesting-code-reviewSkill
- simplify-codeSkill
- spikeSkill
- systematic-debuggingSkill
- test-driven-developmentSkill
- blocked-page-recoverySkill
The file
We split this AGENTS.md into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 146
Do extract the logic into a pure/DI-testable function and call it:
- Distinctive: line 153
If the logic lives inline in a god-file and extraction feels disruptive, that is the signal to extract, not to regex around it.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
tests/ — how Hermes tests are written and run
Applies on top of the root AGENTS.md. Read it before adding or changing any test.
Running tests
ALWAYS use scripts/run_tests.sh, never bare pytest. It enforces CI parity: credential
vars unset, TZ=UTC, LANG=C.UTF-8, HERMES_HOME → temp dir, and per-file subprocess
isolation via scripts/run_tests_parallel.py (no xdist; workers scale with CPU count) so
module-level dicts/ContextVars cannot leak between files. Direct pytest on a big machine
with API keys set has caused repeated "works locally, fails in CI" incidents (and the reverse).
Prepare a test interpreter with the checkout's bootstrapped Python:
python -m pm.build_env --source . --out .venv --group dev --group testThis is a fresh build, not an in-place sync. If the disposable output exists,
stop its processes and intentionally remove it before regeneration. The runner
clears PYTHONPATH, so PM shell activation alone does not supply pytest. For a
fresh output outside the checkout, set HERMES_PYTHON to its interpreter.
scripts/run_tests.sh # full suite
scripts/run_tests.sh tests/gateway/ # one directory
scripts/run_tests.sh tests/agent/test_foo.py -k test_x # runner is file-granular; -k narrows
scripts/run_tests.sh -v --tb=long # pytest flags pass through- Flake policy: a failing FILE is retried once in a fresh subprocess (
--file-retries;HERMES_TEST_FILE_RETRIES=0disables); a worker killed by signal or the file timeout is never retried (relaunching a runaway doubles the damage). Pass-on-retry is green but printed under⚠ FLAKYwith both outputs — a bug to fix, not noise. Timing tests must not assume a quiet runner: wall-clock bounds ≥ 2s, event-based sync, noassert not _wait_until(...)races. A new non-zerotime.sleep/asyncio.sleepin a test fails the ratchet (HX013): wait on an Event or poll withtests.waiting.wait_until/async_wait_until. - Placement mirrors the source tree. A test lives in
tests/<top-level source dir>/(tests/hermes_cli/,tests/agent/,tests/hermes_state/,tests/gateway/relay/, ...); installer/updater script tests undertests/scripts/{install,desktop_update}/. Only tests of root-level modules (batch_runner,utils,hermes_constants, packaging) sit directly intests/. No issue numbers in filenames — cite the issue in the module docstring (test_89315_x.py→test_x.py, "Regression for #89315"). - Placement (CI lanes):
scripts/ci/classify_changes.pypicks jobs by changed files. A Python test asserting aboutpackage.json,package-lock.json,tsconfig.json, or.ts/.tsx/.js/ .mjs/.cjssources will not run on a JS-only PR (green on PR, red onmainwhere the classifier fails open). Such tests belong in the vitest suite, nottests/*.py. - Tests must not write to
~/.hermes/. The autouse_isolate_hermes_homefixture intests/conftest.pyredirectsHERMES_HOME; never hardcode~/.hermes/in tests. Profile tests also mockPath.home()so_get_profiles_root()/_get_default_hermes_home()stay in the temp dir (pattern:tests/hermes_cli/test_profiles.py):
Tests that@pytest.fixture def profile_env(tmp_path, monkeypatch): home = tmp_path / ".hermes"; home.mkdir() monkeypatch.setattr(Path, "home", lambda: tmp_path) monkeypatch.setenv("HERMES_HOME", str(home)) return homepatch.object(Path, "home", ...)must ALSO setHERMES_HOME— code reads the env var, notPath.home()/.hermes.
Don't fake the host OS
Behaviour that genuinely differs per host is tested ON that host with @pytest.mark.platforms("linux")
/ platforms("macos") / platforms("windows"), never by patching sys.platform. Host-independent things stay
unmarked: pure functions that take the platform as data (hidden_windows_child_options(opts,
is_windows=True)) and declaration/packaging invariants ("pyproject declares tzdata with a
sys_platform == 'win32' marker"). Setting a module-level IS_WINDOWS flag and calling
windows_detach_flags() IS a fake. The line: if the test needs the interpreter to believe it
is on another OS to pass, it belongs on that OS. A test that walks several platforms in
sequence is split — host-native arm on Linux, other arms as their own marked tests.
One marker per test, with any number of spec strings (any-of semantics) plus
optional arch filters. To gate on several OSes, pass several specs to ONE
marker — never stack several platforms() decorators on one test (the
conftest rejects that at collection):
@pytest.mark.platforms("linux", "macos") # ONE marker, two specs: runs on either
def test_posix_signal_path(): ...Other single-marker forms (each is a complete marker on its own):
platforms("windows") (native Windows only), platforms("not macos")
(anywhere except macOS), platforms("windows", arch="arm64") (native Windows
on arm64), platforms("posix") (Linux or macOS).
Specs: linux, macos, windows, posix, any, and not <spec>.
The historic linux_only / macos_only / windows_only markers have been
fully replaced — platforms is the only host-gating marker in the tree.
Live Windows process-topology E2E: the wine2e lane. For claims about
real Windows process behavior that mocks cannot reproduce (venv-holder
scans, process-tree parentage, launcher/worker chains, detach semantics),
there is an on-demand workflow windows-venv-e2e.yml that runs
tests/hermes_cli/test_venv_holder_windows_live.py on a real
windows-latest runner — spawning actual processes and driving the real
detection code, no mocked psutil. It fires ONLY on pushes to wine2e/**
branches (inert on PRs and main; costs nothing on normal work). The proven
workflow: write probes that pin CORRECT behavior, push to a wine2e/
branch to reproduce the bugs live on unfixed code, build the fix, iterate
until the lane is green, then open the PR — the live receipt on the exact
head is the Windows proof reviewers ask for. Extend the live suite when
touching that subsystem; assert against the gateway ANCESTOR found by
argv, not the direct parent (the venv shim makes every spawn a
launcher/worker chain).
Use the marker, never a bare skipif. scripts/ci/list_os_marked_tests.py
decides which files an OS lane imports by resolving the quoted specs inside
platforms(...) ("posix" reaches the macOS lane, "not linux" reaches
both others), and the lane then selects with -m platforms while the
conftest's per-test host skips do the actual gating. A test gated with
@pytest.mark.skipif(sys.platform != "win32") therefore runs on no host at
all, silently — it is never imported by the lane that would run it, and the
full-suite lanes skip it. skipif(sys.platform == "win32") becomes
platforms("posix"); a non-host condition (os.geteuid() == 0) stays a
separate skipif beside the marker. A misspelt spec is a collection error,
not a skip. Don't stack a module-level pytestmark =
platforms(...) on a file whose tests carry their own host marker — the
conftest hard-rejects tests carrying two platforms() markers (a test
skipped on every host, reported green everywhere).
Equally, don't pytest.skip() the non-host rows of a @parametrize over
platforms — split it into one marked test per OS, or only the host's row ever
executes.
Don't write change-detector tests
A change-detector fails whenever data expected to change is updated — model catalogs,
_config_version, enumeration counts, hardcoded model lists. It adds no coverage and taxes
every routine update. Don't: assert "gemini-2.5-pro" in _PROVIDER_MODELS["gemini"],
assert DEFAULT_CONFIG["_config_version"] == 21, assert len(models) == 8. Do: assert
"gemini" in _PROVIDER_MODELS and len(_PROVIDER_MODELS["gemini"]) >= 1 (plumbing works);
assert raw["_config_version"] == DEFAULT_CONFIG["_config_version"] (migration reaches
latest); assert not (set(moonshot_models) & coding_plan_only_models) (no leak); every
catalog model has a context-length entry (relationship). If it reads like a snapshot, delete
it; if it reads like a contract between two pieces of data, keep it. Reviewers reject new
change-detectors; authors convert them before re-review.
Never read source code in tests
A test that reads a .py/.ts/.tsx file's text tests the shape of the source, not
behavior — banned outright. It passes when the implementation is subtly broken (regex matches
a mis-wired call site) and fails on correct refactors; it can't run against bundled/minified
artifacts; it blocks structural cleanup; it gives false confidence. Don't
fs.readFileSync('main.ts') + assert.match(source, /spawn\(...hiddenWindowsChildOptions/).
Do extract the logic into a pure/DI-testable function and call it:
export function hiddenWindowsChildOptions(options = {}, isWindows = process.platform === 'win32') {
if (!isWindows || 'windowsHide' in options) return options
return { ...options, windowsHide: true }
}If the logic lives inline in a god-file and extraction feels disruptive, that is the signal to extract, not to regex around it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

