Repository navigation
AGENTS.md: the absolute rules; delete CLAUDE.md #4862
Copy link
Copy link
Closed
Labels
agent guidanceRules, skills, and quality gates for agentsRules, skills, and quality gates for agentsdocumentationImprovements or additions to documentationImprovements or additions to documentationv2
Milestone
Description
Part of the agentic software factory tracker #4858, Wave 2. Proposed as S1 in docs/agent-guidance-inception.md (PR #4861) §9, from #4859.
Depends on
None beyond #4859. Can run in parallel with the rest of Wave 2.
Scope
- Write
AGENTS.mdat the repo root, starting from the Inspector'sAGENTS.mdonv2/main. §6 of the inception doc lists what to keep, rewrite, drop and add. - It holds only rules that are true on the day it merges. If a rule's machinery doesn't exist yet (
validate,local:gate, per-file coverage), the sub-issue that builds that machinery adds the rule. - Map every
CLAUDE.mdsection per §4 of the doc:- project overview
- monorepo structure
- build and test commands for each language
- code style for TypeScript and Python
- contributing guidelines
- the CI/CD pipeline (dropped as derivable)
- the MCP protocol reference
- key patterns:
registerTools/registerResources/registerPrompts, tool annotations, transports (SSE deprecated), the PR template checklist
- Map every Adopt AGENTS.md (with CLAUDE.md pointer) modeled on the inspector repo #4473 decision marked S1 in §5. The board ID table goes to
board-ops(Part 6), not here. - Settle
src/everything/AGENTS.md: fold its generic rules into the root file, keep its server-specific extension guidance next to the server, and check whether a nestedAGENTS.mdis loaded at all. - Adopt the Inspector's purpose-header rule without a bulk migration. New files, and files a PR substantially rewrites, open with a comment stating their purpose and rationale. That's the first comment in the file, after any shebang:
#!/usr/bin/env nodemust stay on line 1 of an executable entry point. - State "every PR references an issue" with an explicit temporary exception for Dependabot PRs. Dependabot still opens issue-less PRs until Part 15 (Replace Dependabot PRs with issue-filing sweeps; SDK watch; the factory overview #4874) retires them, and Part 15 removes the exception.
- Delete
CLAUDE.md. No@./AGENTS.mdpointer file stays behind.
Acceptance criteria
-
AGENTS.mdexists at the root.CLAUDE.mdis deleted and no pointer file remains. - Every §4 and §5 row marked S1 is present.
- The PR shows a fresh Claude Code session following a rule that exists only in
AGENTS.md. - The skills index lists only skills that exist; each later skill PR adds its own row.
Branch
Targets v2/main. Closes #N won't auto-close an issue on a non-default branch, so close this one by hand on merge and move the card to Done.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
agent guidanceRules, skills, and quality gates for agentsRules, skills, and quality gates for agentsdocumentationImprovements or additions to documentationImprovements or additions to documentationv2
Activity
cliffhall commentedon Sep 29, 2026
Rules from #4865 (Python gate parity, PR #4893) for
AGENTS.md, handed over per §9 since #4862 owns that file:Python instructions
uv, neverpip. Every Python server (src/fetch,src/git,src/time) is a standalone uv project with its ownpyproject.toml,uv.lockand.python-version. Install withuv sync --locked --all-extras --devfrom the server's directory; run tools withuv run --frozen <tool>. Python ≥ 3.10.npm run validate:pyis the Python gate, and it runs every Python server. For one server:node scripts/validate-py.mjs <server>. Each server runs the same fail-fast chain:uv sync --locked,ruff check .,ruff format --check .,pyright,pytest,uv build. CI'spython.ymlruns the same script per matrix package, so the local command and CI cannot drift.uv run ruff format .in each server you touched before committing. CI fails on aruff checkorruff format --checkfinding exactly as on a failing test. Ruff has no warning tier: a finding is a finding.ignore/excludeentries, pyrightexcludes or disabled rules to make a check pass. A genuinely necessary inline waiver (# noqa: <code>,# pyright: ignore[<rule>]) names the specific rule and carries a one-line justification.pyproject.toml.validate-py.mjsdiscovers servers undersrc/rather than listing them, and CI's matrix discovers them the same way; a new server must ship with tests (pytestexits non-zero when it collects none).pyright-clean type hints on all new code; async/await withpytest-asynciowhere a server is async; follow each server's existing module layout.dist/and.venv/are excluded by ruff's and pyright's defaults — keep it that way rather than widening a scope to cover them.cliffhall commentedon Sep 29, 2026
Rules handed over from #4863 (PR #4895) for
AGENTS.md, per the wave-2 plan: #4863 does not createAGENTS.md. They belong under Maintenance Rules. Whichever PR merges second reconciles.Maintaining the skills
Skills are conditional — a skill's body loads only when it is invoked — so a
skill that stops being reachable loses behavior silently. These rules keep
that from happening. How to write a description that fires, and eval cases that
measure it, is
docs/skill-authoring.md.npm run verify:skillsmust pass. CI runs it in theroot-guardsjob of.github/workflows/typescript.yml(the rootvalidatepicks it up onceTypeScript workspace gate: Prettier, ESLint, root validate, CI #4864 builds that). It parses each
SKILL.md's frontmatter the way ClaudeCode does and fails on anything that would strip the metadata — most
importantly malformed YAML, which loads the body with an empty
description, so
/skill-namestill works and a manual spot check passeswhile the skill can never auto-fire again. Quote any description containing
#or:. An unquoted colon is enough to break the YAML; an unquoted#is read as a comment and truncates the description silently from that
point on, leaving a non-empty string every other check accepts.
---is the file's firstline — no BOM, no leading blank line.
The authoritative schema check,
claude plugin validate, runs as its ownguaranteed step,
npm run verify:skills:cli, in the same CI job (and inlocal:gateonce Add local:gate, pre-push-gate skill #4871 builds it). It uses an installed CLI only when itmatches the pin exactly, and otherwise fetches the pinned package with
npx -y: a newer local CLI is a different schema from CI's.disable-model-invocationis required on every skill (true= reachableonly by name,
false= the model may fire it). Default tofalse.Invoking a skill has no side effects — it loads instructions — and work is
usually asked for in prose ("create a PR for #N"), where a
trueskill isabsent from the listing and cannot be reached at all. Reserve
truefor aprocedure that is only ever started deliberately (a release). A skill that is
background knowledge rather than an action also sets
user-invocable: false.trueskill cannot be reached from another skill's body either: apointer to it from a model-invoked skill is a dead end for the model.
pathsis not a free win. Measured in the Inspector, adding itroughly halved how often the same skill fired from a conversational prompt,
and a prompt-only eval can never exercise a path trigger, so shipping
pathsmeans shipping an untestable claim. Use it only when the skill is useless
outside the matched files, and state that trade-off in the PR.
evals/evals.json— at least five positives, plus negatives(
"expect": null).verify:skillsenforces both. Five is a floor forbreadth, not variance: each prompt is scored on its own
passes / RUNS,so more prompts cover more of the ways someone reaches the skill rather than
steadying any rate.
npm run skills:evalruns the cases against Claude, andagainst GitHub Copilot with
AGENT=copilot; it spends metered model callsand reports a hit rate, so it is deliberately not a gate. Run the whole
suite after adding a skill, flipping an invocation mode, or editing a
model-invoked description — adding a skill can lower the trigger rate of the
ones already there. A prompt whose answer is already in
AGENTS.mdis not atrigger case: the model answers without the skill and the case reads as a
miss.
name and description of every model-invoked skill into context, truncates the
listing when it overflows, and drops the least-invoked entries first —
exactly the skills that must fire on their own.
verify:skillsprints thisrepo's share against the budget in
scripts/lib/skill-manifest.mjs(
LISTING_BUDGET, 4,000 characters) and fails when it is exceeded. Raise thebudget deliberately or tighten a description; each entry is capped at 1,536
characters regardless, so put the key use case first.
.claude/skills/directories below the working directory donot load at startup. Keep every skill in the repo-root
.claude/skills/.verify:skillspasses an empty.claude/skills/under theEMPTY_SKILLS_BOOTSTRAPallowance. The first PRthat adds a skill (#4866, #4867, #4870, #4871 or #4872, whichever merges first)
sets it to
false, deletes.claude/skills/.gitkeep, and adds its row to theskills index;
verify:skillsfails until it does.cliffhall commentedon Sep 29, 2026
AGENTS.md rules from #4864 (Part 4, TypeScript workspace gate), handed to #4862. PR #4896 builds the machinery. Per §9 S3, these rules belong in
AGENTS.md, which this issue owns, so here is the text I would add. It fits as a new section after TypeScript instructions, or folded into the Inspector-template sections "Build output is never a gate target" and "Lint has no warning tier". Whichever PR merges second reconciles the two.Format, lint and validate
npm run formatat the repo root before committing. It runs the root Prettier (format:root, the root tooling) and every workspace'sformat.format:checkis the non-fixing form the gate runs, and CI fails on any unformatted file, so run the fixer first rather than letting the check catch it. Prettier is pinned exactly at the root, and the formatted surface is JS/TS source (*.{ts,mts,cts,js,mjs,cjs}); everyprettierscript passes the root.prettierignorewith--ignore-path, so the workspaces (which run from their own directories) read the same ignore list as the root.npm run validateis the inner loop. Each TypeScript server'svalidaterunsformat:check→lint→typecheck→build→testfor that package only (npm run validate -w src/<server>). The rootvalidaterunsvalidate:guards(the root tooling's format and lint,verify:format-coverage,verify:skills,verify:typecheck-coverage,verify:dep-lockstep,test:scripts) and thennpm run validate --workspaces. In CI, eachtypescript.ymlmatrix leg runs only its own package'svalidate, and the root-guards job runsvalidate:guards.testis the fast run;coverageis the instrumented one.lintscript runs ESLint with--max-warnings 0, so a warning fails the gate exactly as an error does. The one config is the rooteslint.config.js: type-aware for the servers, with@typescript-eslint/no-floating-promisesaterror. Every promise is awaited, returned, ended with.catch(…), or discarded withvoidplus a one-line comment saying why the caller cannot hold it. A rule you intend to enforce is set toerror, not left atwarn, so the editor squiggle reads right too.dist/,coverage/andnode_modules/are excluded ineslint.config.js'sglobalIgnoresand in the root.prettierignore, and each workspace'stsconfig.test.jsonexcludes them. When a build starts writing somewhere new, add it to those ignore lists in the same change.lintorformat:checkpass. If a rule genuinely must be waived on one line, use its inline disable comment with a one-line justification.tscpass. Each workspace'stypecheckrunstsc -p tsconfig.test.json, which covers the whole workspace including the tests the buildtsconfig.jsonleaves out.verify:typecheck-coveragefails when a tracked file falls outside it, andverify:format-coveragefails when a tracked source file matches noformat:checkglob. A new file that trips either goes into the rightincludeor glob, never into an exemption.typescript,vitest,@vitest/coverage-v8,prettierand@types/nodeare each declared with one identical range everywhere they are declared, or only once at the root (verify:dep-lockstep). Bump one in every manifest in the same change, thennpm installat the root.[-]Agentic software factory Part 2: AGENTS.md: the absolute rules; delete CLAUDE.md[/-][+]AGENTS.md: the absolute rules; delete CLAUDE.md[/+]docs: add AGENTS.md with the repo's rules; delete CLAUDE.md