agentleFS
ElasticKnown publisherelastic/docs-builder/AGENTS.md

docs-builder

AGENTS.md25 starsChanged 19 days agoApache-2.0View on GitHub

Elastic's documentation build toolchain. Processes Markdown from multiple repos into a unified documentation site, validates cross-repo references, serves with live reload, and ships as native AOT binaries for CI. CLI changes: after editing src/tooling/docs-builder/Commands/, regenerate docs/cli-schema.json: See CONTRIBUTING.md for supplemental CLI docs under docs/schema-support/cli-schema/. Tests live in tests/ (unit) and tests-integration/ (integration). Use the /test skill to pick the right test project automatically. A change to product code should land with a test that exercises it — the mapping from…

  • Commits and pushes

We split this AGENTS.md into the rules it gives an agent

9 rules. About 0 are common, 1 is distinctive, and 8 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 8

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    CLI changes: after editing src/tooling/docs-builder/Commands/, regenerate docs/cli-schema.json:

    line 35
  2. Very specific:

    Use the /test skill to pick the right test project automatically.

    line 64
  3. Very specific:

    Never skip hooks (--no-verify) — see Code Style.

    line 104
  4. Very specific:

    If the build also has style errors/warnings outside that set, add --forward to hand remaining diagnostics to dotnet format style:

    line 114
  5. Very specific:

    Collections: never return null — return [].

    line 126
  6. Very specific:

    Comments: only when *why* is non-obvious.

    line 128
  7. Very specific:

    Use /style-review to check a diff against these rules.

    line 130
  8. Distinctive:

    Always invoke the skill for the following tasks — never substitute your own format:

    line 134
  9. Very specific:

    Update /docs/ whenever Markdown syntax or rendering behaviour changes.

    line 143

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

docs-builder

Elastic's documentation build toolchain. Processes Markdown from multiple repos into a unified documentation site, validates cross-repo references, serves with live reload, and ships as native AOT binaries for CI.

Architecture

ProjectPurpose
src/Elastic.Markdown/Core Markdown parser and Myst directive/role engine
src/tooling/docs-builder/CLI — entry point Program.cs, commands in Commands/
src/tooling/essc/AOT CLI indexing elastic.co content (Contentstack, Labs) into Elasticsearch; ships as ghcr.io/elastic/website-search-essc
src/services/search/Elastic.Documentation.Search.Contract/Shared search document/mapping/API contract used by docs search and essc
src/Elastic.Documentation.Site/Frontend (TypeScript · React · Vite)
src/Elastic.Documentation.Configuration/YAML config schema and loading
src/Elastic.Documentation.Navigation/Nav tree assembly and validation
src/Elastic.Documentation.Links/Cross-repo link index and resolution
src/Elastic.ApiExplorer/API reference rendering
src/Elastic.Codex/Content management and assembly
src/services/Background microservices
src/infra/AWS Lambda functions (link index updater, changelog scrubber)

Essential Commands

dotnet build                                    # verify compilation
dotnet run --project src/tooling/docs-builder   # run CLI locally
./build.sh unit-test                            # all unit tests (fast, ~1 min)
./build.sh integrate                            # integration tests (slow — needs cloned repos)
./build.sh lint                                 # C# format check (read-only)
./build.sh clean                                # remove .artifacts/
dotnet curb format .                            # auto-fix C# formatting
dotnet test tests/Elastic.Markdown.Tests/       # single test project

CLI changes: after editing src/tooling/docs-builder/Commands/, regenerate docs/cli-schema.json:

dotnet run --project src/tooling/docs-builder -- __schema > docs/cli-schema.json

See CONTRIBUTING.md for supplemental CLI docs under docs/schema-support/cli-schema/.

TypeScript frontend

cd src/Elastic.Documentation.Site
npm ci
npm run build           # production build
npm run watch           # dev with live reload
npm run test            # Vitest
npm run lint            # ESLint
npm run fmt:write       # Prettier auto-fix
npm run compile:check   # TypeScript type check only

