Skip to content

Your repo's knowledge base ​

The walkthrough covers standing a knowledge base up as a sequence of steps. This page is the reference for the model underneath it: what a repo's own knowledge base is, how it is laid out, and how it draws on shared knowledge.

Documenting a repo in place ​

A repo does not have to only consume knowledge someone else publishes. It can document itself - host its own corpus, built and served in place, specific to that repo. That is what alloy init creates, and it is the default way to adopt Alloy.

The defining fact: the source is self: true. The source being documented is the enclosing repo, and its drift referent is the repo's own git HEAD. Documentation and code therefore share one commit history, and provenance comes nearly free.

The .alloy/ layout ​

alloy init scaffolds a portable root:

.alloy/
├── alloy.config.yaml                 the source registry - a single self: true source
├── ecosystems.yaml                   what counts as a source file per ecosystem
├── rulepacks/
│   └── templates/                    rule packs + doc templates (survey-drafted)
└── corpus/
    ├── meta/corpus-manifest.yaml      this repo's own consumer contract
    ├── shared/                        curated docs
    └── sources/<name>/                generated docs

Everything is committed to the repo. There is no separate state store: the committed manifest is the corpus's declaration, the same "committed = declared" principle the dependency lock rests on.

The self: true source ​

A repo's own source is deliberately minimal:

yaml
corpusRoot: .alloy/corpus
sources:
  your-repo:
    self: true            # this repo is the source; referent = local HEAD
    scanners: [js-workspace]
    units:
      - kind: lib
        match: packages/{name}
        groupBy: name
    # coverage: { ... }     # opt into accounting once you are triaging

It carries no repo/ref (those are optional-informational only for a self source) and no path/track/drift - the referent is always local HEAD. Keep machine-local paths out of it entirely; it is committed and pathless.

Running the loop ​

Every command runs from anywhere inside the repo; the CLI walks up to .alloy/alloy.config.yaml and resolves the corpus home (.alloy/corpus/) from there. Because the repo need not depend on the package, the CLI can be invoked directly:

bash
npx @engineering11/alloy-cli discover
npx @engineering11/alloy-cli status

Unlike a source that reads an external checkout, a self: source needs no ALLOY_SOURCE_PATH_* override, and its tree is legitimately dirty with the authored docs at stamp time - self mode warns rather than refuses.

Adding shared knowledge ​

A fresh knowledge base sees only itself. To draw on knowledge another repo publishes - a shared knowledge base such as the Engineering11 foundation - declare it as a dependency:

bash
alloy add @engineering11/alloy

The intent lands in the corpus manifest's dependencies: block and the exact resolution in .alloy/corpus.lock; both are committed, and a fresh clone restores them with alloy sync. A query key whose category your own corpus declares resolves against your own corpus and is terminal; a key whose category only a dependency declares resolves there. Own categories always win, so pick category names that do not collide with a dependency unless you mean to override it.

Full detail - package and git locators, what lands in the manifest versus the lock, qualified keys, and the scope line - is in Add shared knowledge.

Self-updating CI ​

alloy init --ci (or --ci on an existing knowledge base) scaffolds three workflows that keep the corpus honest without ever auto-merging:

  • alloy-detect.yml - daily drift detection to a single pinned issue.
  • alloy-propose.yml - a weekly propose run that opens one human-merged PR.
  • alloy-validate.yml - corpus validation on every PR touching .alloy/**.

Detection and proposal automate; the merge is always a human. That is the same automation ladder Alloy runs everywhere.

E11 Alloy - knowledge as a build artifact.