almanac

module
v0.0.0-...-98211a5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: ISC

README

Almanac

Almanac keeps your repositories maintained. When a Renovate pull request breaks the build, it reads the failure, repairs it in a sandbox, and pushes the fix to the pull request, so the update can merge with nobody looking at it. When it cannot help, it says why and asks you on the pull request.

It is a Rust library for writing small, self-contained programs like that one, called almanacs. Behaviour is code you can test, and a model is called only where judgment or repair is needed.

[!NOTE] Early. almanacs/renovate runs live on its author's repositories, and there are no releases yet. You build from a clone. It works with GitHub and Claude today.

What it does

@types/node 26 broke a build in ivy/thicket#159. Nobody was going to look at it. Almanac waited for the release to be a few days old, held the pull request, and had an agent fix one line in a sandbox with no network:

-      body: new Blob([bytes]),
+      body: new Blob([new Uint8Array(bytes)]),

Plain code checked the patch, Almanac pushed it, CI passed, and the pull request was ready to merge. A repair like this costs tens of cents. One broken pull request follows it step by step.

Is it for you?

Almanac is for one person or a small team with a lot of repositories. You are "the operator" throughout these docs. It needs GitHub, and Renovate if you want the repairs, plus a host with PostgreSQL and Podman, and an Anthropic key or token. It is not a merge bot, a hosted service, or a general workflow engine.

Start here

What a workflow looks like

#[workflow(
    on = PullRequestChanged,
    key = "{repo}:{sha}",
    intent = "Hold a draft pull request, and let it through once it is ready.",
    may = [Attest],
    runs_per_hour = 10,
    decide = policy,
)]
pub async fn hold_drafts(_cx: &Cx, event: &PullRequestChanged) -> Result<Facts, Halt> {
    Ok(Facts {
        repo: event.repo.clone(),
        sha: event.sha.clone(),
        draft: event.draft,
    })
}

pub fn policy(facts: &Facts) -> Vec<Effect> {
    let state = match facts.draft {
        true => AttestState::Pending,
        false => AttestState::Success,
    };
    vec![Effect::Attest {
        context: "demo/ready",
        state,
        repo: facts.repo.clone(),
        sha: facts.sha.clone(),
    }]
}

The function gathers facts, and policy decides from them. A workflow can only do what may lists, and text an attacker could have written will not compile into a decision.

Documentation

Do something

Look something up

Understand it

Work on Almanac

AGENTS.md is the repository guide, and make check is the gate. It needs Podman and the claude CLI, and calls no model: the CLI runs against a local stub. Requirements, what proves each one, the roadmap, and decisions are maintainer documents.

License

ISC

Directories