Testing

Tests live in tests/ (unit) and tests-integration/ (integration).

  • C#: TUnit · AwesomeAssertions · FakeItEasy across all test projects. All test projects (unit and integration) use TUnit (wired centrally via tests/Directory.Build.props and tests-integration/Directory.Build.props; no per-project flag needed). Write new tests using TUnit APIs: [Test], [Arguments(...)], [MethodDataSource(nameof(X))].
  • TypeScript: Vitest
  • Integration: clones real repos, runs full assembler — only run when integration files change

Use the /test skill to pick the right test project automatically. A change to product code should land with a test that exercises it — the mapping from changed source to test project (mirrored by /test):

Changed pathTest project / command
src/Elastic.Markdown/./build.sh unit-test (targets Elastic.Markdown.Tests and Elastic.Authoring.Tests)
src/Elastic.Documentation.Configuration/./build.sh unit-test (targets Elastic.Documentation.Configuration.Tests)
src/Elastic.Documentation.Navigation/./build.sh unit-test (targets Navigation.Tests)
src/Elastic.Documentation.Indexing/./build.sh unit-test (targets Elastic.Documentation.Indexing.Tests)
src/authoring/Elastic.LegacyDocs.Migration/./build.sh unit-test (targets Elastic.LegacyDocs.Migration.Tests)
src/tooling/essc/./build.sh unit-test (targets Elastic.SiteSearch.Tests)
src/Elastic.ApiExplorer/./build.sh unit-test (targets Elastic.ApiExplorer.Tests)
src/services/Elastic.Documentation.Deploying/./build.sh unit-test (targets Elastic.Documentation.Deploying.Tests)
src/Elastic.Documentation.Site/cd src/Elastic.Documentation.Site && npm run test; design-system, style-guide and _Head changes also run ./build.sh unit-test (Navigation.Tests, DesignSystem folder); changes to shared views or layout CSS also run npm run visual:seed once and npm run visual:check to prove flag-off output is unchanged. See src/Elastic.Documentation.Site/AGENTS.md
tests-integration/./build.sh integrate
Multiple / uncertain./build.sh unit-test

Key Locations

WhatWhere
Myst extensions (directives, roles)src/Elastic.Markdown/Myst/
CLI commandssrc/tooling/docs-builder/Commands/
Config schemasrc/Elastic.Documentation.Configuration/
Frontend assetssrc/Elastic.Documentation.Site/Assets/
Test helperstests/Elastic.Markdown.Tests/TestHelpers.cs
Repo / nav configconfig/
Docs site/docs/

Cross-cutting decisions

  • AOT + source-generated JSON everywhere. Both CLIs (docs-builder, essc), the Lambda functions in src/infra/, and most shared libraries are Native AOT (<PublishAot>true</PublishAot>) or AOT-compatible (<IsAotCompatible>true</IsAotCompatible>). The load-bearing rule this implies: any new serialized type must be registered with [JsonSerializable] on the right JsonSerializerContext (canonical example: src/Elastic.Documentation/Serialization/SourceGenerationContext.cs) or it fails at runtime once published/trimmed, not at compile time. Code in AOT/AOT-compatible projects must stay reflection-free — this is why SYSLIB1100/SYSLIB1101/IL3050 are suppressed in those .csproj files rather than fixed; they can't be fixed, only worked around.
  • The shared search contract. src/services/search/Elastic.Documentation.Search.Contract/ exists as a separate, dependency-light project specifically so both the docs indexing pipeline (Elastic.Markdown/Exporters/Elasticsearch/) and essc reference the same document schema, mappings, and analysis config — one content-source's fields can't drift from another's. See docs/development/essc.md for the source-by-source detail (Contentstack, Labs).

