Repository navigation
Docs: split AGENTS.md so it stops being silently truncated - #3284
Merged
Merged
Conversation
AGENTS.md was 135,147 bytes. OpenAI Codex reads a project doc up to project_doc_max_bytes, default 32768 (codex-rs/config/defaults.toml), and overflow is a hard mid-file byte truncation whose only signal is a tracing::warn! below the level `codex exec` prints at. At 4.1x that budget a Codex user was getting roughly the first quarter of the file and no indication the rest existed. The budget is also a running total across the whole root-to-cwd chain, not a per-file allowance. This is a move, not an edit. The root file is now 23,012 bytes and holds what every agent needs before its first edit — build and test commands, the Release-only rule, the branch to target, the architecture map, the conventions that apply everywhere, and a triggered index of the rest. Everything else moved verbatim into an AGENTS.md beside the code it governs, each far under the cap: AGENTS.md 23,012 Jint/AGENTS.md 25,396 Jint/WebApi/AGENTS.md 19,986 Jint/Native/Object/AGENTS.md 18,267 Jint/Runtime/Modules/AGENTS.md 12,891 Jint.Benchmark/AGENTS.md 12,541 Jint/Runtime/Interpreter/AGENTS.md 9,467 Jint/Constraints/AGENTS.md 7,763 Jint.Tests/Wpt/AGENTS.md 5,466 Jint/Runtime/Interop/AGENTS.md 5,404 Jint/Extensions/AGENTS.md 4,041 Jint.Tests.Test262/AGENTS.md 3,623 Jint/Native/AGENTS.md 2,783 Jint.Tests.PublicInterface/AGENTS.md 1,205 Four gotchas stay in the root, because they are the ones an agent breaks before it knows which file to open: constraints bounding one entry rather than a host loop, FastSetProperty always creating an own property, GetOwnProperties not being the enumeration hook, and JsValue not being shareable across engines. Co-location is not decoration. Amp, Cursor, Devin Desktop/CLI and Copilot's cloud agent auto-load a nested AGENTS.md; a docs/ path would reach none of them. Claude Code reads CLAUDE.md rather than AGENTS.md and does not walk into a nested one, so .claude/rules/*.md with `paths:` frontmatter (gitignore semantics, trailing /** stripped) carries a pointer per area instead. That is also the only way Jint/Extensions/AGENTS.md — the polyfill discipline, which governs every call site in the assembly and not just its own directory — fires at all; its rule matches Jint/**/*.cs. .github/copilot-instructions.md had never been committed and was a 4.6 KB duplicate that had already drifted (it still named FluentAssertions). It is now a pointer that adds no rules of its own, kept only because Copilot in Visual Studio and JetBrains read it and have no AGENTS.md support at all. Nothing was lost and no prose was rewritten. Every heading and every gotcha bullet is byte-identical in exactly one destination; seven lines changed because a #anchor became a relative path to the file the anchor moved to. The +16,698 bytes of growth are entirely the new navigation: 13 file headers, 6 re-emitted "### Gotchas" headings, the index, the size-budget table, two pointer paragraphs, and 32 bytes of blank-line seams. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FHnbgQGW5QgfatxL6DgGEd
lahma
added a commit
that referenced
this pull request
Aug 23, 2026
…he README (#3291) The 4.x branch exists now, cut at the last commit before the opt-in Web API foundation and the security-defaults stack — both of which change what a default engine is and therefore belong to 5.x, not to a maintenance line. Three pieces of housekeeping follow from the branch existing at all. `build.yml` filtered its push trigger to `[ main, 3.x ]`, so a push to 4.x built nothing and published no preview package. 4.x joins the list. `pr.yml` needs no change: it deliberately carries no `branches:` filter, so a pull request based on 4.x already gets the full matrix. `VersionPrefix` moves to 4.16.1, which is what the MyGet preview stream coming off this branch should be numbered. It is not what a release will carry — `release.yml` derives that from the pushed `vX.Y.Z` tag and passes it to `dotnet pack`, so the property only ever names the preview feed's version. The README's "Branches and releases" section described `main` alone, which was true when `main` was the only branch anyone was asked to target. It now says what each of the three live branches is for and how a release is actually cut. What is deliberately *not* here: the AGENTS.md split (#3284). The maintenance branch keeps its single pre-split AGENTS.md, so a backport cherry-picked from main never conflicts on documentation layout. Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Docs: split
AGENTS.mdso it stops being silently truncatedAGENTS.mdwas 135,147 bytes (~17,700 words) in one file. OpenAI Codex reads a project doc up toproject_doc_max_bytes, whose default is 32768 — confirmed at today's HEAD incodex-rs/config/defaults.tomllines 8–9. Overflow is not a skip and not a warning the user sees:
read_agents_md()does a harddata.truncate(remaining)mid-file and emits atracing::warn!, which is below theRUST_LOG=errorthat
codex execdefaults to. At 4.13× the budget, a Codex user was getting roughly the first quarterof the file and no signal that the rest existed.
Two further facts from that source made the budget tighter than the headline number suggests, and both are
now recorded in the file itself:
remainingis a running total across the whole root→cwd chain, decremented per file — a fat root filestarves a nested one to zero bytes.
The root index is what reaches it.
This is a move, not an edit. No prose was rewritten, shortened or paraphrased.
1. The "stays inline" list — the judgement call, ranked by what a violation costs
These four gotchas stay in the root file. The test I applied: would an agent break this before it knew
which area it was working in? Each of them looks like an ordinary internal refactor right up to the moment
an embedder's bounded execution stops being bounded, or an embedder's object model stops being visible.
Jint/Constraints/— it is a rule aboutEngine.ExecuteWithConstraintsand about what an embedder'sforeach (var row in rows) predicate.Call(row)does. An agent "simplifying" a reset, or writing a test that assumes a host loop is bounded, never opens the constraints file first. Measured consequences are in the text:MaxStatements(100)does not stop 1000 host calls;TimeoutInterval(200ms)does not fire across 3 s.GetOwnPropertiesis not the enumeration hook (844 B)Jint/Native/Object/AGENTS.mdbefore you make the mistake, because you do not know you are making one.FastSetProperty/FastSetDataPropertyalways create an own property (646 B)JsValueacross engines is unsupported (333 B)What I deliberately did not keep inline, and why — the fourth candidate named in the brief:
### Engine-affine vs shareable state, 4,891 B) moved toJint/Runtime/Interpreter/AGENTS.md. The decisive question is who breaks it, and the answer iswhoever stashes engine-affine state on AST
UserData— i.e. someone editingJint/Runtime/Interpreter/**, which is exactly whereJintStatement.Build'sINVARIANTcomment alreadylives. The root index row for that file names the contract and its cost explicitly. This is the one
inline/move call I would most welcome being overruled on; see §7.
2. Byte table, before and after
Before — one file, 135,147 bytes (working-tree CRLF; 134,604 as the LF blob git stores). Section shares:
After — 14 files, none within 20% of the cap:
AGENTS.md(root)Jint/AGENTS.mdJint/WebApi/AGENTS.mdJint/Native/Object/AGENTS.mdJint/Runtime/Modules/AGENTS.mdJint.Benchmark/AGENTS.mdJint/Runtime/Interpreter/AGENTS.mdJint/Constraints/AGENTS.mdJint.Tests/Wpt/AGENTS.mdJint/Runtime/Interop/AGENTS.mdJint/Extensions/AGENTS.mdJint.Tests.Test262/AGENTS.mdJint/Native/AGENTS.mdJint.Tests.PublicInterface/AGENTS.mdPlus, not moved content:
.claude/rules/13 files totalling 7,217 B,.github/copilot-instructions.md837 B,
CLAUDE.md12 B (unchanged, still@AGENTS.md).Root is 23,197 B, under the 24 KiB (24,576 B) target with 1,379 B of headroom, and 9,571 B under the
hard cap.
Delta accounting: +16,883 bytes, explained line by line
### Gotchasheadings + their one-line pointer## How these instructions are laid out+ the 13-row triggered index## The size budget, and which agents load what+ the 13-row tool table## Third-party integration surface#anchor)Every byte of growth is navigation. No moved text grew.
3. The file map — every heading and every gotcha bullet
Produced by the splitter itself, which is heading-keyed rather than line-number-keyed and aborts if it
finds a unit the manifest does not route (see §6).
AGENTS.md(root) — 14,434 B of retained text## Build & Test### Quick manual testing with Jint.Repl## Architecture### Execution pipeline### Test projects## Third-party integration surface(intro)### Gotchasheading + preambleFastSetProperty/FastSetDataPropertyalways create an own property.GetOwnPropertiesis not the enumeration hook.JsValueacross engines is unsupported## Conventions### Performance is critical### Code patterns(includes theThrow.*rule and the spec-reference convention)### Data structures### Visibility: internal-firstJint/AGENTS.md— 24,530 B moved### Key types### Namespace organization### Type co-location### Unsigned-cast bounds check (`(uint) i < (uint) length`)## AOT compatibility### What counts as a public contract*Asyncentry has two ways out…RestoreGlobalSnapshotbumps version counters, it never restores them.EvaluateAsyncis invisible to the ordinary signals.Jint/Native/AGENTS.md— 2,246 B moved## ECMAScript complianceJint/Native/Object/AGENTS.md— 17,488 B moved### The subclassing cliff### Host-contract verification### When you add a fast lane, decide who can reach itJint/Runtime/Interop/AGENTS.md— 4,648 B movedIObjectConverterused to disable the compiled member-read lane…IReferenceResolverused to disable the inline caches…Jint/Runtime/Interpreter/AGENTS.md— 8,724 B moved### Engine-affine vs shareable stateJint/Runtime/Modules/AGENTS.md— 12,186 B moved## Modules### Asynchronous module loadingJint/Constraints/AGENTS.md— 6,995 B moved## Constraints & securityMaxRecursionDepthcounts one function's occurrences, not stack depth…Jint/Extensions/AGENTS.md— 3,429 B moved### Write against the modern BCL, and polyfill downwardsJint/WebApi/AGENTS.md— 19,491 B moved### Web APIs#### Diagnostics and reportErrorJint.Tests/Wpt/AGENTS.md— 4,967 B moved ·Jint.Tests.Test262/AGENTS.md— 3,126 B ·Jint.Tests.PublicInterface/AGENTS.md— 747 B### Web platform tests### Updating the test262 suite### Where integrator-facing tests belongJint.Benchmark/AGENTS.md— 12,136 B moved## Benchmarks### The measurement environment### Adding a new benchmark### Never warm one engine with more than one row's workload### Benchmarking host-object shapesThe seven prose edits, in full
These are the only characters of existing text that changed. Each is a
#anchorthat now lives in anotherfile, retargeted to a relative path.
## Build & Test[Host-contract verification](#host-contract-verification)…(Jint/Native/Object/AGENTS.md#host-contract-verification)### Test projects[Web platform tests](#web-platform-tests)…(Jint.Tests/Wpt/AGENTS.md#web-platform-tests)### Test projects[Updating the test262 suite](#updating-the-test262-suite)…(Jint.Tests.Test262/AGENTS.md#updating-the-test262-suite)Jint/AGENTS.mdnamespace mapSee [Web APIs](#web-apis).See [Web APIs](WebApi/AGENTS.md#web-apis).Jint/AGENTS.mdcontract tableis derived `Exotic` (below)is derived `Exotic` (see [the subclassing cliff](Native/Object/AGENTS.md#the-subclassing-cliff))Jint/Native/AGENTS.mdsee [Web APIs](#web-apis) for how it works and whysee [Web APIs](../WebApi/AGENTS.md#web-apis) …Jint.Benchmark/AGENTS.md[…](Jint.Benchmark/README.md)[…](README.md)4. Tool discovery — verified against primary sources, 2026-08-23
Two research passes; every row below was fetched from vendor documentation, a changelog, or source. The
brief's own claim was half right, and the correction matters: Copilot's cloud agent auto-loads nested
AGENTS.md, but Copilot's CLI does not — it walks upward only, and downward discovery is an openfeature request. Claude Code does not read
AGENTS.mdat all.AGENTS.mdbelow cwdAGENTS.override.md→AGENTS.md;codex.mdis entirely goneproject_doc_max_bytes= 32768, a running budget over the whole chain; silent mid-file truncationCLAUDE.md,.claude/CLAUDE.md,CLAUDE.local.md. Does not readAGENTS.md("create aCLAUDE.mdthat imports it")CLAUDE.mdloads when Claude reads a file in that directory;.claude/rules/*.mdwithpaths:fires on a matchCLAUDE.mdover 4 MiB is skipped, not truncatedAGENTS.mdsince 2025-08-28 and.github/copilot-instructions.mdand.github/instructions/**— all sets are supplied, none wins**/AGENTS.md; "the nearestAGENTS.mdfile in the directory tree will take precedence"AGENTS.md, root only, since 2026-06-18AGENTS.md,CLAUDE.md,.github/copilot-instructions.md,~/.copilot/…AGENTS.md—chat.useAgentsMdFiledefault true (GA v1.105, 2025-10-09)chat.useNestedAgentsMdFilesdefault false, experimental; and even when on it injects the path, not the content.github/copilot-instructions.mdonly — noAGENTS.mdsupportAGENTS.md,CLAUDE.md,.cursor/rules/*.mdc(.cursorruleslegacy)AGENTS.md; per-directory fallback toAGENT.md/CLAUDE.mdAGENTS.md,.devin/rules/*.md,.windsurf/rules/*.md,.windsurfrules<directory>/**"global_rules.md; 12,000 chars per workspace rule file; no total cap and no truncation sentence any moreAGENTS.md,AGENTS.local.md,AGENT.md,CLAUDE.md,.cursor/rules/*AGENTS.md"in your project root (or anywhere else)"; ingests rules files into KnowledgeGEMINI.md;AGENTS.mdonly ifcontext.fileNamenames itAGENTS.mdat the repository root (since 2025-06-20)read: [AGENTS.md]in.aider.conf.ymlSources. Codex:
defaults.toml,agents_md.rs,docs/install.md,AGENTS.md guide,
config reference. ·
Claude Code: memory, hooks,
skills,
CHANGELOG (
.claude/rules/landed inv2.0.64;
paths:accepting a YAML list fixed in v2.1.84),issue #16853. ·
Copilot: 2025-08-28 changelog,
2026-06-18 code review changelog,
custom-instructions support matrix,
response customization,
Copilot CLI changelog,
VS Code v1.104 / v1.105,
VS Code custom instructions. ·
Cursor: rules, help,
CLI changelog. ·
Amp: manual, multiple AGENT.md files,
AGENTS.md rename. ·
Cognition: Devin Desktop memories,
Devin Desktop AGENTS.md,
Devin CLI changelog,
Devin AGENTS.md. ·
Gemini CLI: GEMINI.md, memport. ·
Jules: docs, changelog. ·
Aider: conventions, config.
A condensed version of this table is now in the root
AGENTS.mditself, under## The size budget, and which agents load what, so the next person to grow the file sees the constraint.Consequences that shaped the design
docs/agents/— but only for four ecosystems. Amp, Cursor, Devin Desktop/CLI andCopilot's cloud agent auto-load a nested
AGENTS.md; adocs/path would reach none of them. That isthe whole justification and it holds, with the correction that Copilot's CLI is not one of them.
AGENTS.mdand does not walk into anested one.
.claude/rules/*.mdwithpaths:frontmatter is that mechanism, and I verified the detailsrather than assuming: the key is
paths:, notglobs:(that is Cursor) and notapplyTo:(that isCopilot); patterns are matched with gitignore semantics via the
ignorepackage with a trailing/**stripped, soJint/WebApi/**does matchJint/WebApi/Console/JsConsole.cs; and a path-scoped rulefires "when Claude reads files matching the pattern, not on every tool use."
One gitignore consequence worth flagging: a slash-free pattern matches at any depth, which is why the
single-component rules here are written anchored (
/Jint/**,/Jint.Benchmark/**).Gemini CLI and Aider the co-located files are never auto-loaded — they are reachable only because the
index names them and those agents can read files. That is why the index is a table with a trigger
column and a cost column, and why the four rules in §1 could not be delegated to it.
5.
.github/copilot-instructions.md: committed, as a pointerIt had never been committed, was 4.6 KB, and duplicated
AGENTS.md— and it had already drifted, stillnaming FluentAssertions after the repository moved to AwesomeAssertions. That is the failure mode the
brief warned about, demonstrated.
Deleting it outright was tempting but wrong: Copilot in Visual Studio and in JetBrains read
.github/copilot-instructions.mdand have noAGENTS.mdsupport at all, so deletion would leave thosetwo surfaces with nothing. And committing the duplicate was worse: the cloud agent supplies
.github/copilot-instructions.mdandAGENTS.mdtogether — "all sets of relevant instructions areprovided to Copilot" — so a copy is not a fallback, it is a second, diverging voice in the same prompt.
The committed file is 837 bytes, states no rule of its own, points at
AGENTS.md, and says in oneparagraph why it contains nothing else. The stale untracked copy was removed from the working tree.
6. Verification
Build.
dotnet build -c Releasefor the solution: exit 0, 0 errors. The one warning is apre-existing
MSB3277NuGet version conflict inJint.Tests.CommonScriptsonnet472, unrelated to thischange. (Note
.github/workflows/build.ymlhaspaths-ignore: '**.md', so a docs-only change skips thatworkflow anyway.)
Diff shape.
git diff --cached --stat: 28 files, all.md— 14AGENTS.md, 13.claude/rules/*.md,1
.github/copilot-instructions.md. No source, project or configuration file touched.CLAUDE.mdisbyte-identical (12 bytes,
@AGENTS.md).Nothing lost — scripted, not eyeballed. The splitter parses
AGENTS.mdinto 60 addressable units(heading-rooted sections, plus one unit per gotcha bullet keyed on its bold lead-in) and asserts every byte
belongs to exactly one unit. It then routes each unit through a manifest and aborts on any unit the
manifest does not name — which is precisely the guard against a concurrently landed edit being swallowed.
A separate verifier then compares the result against a snapshot of the original:
Exit code 0. Each of the seven is a declared retarget from §3, and the verifier proves the transformed
line is present rather than taking my word for it.
Concurrency. Cut against
upstream/main@50d4219fc, which is the tree the byte figures abovedescribe. PR #3278 was open and rewriting one of the moved bullets while this was drafted, so I ran the
splitter against #3278's head (
42419e3d3) as a rehearsal: it routes cleanly, the rewritten bullet landswhole in
Jint/AGENTS.md, and that file comes out at 25,547 B — still well under the cap. If #3278 landsafter this, its rebase will conflict because
AGENTS.mdno longer contains that bullet; the resolution isto put #3278's new bullet, wholesale, into
Jint/AGENTS.mdunder### Gotchas, not to reinstate it inthe root. The same applies to #3273 or anything else that appends: the root file now says explicitly do not
add a new gotcha here.
7. Against the verdict — what this split makes worse
A nested file an agent never triggers is a rule nobody reads. That is the real cost here, and it is not
hypothetical. Honestly, these are the rules now most at risk:
Jint/Extensions/AGENTS.md). It governs every call site in the assemblybut now sits in a directory almost nobody edits. It is the single worst fit for co-location in this
change. Mitigations:
.claude/rules/modern-bcl-polyfills.mdmatchesJint/**/*.cs— the one rule whosepaths:is deliberately not the directory it points at — and the root index row names it. For everyother agent, an engine edit no longer surfaces it at all. If one thing in this PR should be reverted
into the root, it is this.
Jint/Runtime/Interpreter/AGENTS.md). Placed bywho breaks it, not by who reads it. An agent editing
Jint/Engine.cs— wherePrepareScriptlives,and where the "may be shared across engines" promise is made — will get
Jint/AGENTS.mdand not this.§1 explains the reasoning; it is the call I am least sure of.
## ECMAScript compliance(Jint/Native/AGENTS.md). "Read the normative text before writing code"and "do not introduce non-standard language extensions" are close to constitutional, and they now fire
only under
Jint/Native/. Someone adding syntax works inJint/Runtime/Interpreter/and will not seethem.
## Constraints & security— "CLR access is disabled by default" moved toJint/Constraints/AGENTS.md. It is a configuration snippet rather than a rule, but it is the onlystatement of a security default and it is no longer in the file everyone reads.
### Key typesand### Namespace organizationleft the root. The brief required root to stillanswer "where things live"; it does — pipeline, test projects, and a 13-row index that names every area —
but the namespace-by-namespace map is now one hop away for anyone not already inside
Jint/.Two more honest costs:
### Gotchasis now seven lists in seven files. Nobody can read "all the gotchas" in one place anymore, and the count in the root's pointer sentence ("the other seventeen") is a hard-coded number that
will rot the first time someone adds one. That is a deliberate trade for making each list appear where it
bites, but it is a real loss of a document that people did read end-to-end.
for the machine's budget, not the human's.
And two things this does not fix:
AGENTS.mdits rules engine processes is not documented. If it does, six of the fourteen files exceedit. The root file's budget section says so rather than pretending otherwise.
file. For them the change is: the root file is no longer truncated (real, and the point), and everything
else is one deliberate
Readaway if the index does its job. If the index does not, this split hasmoved rules out of reach for six of the fourteen surfaces surveyed.
8. Proposals, not changes
Nothing below was acted on; the brief said to list rather than remove.
CLAUDE.mdimports it", which is true but now under-describes the layout; thenew
## How these instructions are laid outsection immediately below it covers the same ground from adifferent angle. Candidate for a one-line merge in a follow-up.
### Test projects(root) andJint.Tests.PublicInterface/AGENTS.mdoverlap by one sentence each aboutInternalsVisibleTo. Both were left verbatim.### Host-contract verificationcontains a self-referential "(below)" pointing at itself, which predatesthis change. Left as found.
## Modules(the 280-byte usage snippet) and### Asynchronous module loadingare now adjacent in onefile and could be introduced by a single sentence. Left unmerged.
Rebase note — the #3278 collision, resolved as predicted
Cut against
50d4219fc; #3278 landed in between and rewrote theRestoreGlobalSnapshotgotcha bullet from 1,463 to 3,337 bytes.AGENTS.mdwas the only conflicted file, and the resolution was the one rehearsed: take the split root wholesale, and put #3278's new bullet — not the old one the split had carried — intoJint/AGENTS.mdunder### Gotchas.Jint/AGENTS.mdis therefore 27,276 B rather than the 25,396 B the pre-rebase table states; still 83% of the cap, and still the largest file.Re-verified after the rebase, and this is the check that matters, because a clean-looking conflict resolution is exactly how somebody's new bullet gets dropped into a section that no longer exists:
upstream/main'sAGENTS.mdpresent in exactly one destination.- **bold**bullets present verbatim.](#anchor)→](path/AGENTS.md#anchor)); the seventh is thePropertyFlag.CustomJsValueparagraph, whose bare(below)became(see [the subclassing cliff](Native/Object/AGENTS.md#the-subclassing-cliff))— a required fix, since "below" stopped being true the moment that section moved to another file. Zero content lost.dotnet build -c Releasefor the solution: 0 errors.git diff --name-onlyagainstmain: markdown only, no source file touched.Jint/AGENTS.md27,276 (83%), root 23,197 (71%),Jint/WebApi/AGENTS.md19,986 (61%),Jint/Native/Object/AGENTS.md18,267 (56%), the remaining ten between 1,205 and 12,891.The mechanism claims were also re-verified independently against Claude Code's own documentation before merging, since the whole Claude Code half of the split rests on them:
.claude/rules/*.mdwith apaths:key is real, matches gitignore-style globs, and injects when Claude reads a matching file rather than at launch; a rule with nopaths:loads at launch; nestedCLAUDE.mdauto-loads on demand and concatenates with its ancestors rather than overriding them;@imports expand at launch with a 4-hop limit; and Claude Code does not readAGENTS.mdnatively — the@AGENTS.mdline inCLAUDE.mdis load-bearing and must stay.