|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +A machine-readable map of the NativeLink repository for AI coding agents and new |
| 4 | +contributors. NativeLink is a high-performance remote build cache and execution |
| 5 | +platform (Remote Execution API), written in Rust. |
| 6 | + |
| 7 | +Full documentation: https://docs.nativelink.com. Two entry points for machine |
| 8 | +readers, both generated from the docs navigation so neither can drift from the |
| 9 | +sidebar: https://docs.nativelink.com/llms.txt is the link index, one line per |
| 10 | +page in reading order, and https://docs.nativelink.com/llms-full.txt is the same |
| 11 | +corpus with page bodies inlined. Human contributor guide: |
| 12 | +[`CONTRIBUTING.md`](CONTRIBUTING.md). |
| 13 | + |
| 14 | +## The four roles |
| 15 | + |
| 16 | +NativeLink is four cooperating roles that speak the Remote Execution API: |
| 17 | + |
| 18 | +- **CAS**: content-addressable storage for build inputs/outputs, keyed by digest. |
| 19 | +- **Action Cache (AC)**: maps an action's digest to its cached result. |
| 20 | +- **Scheduler**: queues actions and matches them to workers by platform property. |
| 21 | +- **Workers**: execute actions and stream results back to the CAS. |
| 22 | + |
| 23 | +A single binary can run any combination of these, configured in JSON5. |
| 24 | + |
| 25 | +## Crate map (where things live) |
| 26 | + |
| 27 | +| Crate | Owns | |
| 28 | +| ----- | ---- | |
| 29 | +| `nativelink` (root, `src/bin/nativelink.rs`) | The server binary; wires config to running services. | |
| 30 | +| `nativelink-config` | JSON5 config schema. Stores in `src/stores.rs`, server/worker in `src/cas_server.rs`. Source of truth for the config reference. | |
| 31 | +| `nativelink-service` | gRPC services: CAS, AC, Execution, Capabilities, ByteStream, Worker API, BEP, health, fetch/push. | |
| 32 | +| `nativelink-store` | Every store implementation: filesystem, memory, redis, S3/R2/GCS/Azure/OCI/Mongo, and the composition stores (`fast_slow`, `shard`, `size_partitioning`, `compression`, `dedup`, `existence_cache`, `verify`, `ref`). | |
| 33 | +| `nativelink-scheduler` | Scheduler internals: matching engine, awaited-action DB, worker registry, state manager, retries. | |
| 34 | +| `nativelink-worker` | Worker: action execution, input materialization, sandboxing/namespaces, directory cache. | |
| 35 | +| `nativelink-util` | Shared utilities: `fs`/`fs_util`, `evicting_map`, `action_messages`, digests, and the OTLP metrics (`metrics.rs`). | |
| 36 | +| `nativelink-proto` | Generated protobufs (REAPI + NativeLink extensions). | |
| 37 | +| `nativelink-metric` / `nativelink-macro` | The `#[metric]` component-metrics derive system and proc macros. | |
| 38 | +| `nativelink-error` | The `Error` type and `ResultExt`. | |
| 39 | +| `nativelink-test` / `nativelink-redis-tester` | Test harness (`nativelink_test`) and Redis test tooling. | |
| 40 | + |
| 41 | +## Where to change what |
| 42 | + |
| 43 | +- **Add or change a config field**: edit the relevant spec in |
| 44 | + `nativelink-config/src/stores.rs` or `cas_server.rs`; the config reference is |
| 45 | + generated from the doc comments, so document the field there. |
| 46 | +- **Add a store type**: implement `StoreDriver` in `nativelink-store/src`, add |
| 47 | + its spec to `nativelink-config/src/stores.rs`, and wire it in the store factory. |
| 48 | +- **Add or change a gRPC service**: `nativelink-service/src/*_server.rs`. |
| 49 | +- **Change scheduling/matching/retries**: `nativelink-scheduler/src`. |
| 50 | +- **Change action execution / worker behavior**: |
| 51 | + `nativelink-worker/src/running_actions_manager.rs`. |
| 52 | +- **Add an OTLP metric**: declare and record it in |
| 53 | + `nativelink-util/src/metrics.rs`; record it at the call site; regenerate the |
| 54 | + metrics reference. Do not leave a metric declared-but-never-recorded: the |
| 55 | + generated reference has a column for exactly that, and it will say so. |
| 56 | + |
| 57 | +## Changing X: source of truth, and the doc that must follow |
| 58 | + |
| 59 | +When a change lands, this table says what else has to move with it. The rule is |
| 60 | +that the source of truth is always in the repo, and the doc either regenerates |
| 61 | +from it or cites it, never restates it by hand. Every path in the right-hand |
| 62 | +column is a real page under `web/apps/docs/content/docs/`. |
| 63 | + |
| 64 | +| You changed | Source of truth | Doc that must follow | |
| 65 | +| ----------- | --------------- | -------------------- | |
| 66 | +| A config field or its doc comment | `nativelink-config/src/{stores,cas_server}.rs` | `reference/nativelink-config/*`; regenerate with `gen:config-reference`, never hand-edit | |
| 67 | +| A store's behavior or defaults | `nativelink-store/src/*` | the backend page under `how-to/stores/`, plus `reference/nativelink-config/store-overview` if the composition model moved | |
| 68 | +| A metric name, type, or label | `nativelink-util/src/metrics.rs` and its call sites | `reference/metrics` (regenerate with `gen:metrics-reference`) and `operate/observability` | |
| 69 | +| A CLI flag or `NL_*` env var | the binary's arg parsing | `reference/cli-and-env` | |
| 70 | +| A gRPC service or the set of services a server exposes | `nativelink-service/src/*_server.rs` | `configuration/servers-and-services`, which names every service as the config spells it | |
| 71 | +| Scheduler matching or platform-property semantics | `nativelink-scheduler/src` | `remote-execution/platform-properties`, and `explanations/architecture` if the model changed rather than the mechanics | |
| 72 | +| Worker sandboxing or input materialization | `nativelink-worker/src/running_actions_manager.rs` | `explanations/architecture` and `operate/security-hardening`; the second one states what the sandbox is *not* | |
| 73 | +| The licence header on a file, or `LICENSE` | the headers themselves | `reference/oss-and-enterprise`, which is the only place the licence split is explained | |
| 74 | +| The canonical production config | `deployment-examples/`, `nativelink-config/examples/` | `operate/production-config`; the snippets are lifted from there, not invented | |
| 75 | +| A page's URL | `web/apps/docs/content/docs/**/meta.json` | add a redirect in `web/apps/docs/next.config.mjs` | |
| 76 | + |
| 77 | +## Build, test, verify |
| 78 | + |
| 79 | +NativeLink builds with both Bazel and Cargo. |
| 80 | + |
| 81 | +```bash |
| 82 | +bazel test //... # all tests (first run 10-20 min) |
| 83 | +bazel test //nativelink-store/tests:s3_store_test # one target |
| 84 | +bazel build //nativelink:nativelink # the server binary |
| 85 | +cargo test -p nativelink-store # a single crate with cargo |
| 86 | +``` |
| 87 | + |
| 88 | +Run the built server against a config: |
| 89 | + |
| 90 | +```bash |
| 91 | +bazel run //nativelink:nativelink -- ./path/to/config.json5 |
| 92 | +``` |
| 93 | + |
| 94 | +Example configs live in `nativelink-config/examples/` and runnable deployments in |
| 95 | +`deployment-examples/` (docker-compose, including a multi-worker set) and |
| 96 | +`integration_tests/`. |
| 97 | + |
| 98 | +## The docs, and their gates |
| 99 | + |
| 100 | +The docs site is a [Fumadocs](https://fumadocs.dev) app at `web/apps/docs`. Pages |
| 101 | +are MDX under `content/docs/`, and `meta.json` in each directory controls both the |
| 102 | +sidebar order and which pages are published. |
| 103 | + |
| 104 | +```bash |
| 105 | +cd web && bun install |
| 106 | +bun run --filter docs dev # local docs server; regenerates first |
| 107 | +bun run --filter docs build # what CI builds |
| 108 | +bunx biome check --write . # lint and format |
| 109 | + |
| 110 | +bun --filter @nativelink/docs lint:snippets # JSON5 snippets against the config schema |
| 111 | +bun --filter @nativelink/docs lint:anchors # explicit anchors on headings and FAQ entries |
| 112 | +``` |
| 113 | + |
| 114 | +Six things a docs change has to satisfy: |
| 115 | + |
| 116 | +- **Vale and typos** run in pre-commit. New product nouns go in |
| 117 | + `.github/styles/config/vocabularies/TraceMachina/accept.txt`. |
| 118 | +- **Biome** formats and lints the TypeScript and the MDX components. |
| 119 | +- **Every nav entry resolves.** A `meta.json` entry naming a page that doesn't |
| 120 | + exist is a broken sidebar link, and `gen:llms` fails loudly on one. |
| 121 | +- **Moved URLs redirect.** Agents cache URLs longer than humans keep bookmarks; |
| 122 | + a 404 on an old path is a regression. |
| 123 | +- **`lint:snippets` passes.** Every key in a JSON5 config snippet has to exist in |
| 124 | + the generated config reference. A snippet that is deliberately wrong (showing |
| 125 | + a mistake, or a foreign tool's config) opts out with |
| 126 | + `{/* lint-snippets: ignore */}` above it. |
| 127 | +- **`lint:anchors` passes.** Every heading and every `<Accordion>` carries an |
| 128 | + explicit anchor, so rewording a heading cannot silently repoint a citation. |
| 129 | + `lint:anchors --fix` writes the anchor Fumadocs would have derived anyway, |
| 130 | + which means running it never moves an existing link. |
| 131 | + |
| 132 | +Four things under `web/apps/docs` are generated. Regenerate them; never hand-edit: |
| 133 | + |
| 134 | +| Generated | From | Command | |
| 135 | +| --------- | ---- | ------- | |
| 136 | +| `content/docs/reference/nativelink-config/*` | the `nativelink-config` crate, via `build-schema` | `gen:config-reference` | |
| 137 | +| `content/docs/reference/metrics.mdx` | `nativelink-util/src/metrics.rs` and its call sites | `gen:metrics-reference` | |
| 138 | +| `content/docs/reference/changelog.md` | the repository-root `CHANGELOG.md` | `gen:changelog` | |
| 139 | +| `public/llms.txt`, `public/llms-full.txt` | the navigation and page frontmatter | `gen:llms` | |
| 140 | + |
| 141 | +The last two are gitignored and rebuilt by `dev` and `build`, so they cannot be |
| 142 | +committed in a stale state. |
| 143 | + |
| 144 | +Page structure follows four archetypes (tutorial, how-to, explanation, |
| 145 | +reference), with a template for each in `web/apps/docs/templates/`. The |
| 146 | +conventions those templates encode: |
| 147 | + |
| 148 | +- A narrative page never inlines an exhaustive field list. It explains the |
| 149 | + fields that carry a decision and links the generated reference for the rest. |
| 150 | +- Pages on the reading path (Getting started, Remote execution, Configuration, |
| 151 | + How-to guides, plus Why NativeLink before and Operate after) open with |
| 152 | + `<Prerequisites>`, so a reader landing cold from a search knows what the page |
| 153 | + assumes. |
| 154 | +- Tutorials and how-tos close with `<VerifyBlock>`: a checkable claim, not "it |
| 155 | + should work now". |
| 156 | +- Behavioural claims carry `<SourceLink>`, permalinked to a release tag rather |
| 157 | + than to `main`. The pinned ref lives in `web/apps/docs/lib/source-ref.ts`; bump |
| 158 | + it in the same change that regenerates the reference for a new release. |
| 159 | +- Headings carry an explicit `[#anchor]`, and `<Accordion>` entries an `id`, so |
| 160 | + a citation to a specific claim keeps resolving after the prose is reworded. |
| 161 | + |
| 162 | +## Conventions |
| 163 | + |
| 164 | +- Pre-commit runs rustfmt, `typos`, and (for docs) `vale`. Write to pass them. |
| 165 | +- The config reference under `web/apps/docs/content/docs/reference/nativelink-config` |
| 166 | + is autogenerated via the `build-schema` binary; regenerate, never hand-edit. |
| 167 | +- Prefer generating docs/reference from a code source of truth over hand-writing, |
| 168 | + to prevent drift. |
0 commit comments