Boundaries: never touch / human-gated

  • Destructive essc indices commands target production Elasticsearch. unify, copy --force, cleanup, sync-remote, unify-incremental-sync (src/tooling/essc/Commands/IndicesCommands.cs) delete indices and repoint aliases against real clusters. Never run these against a real cluster without an explicit human decision; prefer --dry-run first. cleanup's planning step (IndicesCleanupPlanner.Plan, same folder) is a pure function that's idempotent by design — retrying a cleanup run after a partial apply re-plans against current state and deletes nothing further (see Applying_the_plan_then_replanning_yields_no_further_deletions in tests/Elastic.SiteSearch.Tests/IndicesCleanupPlannerTests.cs); the mutating steps around it still touch a real cluster, so the caution above still applies.
  • docs-builder commands tagged [CommandIntent(Intent.Destructive)] / [MutationScope(MutationScope.Global)] / [RequiresAuth] — Assembler Apply, Codex Apply, ChangelogCommand's publish path, Move/mv (src/tooling/docs-builder/Commands/). These do mass S3 deletes or repo-wide link rewrites; the attributes on a command are the ground truth for its blast radius — read them before running anything unfamiliar.
  • Prod Lambda deploys are GitHub-Environment-gated. deploy-link-index-updater-lambda-prod and deploy-changelog-scrubber-lambda-prod in .github/workflows/release.yml require the link-index-updater-prod / changelog-scrubber-prod environments respectively. Don't try to route around environment protection.
  • config/assembler.yml is baked into the changelog-scrubber Lambda as its public-bucket allowlist. Editing it changes what private-repo content can be published to the public bucket — treat changes here as high blast-radius, not a routine config edit.
  • Credentials load from dotnet user-secrets (the docs-builder store) or environment variables (src/tooling/essc/Elasticsearch/SourcingConfiguration.cs, ContentStackConfiguration.cs) — never hardcode a key/URL or commit one to config.
  • Never skip hooks (--no-verify) — see Code Style.

Code Style

Mechanical formatting is fully enforced by .editorconfig and curb via the MSBuild integration (auto-rewrites on dotnet build in Debug mode) and the Husky.Net pre-commit hook (curb check). To fix manually: dotnet curb format .. Never use --no-verify.

After a build that produces only errors curb natively handles (IDE0005, IDE0007, IDE0034, IDE0040, IDE0044, IDE0071, IDE0090, IDE0240, IDE0250, IDE0251), run:

curb cleanup

If the build also has style errors/warnings outside that set, add --forward to hand remaining diagnostics to dotnet format style:

curb cleanup --forward

Beyond what .editorconfig can check:

  • Async: public async methods → PascalCaseAsync; private → PascalCase. Never .Result/.Wait(). Always accept CancellationToken. Use ConfigureAwait(false) in library code.
  • Class member order: fields → constructors (prefer primary) → properties → methods (grouped by function, not visibility).
  • Complexity: max 5–7 branches per method. Extract named helpers rather than nesting.
  • Early returns: guard clauses first, happy path last.
  • Parameters: max 4 — use a record/options object beyond that. Boolean params must be named at call sites.
  • Collections: never return null — return []. Use the TryGet pattern for lookups.
  • Testing: TUnit with AwesomeAssertions fluent style. Method naming: Method_Scenario_Expected.
  • Comments: only when why is non-obvious. No #region. No multi-paragraph docstrings.

Use /style-review to check a diff against these rules.

Agentic skills

Always invoke the skill for the following tasks — never substitute your own format:

  • Commits — use /commit before creating any git commit.
  • Pull requests — use /pr before running gh pr create. Never write your own PR body or title without going through the skill first.
  • Issues — use /issue before running gh issue create. Never file an issue without going through the skill first.
  • Feature flags — use /feature-flag when you add or extend a flag. Flag-off must match the previous default.

Documentation

Update /docs/ whenever Markdown syntax or rendering behaviour changes.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.