Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Bearout
Bearout is a deterministic repository contract engine. A repository keeps prose and structured metadata together as resources; Bearout discovers them, validates their shape, resolves their relationships, applies the repository's own rules, and generates artifacts from the verified graph, with provenance.
A contract here is a machine-checkable agreement about the resources in a repository. It is not necessarily a legal contract.
[!WARNING] Bearout is an experiment. Its bootstrap, resource envelope, shape vocabulary, Starlark ABI (version 0), diagnostic codes, and generated outputs are not stable yet. Do not build a compatibility promise on the current syntax.
Two layers
- The Rust kernel owns discovery, parsing, graph construction, diagnostics, resource limits, path confinement, and filesystem writes.
- The repository owns every domain rule: schema identifiers and their JSON Schema shapes, validators, project checks, and generation plans in Starlark, and templates.
A schema identifier such as example/decision-records/decision@1 belongs to
the repository that defines it. Nothing is registered with Bearout or
compiled into the binary. See docs/design.md for the
responsibilities, phases, and boundaries.
The bootstrap
bearout.toml is static and is the capability boundary of a project:
= 1
= "bearout.star"
[]
= ["records"]
[]
= "rules" # `load()` resolves here; shapes live here
[]
= "templates"
[]
= ["generated"] # the only places generation may write
= "Apache-2.0" # stamped into generated headers
[] # optional; see docs/design.md for which defaults are measured
= 1000000
= 2000000
Repository policy can register schemas, checks, and generators. It cannot widen the roots the bootstrap grants. Roots are disjoint, none is the project root, and all filesystem access goes through a capability opened on the project root.
Repository policy
The entry module registers what the project uses:
A validator receives one frozen resource view and returns findings; a check receives the project view; a generator returns outputs:
return
return
load() resolves only beneath the rules root; escapes, symbolic links,
and cycles are rejected with the import chain. Every module is linted and
statically typechecked, and every evaluation runs under tick, heap, and
call-stack limits with cancellation. Scripts have no filesystem,
environment, network, clock, or random access. The full ABI is in
docs/starlark-abi.md.
Resources and shapes
A resource is Markdown with TOML front matter, or a header-only TOML file:
+++
schema = "example/decision-records/decision@1"
id = "decision-0004"
title = "Records are numbered when merged"
status = "accepted"
date = "2026-09-02"
supersedes = ["decision-0002"]
+++
```toml bearout=ruling
id = "decision-0004-ruling-01"
text = "A record receives its sequence number when it is merged."
```
schema, id, and refs are the envelope keys the kernel owns. Every
other key is validated by the schema's shape, a JSON Schema 2020-12
document authored in TOML with a small x-bearout vocabulary:
= "https://json-schema.org/draft/2020-12/schema"
= "object"
= false
= ["title", "status", "date"]
[]
= "array"
= { = "string" }
= { = "example/decision-records/decision@1" } # typed relation
[]
= ["Context"] # required heading
[] # a fragment kind
= "object"
= ["id", "text"]
The vocabulary itself is validated: an unknown x-bearout key, a relation
on a non-string property, or a shape that declares an envelope key is an
error. Markdown bodies are parsed with Comrak; headings get GFM anchors,
fenced blocks tagged bearout=<kind> become typed fragments with
project-wide identifiers, and every relative link and #anchor is resolved.
Phases
bootstrap, discovery, parsing, structural validation, graph construction, repository policy, generation planning, rendering, delivery. A resource that fails parsing or structural validation is never passed to a validator, and its identifiers still resolve so nothing cascades. Checks run only on an error-free graph; generation runs only on an error-free project.
Generation
Scripts never write files. A generator returns output(template, path, context) entries; the kernel validates every path against the output
roots, renders every artifact into memory with MiniJinja in strict mode,
computes BLAKE3 digests, and only then delivers each file through an atomic
rename. bearout-state.toml records which outputs Bearout owns and their
provenance; bearout generate --check reports missing, stale, unowned,
orphaned, and re-owned outputs. A file the manifest does not own is never
overwritten, even when its bytes already match; orphans are removed only
when the manifest proves Bearout wrote them and they are unmodified. The
report's outputs list names delivered or verified files only when
generation succeeded. Third-party content is recorded in
NOTICE.md.
Commands
Diagnostics use stable codes and forward-slash project-relative paths on
every platform; the catalog and its stability policy are in
docs/diagnostics.md.
Samples
The repository's samples/
directory holds eight complete projects, from three linked notes to a
spreadsheet-expression language whose Rust lexer, parser, and conformance
tests are generated from the resource graph and compiled in CI. The
samples index
is the capability matrix. Every sample is checked, and its outputs
verified, by the test suite. Samples are not part of the crates.io package.
Development
All required tools and versions are pinned in
mise.toml.
See CONTRIBUTING.md, docs/design.md,
and docs/technology-evaluation.md.
Trust
Bearout is a capability-confined host with resource limits. It is not a
sandbox for hostile repositories; see SECURITY.md.
Licence
Licensed under the Apache License 2.0.
Copyright 2026 Ali Malekpour.