Imported from SemiAnalysisAI/InferenceX (
AGENTS.md). Install upstream withnpx skills add SemiAnalysisAI/InferenceX. Copyright stays with the author.
AGENTS.md
Guidance for AI agents working with InferenceX.
Start here
- Start every task with
docs/index.md. Choose the one focused guide that matches the task. Do not load every documentation page. - Repository source, schemas, workflows, launchers, and collectors are authoritative. If documentation disagrees with implementation, follow the implementation and update the nearest English guide plus its Chinese counterpart.
- Read
CONTRIBUTING.mdbefore opening or reviewing a PR or changing review, sweep, or merge policy. - Read
KLAUD_DEBUG.mdbefore debugging a Klaud-Cold orclaude/*image-bump PR.
Agent-specific policy
- Repository skills are canonical under
.agents/skills/. Add or update skills there..claude/skills/contains compatibility symlinks for Claude discovery. - PR and issue titles, descriptions, and human-authored PR comments must include English and natural Simplified Chinese. Titles use
<English title> / <中文标题>. In bodies and comments, keep English visible and put Chinese in one collapsed<details><summary>中文</summary>section. Keep code, commands, logs, stack traces, model names, hardware SKUs, framework names, flags, and identifiers unchanged. The exact CODEOWNER sign-off template is English-only. Seedocs/documentation-procedures.mdand.github/AGENT_OPERATIONS.md. - Klaud Cold reports: Follow the compact body/comment templates in
docs/klaud-reporting.md, including cleanup and completion reports. - Commit subjects use conventional English style, while commit bodies include the Chinese translation. Contributor-facing docs use English as the source version and ship with a synchronized
_zh.mdpage and language switcher. - Follow the nearest existing pattern. Python uses typed signatures and strict Pydantic schemas. YAML uses kebab-case fields. Shared benchmark Bash behavior belongs in
benchmark_lib.sh, with parameters passed through environment variables.
Test quality
The one rule: a test must exercise the real implementation with concrete inputs and assert on what it computes, returns, writes, or raises. A test that inspects the code, the repo, or a config file instead of running behavior is not a test and must be deleted. These rules are mandatory for every test added, modified, or reviewed in this repository. When in doubt, delete the test.
Forbidden: tests about the code rather than its behavior
Never write, and always delete on sight, a test that does any of the following:
- Reads source text and asserts on it. Opening a
.sh,.py,.yml,.yaml,.cjs, or.mdfile and asserting that a string, flag, regex, command, or line is present or absent, counting occurrences, or checking line order. This includes launchers, workflow files, skill files, and docs. Grepping is not testing. - Parses source structure. Using
ast.parse,inspect.getsource,inspect.signature,hasattr,callable,__doc__, or import-succeeds checks to assert that a function, class, constant, argument, or flag exists or has a given shape. - Git-greps the repo. Asserting which files contain a literal, how many files match, or that a pin appears in exactly N places.
- Pins checked-in config or data. Asserting the contents of a recipe, master config,
runners.yaml,platform_config.json, a registry dict, an enum, an image tag, a SHA, a port number, or the current count of recipes, SKUs, backends, or models. Validate config through the real validation code with controlled inputs instead. - Is tautological. Asserting a constant equals its own literal; asserting a dict or fixture equals what the test just built; asserting only that a mock was called with the arguments the test itself passed; or computing the expected value with the same helper, formula, or algorithm the test is supposed to check.
- Reimplements the code under test. Any parser, filter, jq/YAML expression, argparse tree, formula, or state machine copied into the test file so the test can run against the copy. This also covers "mirror" parsers and "reference specs" cross-checked against a second in-test implementation.
- Tests the test infrastructure. Tests of fixtures, conftest helpers, in-test expression evaluators, or "this test has teeth" self-checks.
- Is smoke-only. Module imports,
--helpexits 0, or "does not raise" with no assertion on output. - Duplicates a covered path. Several tests that reach the same branch with trivially different inputs. Keep one, or use
pytest.mark.parametrize/subTest. A second test is justified only by a distinct branch, error path, or boundary.
Required: what every kept test looks like
- Feeds small, controlled inputs into the real function, CLI, or script and asserts on the computed output, written artifact, exit code, or raised error.
- Uses expected values worked out independently by hand, never derived by calling the implementation or its helpers.
- Covers a specific branch, boundary, malformed input, or failure path that no other test already covers.
- Mocks only external collaborators (network, GitHub, Slurm, clocks, GPUs), never the behavior under test. Shell scripts are tested by running them with stubbed binaries on
PATHand checking what they produced, not by reading their text. - Would fail on a plausible regression in observable behavior, and would not fail on a harmless refactor, a rename, or the addition of a valid recipe or SKU.
Before adding or approving a test, answer all four
- Which line of the real implementation does this run, and what bug in it would make the assertion fail?
- Would this test still pass if the code were rewritten with identical behavior? If not, it is testing structure and must go.
- Would this test fail because someone added a recipe, bumped an image tag, or reworded a comment? If yes, it is pinning config or source and must go.
- Does an existing test already reach this branch? If yes, extend it or drop the new one.
Deleting a test that fails these questions needs no replacement. Do not preserve test counts. See the testing guide for the reasoning and Randy Coulman's Tautological Tests for the distinction between independent expectations and assertions that repeat the implementation.
Non-negotiable benchmark invariants
- Every priority-scheduled benchmark job on a self-hosted cluster must request exactly one
nodes:Nlabel, whereNis the positive integer number of physical Slurm nodes required. Single-node jobs usenodes:1; generated multi-node jobs must forward their computednode-count. A queued job missing this label is ineligible for priority scheduling, and labels cannot be added retroactively, so fix the source branch and dispatch a new run. - Every change that can affect benchmark performance and every recipe addition or modification requires a new
perf-changelog.yamlentry. The file is append-only and byte-sensitive. Preserve all existing bytes and separator whitespace, and append only at the tail. - Multi-node srt-slurm changes update the recipe YAML and matching master config together. For image bumps,
model.containermust equalimage. - Every
*_mtp.shpasses--use-chat-templatetorun_benchmark_serving. - Benchmarks create no new directories under
/workspace. Root containers must not leave root-owned files in shared AMD runner workspaces. - Generated configuration is not runtime proof. Run the narrowest local check, then the applicable smoke, sweep, or eval procedure from
docs/procedures.md.
All repository maps, task routes, commands, schemas, sweep semantics, artifact contracts, recovery steps, and detailed conventions live behind docs/index.md.