Path Synopsis
Package advisory reads vulnerability advisories, and checks whether an update really is the fix one names (R-10).
Package advisory reads vulnerability advisories, and checks whether an update really is the fix one names (R-10).
Package agent declares the agents a workflow may call.
Package agent declares the agents a workflow may call.
almanacs
renovate
Package renovate is the Renovate almanac's vocabulary: the events, observers, predicates, agents and scans its workflows are written with.
Package renovate is the Renovate almanac's vocabulary: the events, observers, predicates, agents and scans its workflows are written with.
renovate/buildfailures
Package buildfailures repairs a Renovate pull request whose CI failed, once the update has cooled.
Package buildfailures repairs a Renovate pull request whose CI failed, once the update has cooled.
renovate/cmd/almanac-renovate command
Command almanac-renovate is the Renovate almanac: build_failures and security_fixes, run as a daemon or a verb at a time, with the fleet report, the comparison with the Rust version and the workflow views beside them.
Command almanac-renovate is the Renovate almanac: build_failures and security_fixes, run as a daemon or a verb at a time, with the fleet report, the comparison with the Rust version and the workflow views beside them.
renovate/compare
Package compare sets the Go almanac-renovate's decisions beside the Rust one's for the same pull requests, as evidence for a cutover.
Package compare sets the Go almanac-renovate's decisions beside the Rust one's for the same pull requests, as evidence for a cutover.
renovate/e2e
Package e2e holds the Renovate almanac's end-to-end specs, and nothing else.
Package e2e holds the Renovate almanac's end-to-end specs, and nothing else.
renovate/renovatetest
Package renovatetest holds doubles for specs of the Renovate almanac: a package registry held in memory, a way to set a commit status on simforge, and the providers a vocabulary reads through, pointed at a simforge.
Package renovatetest holds doubles for specs of the Renovate almanac: a package registry held in memory, a way to set a commit status on simforge, and the providers a vocabulary reads through, pointed at a simforge.
renovate/report
Package report says where every open Renovate pull request stands: exactly one state, and always a reason, as docs/report-states.md defines them.
Package report says where every open Renovate pull request stands: exactly one state, and always a reason, as docs/report-states.md defines them.
renovate/securityfixes
Package securityfixes validates a Renovate security pull request, and holds it until it is proved.
Package securityfixes validates a Renovate security pull request, and holds it until it is proved.
renovate/wiring
Package wiring sets up everything the Renovate almanac talks to, once, from the environment that docs/configuration.md lists.
Package wiring sets up everything the Renovate almanac talks to, once, from the environment that docs/configuration.md lists.
Package almanactest holds fakes, so a workflow and the runtime are testable with no model, service or network, and the runtime's conformance scenarios, which any store.Store can run under (see Conformance).
Package almanactest holds fakes, so a workflow and the runtime are testable with no model, service or network, and the runtime's conformance scenarios, which any store.Store can run under (see Conformance).
definitions
Package definitions holds the sample workflows, written as models in the DSL over a small vocabulary of their own.
Package definitions holds the sample workflows, written as models in the DSL over a small vocabulary of their own.
app
Package app is what an almanac binary's main calls: the verbs every almanac has, the daemon behind run, and the consumer that reads the broker's deliveries log into a runtime.
Package app is what an almanac binary's main calls: the verbs every almanac has, the daemon behind run, and the consumer that reads the broker's deliveries log into a runtime.
internal/almanac-demo command
Command almanac-demo is an almanac binary over the sample vocabulary and its two sample workflow models, with fakes for everything outside.
Command almanac-demo is an almanac binary over the sample vocabulary and its two sample workflow models, with fakes for everything outside.
Package broker is the one place webhooks arrive.
Package broker is the one place webhooks arrive.
Package check refuses a workflow model that breaks a rule, before any event arrives.
Package check refuses a workflow model that breaks a rule, before any event arrives.
Package clock is the time, as something a test can control.
Package clock is the time, as something a test can control.
cmd
almanac-broker command
Command almanac-broker is the one webhook ingress for every almanac.
Command almanac-broker is the one webhook ingress for every almanac.
Package config reads an almanac's runtime settings: almanac.toml, then ALMANAC_* variables, which win.
Package config reads an almanac's runtime settings: almanac.toml, then ALMANAC_* variables, which win.
Package cooled proves that a release has aged past a cooldown.
Package cooled proves that a release has aged past a cooldown.
Package deliveries is the log every almanac reads: each webhook the broker accepted, in the order it was accepted, with a durable cursor per almanac.
Package deliveries is the log every almanac reads: each webhook the broker accepted, in the order it was accepted, with a durable cursor per almanac.
Package diag holds every error a person or an agent can meet.
Package diag holds every error a person or an agent can meet.
Package docs carries the documents an almanac binary shows at run time: the long form of each error code, which explain prints.
Package docs carries the documents an almanac binary shows at run time: the long form of each error code, which explain prints.
Package dsl writes workflow models in Go.
Package dsl writes workflow models in Go.
Package effect is the closed set of ways a workflow touches the world: attest a status, await a change, file work, ask a person, push a checked patch (R-21).
Package effect is the closed set of ways a workflow touches the world: attest a status, await a change, file work, ask a person, push a checked patch (R-21).
Package engine runs a workflow model as a workflow.Registered, so the runtime runs a model exactly as it runs any workflow and never knows it is one.
Package engine runs a workflow model as a workflow.Registered, so the runtime runs a model exactly as it runs any workflow and never knows it is one.
Package github reaches GitHub through its REST API: the reads workflows and scans make, a Forge that sets statuses and pushes checked patches, an Issues tracker that files work and asks people, and a sweep that asks GitHub to resend webhook deliveries that failed.
Package github reaches GitHub through its REST API: the reads workflows and scans make, a Forge that sets statuses and pushes checked patches, an Issues tracker that files work and asks people, and a sweep that asks GitHub to resend webhook deliveries that failed.
events
Package events holds GitHub's webhook events as workflows read them, generated from projection.toml and checked against specs/github/api.github.com.json (R-37).
Package events holds GitHub's webhook events as workflows read them, generated from projection.toml and checked against specs/github/api.github.com.json (R-37).
harness
claude
Package claude is an agent.Harness on the Claude Code CLI, built as docs/adrs/0001-agent-sandbox.md decides: the agent loop runs on the host with no tools of its own, and its only tools are sandbox calls served over MCP by this process.
Package claude is an agent.Harness on the Claude Code CLI, built as docs/adrs/0001-agent-sandbox.md decides: the agent loop runs on the host with no tools of its own, and its only tools are sandbox calls served over MCP by this process.
claude/stub
Package stub is a stand-in for the Anthropic Messages API.
Package stub is a stand-in for the Anthropic Messages API.
Package hostile keeps text an attacker may have written apart from code that acts on it (principle 3 in docs/core-principles.md).
Package hostile keeps text an attacker may have written apart from code that acts on it (principle 3 in docs/core-principles.md).
internal/seal
Package seal links package hostile to hostile/reveal.
Package seal links package hostile to hostile/reveal.
reveal
Package reveal reads the value inside a hostile.Of.
Package reveal reads the value inside a hostile.Of.
internal
fixture/renovate
Package renovate is a small vocabulary shaped like the Renovate almanac's, for specs of the workflow model and the engine.
Package renovate is a small vocabulary shaped like the Renovate almanac's, for specs of the workflow model and the engine.
fixture/sample
Package sample is a small vocabulary for the sample workflows: triaging an application error from a source with no published schema, and judging a dependency update from a registry's evidence.
Package sample is a small vocabulary for the sample workflows: triaging an application error from a source with no published schema, and judging a dependency update from a registry's evidence.
fixture/workflows
Package workflows writes the Rust almanac's workflows in the Go DSL, against the fixture vocabularies, to prove the model can say everything they do.
Package workflows writes the Rust almanac's workflows in the Go DSL, against the fixture vocabularies, to prove the model can say everything they do.
pgtest
Package pgtest gives specs labelled db a PostgreSQL of their own, started through testcontainers on Podman.
Package pgtest gives specs labelled db a PostgreSQL of their own, started through testcontainers on Podman.
stall
Package stall gives the HTTP clients that reach outside services a limit on how long a peer may stop answering, so a stalled connection fails its request instead of holding a run, or a scheduled scan, forever.
Package stall gives the HTTP clients that reach outside services a limit on how long a peer may stop answering, so a stalled connection fails its request instead of holding a run, or a scheduled scan, forever.
stall/stalltest
Package stalltest gives specs a peer that stalls, for proving a client gives up on it.
Package stalltest gives specs a peer that stalls, for proving a client gives up on it.
Package model is a workflow as data: what triggers it, what it may do, and the steps a run takes, each step naming the vocabulary it uses.
Package model is a workflow as data: what triggers it, what it may do, and the steps a run takes, each step naming the vocabulary it uses.
Package patch is what a Fixer hands back, and the deterministic check that decides whether it may be pushed (R-20).
Package patch is what a Fixer hands back, and the deterministic check that decides whether it may be pushed (R-20).
Package providers holds what an almanac's workflows depend on, set up once where the binary is wired together: a forge, a tracker, a registry, harnesses for agents.
Package providers holds what an almanac's workflows depend on, set up once where the binary is wired together: a forge, a tracker, a registry, harnesses for agents.
Package registry reads what package registries say about a release: when it was published, for the cooldown proof, and its archive, for diffing.
Package registry reads what package registries say about a release: when it was published, for the cooldown proof, and its archive, for diffing.
Package runtime routes events to workflows, runs them, and applies what they decide, within limits.
Package runtime routes events to workflows, runs them, and applies what they decide, within limits.
Package sandbox is where hostile code runs.
Package sandbox is where hostile code runs.
fake
Package fake is a sandbox provider that keeps nothing on the host, which proves no caller depends on a host path.
Package fake is a sandbox provider that keeps nothing on the host, which proves no caller depends on a host path.
podman
Package podman is a sandbox provider on rootless Podman.
Package podman is a sandbox provider on rootless Podman.
Package simforge is a local GitHub for tests: the subset of the REST API Almanac uses, a scenario API to script it, signed webhook delivery, and failure injection.
Package simforge is a local GitHub for tests: the subset of the REST API Almanac uses, a scenario API to script it, signed webhook delivery, and failure injection.
Package store is everything an almanac must remember across a restart: the deliveries it has seen, work waiting for its key, the runs it started and what each recorded, the effects runs decided, and what was done to each key.
Package store is everything an almanac must remember across a restart: the deliveries it has seen, work waiting for its key, the runs it started and what each recorded, the effects runs decided, and what was done to each key.
memory
Package memory is a store.Store held in memory, for tests and one-shot commands.
Package memory is a store.Store held in memory, for tests and one-shot commands.
postgres
Package postgres is a store.Store in PostgreSQL, shared by the almanacs of one deployment and separated by almanac.
Package postgres is a store.Store in PostgreSQL, shared by the almanacs of one deployment and separated by almanac.
storetest
Package storetest is what every store.Store must do, as Ginkgo specs any implementation can run:
Package storetest is what every store.Store must do, as Ginkgo specs any implementation can run:
tools
eventgen command
Command eventgen writes GitHub event types from a projection: a declared list of fields, each checked against GitHub's pinned API spec (R-37).
Command eventgen writes GitHub event types from a projection: a declared list of fields, each checked against GitHub's pinned API spec (R-37).
hostilevet command
Command hostilevet is the taint analyzer, run by go vet:
Command hostilevet is the taint analyzer, run by go vet:
hostilevet/taint
Package taint is the analysis behind hostilevet.
Package taint is the analysis behind hostilevet.
Package version holds the version an almanac binary reports, set at link time by the Makefile.
Package version holds the version an almanac binary reports, set at link time by the Makefile.
Package views draws a workflow from its model, so that a person, or a reviewer of a change to a workflow, can see what it does without reading its code.
Package views draws a workflow from its model, so that a person, or a reviewer of a change to a workflow, can see what it does without reading its code.
Package vocab is what workflow models are made of: events, observers, publish-time sources, predicates, narrowing predicates and classifiers over hostile facts, maps that show hostile facts, agents, scans and patch policies.
Package vocab is what workflow models are made of: events, observers, publish-time sources, predicates, narrowing predicates and classifiers over hostile facts, maps that show hostile facts, agents, scans and patch policies.
Package wire is the boundary between raw payloads and typed events, and the only place outside text becomes a Go value.
Package wire is the boundary between raw payloads and typed events, and the only place outside text becomes a Go value.
Package workflow is the seam between workflows and the runtime.
Package workflow is the seam between workflows and the runtime.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL