Liking cljdoc? Tell your friends :D

hive-build.api

The canonical hive release tasks, delivered as a library.

Point a repository's :build alias here and it inherits the whole release path — no build.clj to copy, and no build.clj to drift:

:build {:deps {io.github.hive-agi/hive-build {:mvn/version "0.1.0"}} :ns-default hive-build.api}

Coordinates come from ./version.edn, the version from ./VERSION:

{:lib io.github.hive-agi/hive-thing :minor 1 :license {:name "MIT" :url "https://opensource.org/licenses/MIT"} :scm-url "https://github.com/hive-agi/hive-thing" :src-dirs ["src"] :publish :clojars ; :clojars | :clojars-aot | :gitea | :gitea-source | :none :aot/java-opts [] ; optional, AOT compile only :aot/elide-meta [] ; optional, [] disables metadata elision :aot/publishable-sources [] ; optional, entry prefixes whose sources ship :aot/source-namespaces [] ; optional, namespaces shipped as source text: ; not compiled, not load-checked (for ; integrations of optional libraries) :aot/strict-opacity false ; optional, overrides the target's default: ; a PRIVATE target (:gitea) fails a leak, ; a public one only reports it :jar-excludes [] ; optional, entry paths (file or directory) ; pruned before the jar is written and ; refused if the jar still carries them :unpackaged-paths [] ; optional, deps.edn :paths roots deliberately ; left out of :src-dirs (otherwise a jar ; warns and a deploy is refused) :pom-exclude-deps []} ; optional, dropped from the published pom

An untracked ./local.deps.edn may supply a :provided alias (host sources that must be on the AOT compile classpath but must NOT enter the pom) and an :aot/preload namespace vector compiled ahead of this lib's own namespaces. The project's own deps.edn may declare a :provided alias too; it reaches the AOT compile classpath, never the pom or the load check.

:publish is the ONLY thing that differs between packages — the task names are identical everywhere, so one CI workflow drives the whole fleet:

:clojars public source jar -> repo.clojars.org :clojars-aot public AOT jar -> repo.clojars.org :gitea AOT no-source jar -> private Gitea Maven registry :gitea-source source jar -> private Gitea Maven registry :none builds, never ships

Tasks (invoke with clojure -T:build <task>): clean delete target/ jar source jar + pom jar-aot AOT no-source jar (own .class + resources only) install build + install to ~/.m2 (offline) kondo sync dependency-exported lint configs, then lint bump rewrite ./VERSION (:level :patch|:minor|:major) verify-license report LICENSE / version.edn / SPDX agreement (warns) audit-opacity report private strings a built jar still carries (warns) freeze-check refuse a release that breaks ./freeze-policy.edn (fails) readme-examples run README.md's clojure blocks in a new JVM (fails) changelog regenerate ./CHANGELOG.md from the release tags deploy build + publish per :publish (no-op when :none)

Release flow (what CI runs on a push to main that touches src/deps): clojure -T:build bump :level :patch clojure -T:build deploy

The canonical hive release tasks, delivered as a library.

Point a repository's :build alias here and it inherits the whole release
path — no build.clj to copy, and no build.clj to drift:

  :build {:deps {io.github.hive-agi/hive-build {:mvn/version "0.1.0"}}
          :ns-default hive-build.api}

Coordinates come from ./version.edn, the version from ./VERSION:

  {:lib      io.github.hive-agi/hive-thing
   :minor    1
   :license  {:name "MIT" :url "https://opensource.org/licenses/MIT"}
   :scm-url  "https://github.com/hive-agi/hive-thing"
   :src-dirs ["src"]
   :publish  :clojars             ; :clojars | :clojars-aot | :gitea | :gitea-source | :none
   :aot/java-opts []              ; optional, AOT compile only
   :aot/elide-meta []             ; optional, [] disables metadata elision
   :aot/publishable-sources []    ; optional, entry prefixes whose sources ship
   :aot/source-namespaces []      ; optional, namespaces shipped as source text:
                                  ;   not compiled, not load-checked (for
                                  ;   integrations of optional libraries)
   :aot/strict-opacity false      ; optional, overrides the target's default:
                                  ;   a PRIVATE target (:gitea) fails a leak,
                                  ;   a public one only reports it
   :jar-excludes []               ; optional, entry paths (file or directory)
                                  ;   pruned before the jar is written and
                                  ;   refused if the jar still carries them
   :unpackaged-paths []           ; optional, deps.edn :paths roots deliberately
                                  ;   left out of :src-dirs (otherwise a jar
                                  ;   warns and a deploy is refused)
   :pom-exclude-deps []}          ; optional, dropped from the published pom

An untracked ./local.deps.edn may supply a `:provided` alias (host sources
that must be on the AOT compile classpath but must NOT enter the pom) and an
`:aot/preload` namespace vector compiled ahead of this lib's own namespaces.
The project's own deps.edn may declare a `:provided` alias too; it reaches
the AOT compile classpath, never the pom or the load check.

`:publish` is the ONLY thing that differs between packages — the task names
are identical everywhere, so one CI workflow drives the whole fleet:

  :clojars       public source jar   -> repo.clojars.org
  :clojars-aot   public AOT jar      -> repo.clojars.org
  :gitea         AOT no-source jar   -> private Gitea Maven registry
  :gitea-source  source jar          -> private Gitea Maven registry
  :none          builds, never ships

Tasks (invoke with `clojure -T:build <task>`):
  clean           delete target/
  jar             source jar + pom
  jar-aot         AOT no-source jar (own .class + resources only)
  install         build + install to ~/.m2 (offline)
  kondo           sync dependency-exported lint configs, then lint
  bump            rewrite ./VERSION (:level :patch|:minor|:major)
  verify-license  report LICENSE / version.edn / SPDX agreement (warns)
  audit-opacity   report private strings a built jar still carries (warns)
  freeze-check    refuse a release that breaks ./freeze-policy.edn (fails)
  readme-examples run README.md's clojure blocks in a new JVM (fails)
  changelog       regenerate ./CHANGELOG.md from the release tags
  deploy          build + publish per :publish (no-op when :none)

Release flow (what CI runs on a push to main that touches src/deps):
  clojure -T:build bump :level :patch
  clojure -T:build deploy
raw docstring

hive-build.boundary.archive

Jar file effects: deterministic rewriting, and selective class extraction.

The decisions these functions act on live in hive-build.promote.naming; what is here is only the IO.

Jar file effects: deterministic rewriting, and selective class extraction.

The decisions these functions act on live in hive-build.promote.naming; what
is here is only the IO.
raw docstring

hive-build.boundary.freeze

Everything the freeze gate must read from the world: source text at HEAD and at the previous release tag, that tag's age, and this commit's message.

Isolated here so promote.freeze and promote.api-surface stay pure and testable without a repository.

Everything the freeze gate must read from the world: source text at HEAD and
at the previous release tag, that tag's age, and this commit's message.

Isolated here so `promote.freeze` and `promote.api-surface` stay pure and
testable without a repository.
raw docstring

hive-build.boundary.load-verify

Verify the built AOT jar in a fresh JVM containing only its declared dependency classpath. Provided/overlay dependencies are deliberately absent.

Verify the built AOT jar in a fresh JVM containing only its declared
dependency classpath. Provided/overlay dependencies are deliberately absent.
raw docstring

hive-build.boundary.run

Executes a Plan against a handler registry.

Knows nothing about tools.build. A handler is (fn [ctx step] -> result) keyed by :step/kind, which is the seam the whole suite exercises: substitute recording handlers and an entire release runs with no filesystem, no network, and no jar.

Executes a Plan against a handler registry.

Knows nothing about tools.build. A handler is (fn [ctx step] -> result)
keyed by :step/kind, which is the seam the whole suite exercises: substitute
recording handlers and an entire release runs with no filesystem, no
network, and no jar.
raw docstring

hive-build.boundary.tools

The tools.build adapter: gathers the Project and Facts a plan is computed from, and supplies the handler that executes each step kind.

This is the only namespace that knows tools.build and deps-deploy exist.

The tools.build adapter: gathers the Project and Facts a plan is computed
from, and supplies the handler that executes each step kind.

This is the only namespace that knows tools.build and deps-deploy exist.
raw docstring

hive-build.collect.git

Reads from the repository, through git.

Every function here is one effect and no decision. Nothing interprets what it reads, and nothing throws: a git that is absent, or a repository that has never released, answers the same way an empty result does.

Reads from the repository, through git.

Every function here is one effect and no decision. Nothing interprets what
it reads, and nothing throws: a git that is absent, or a repository that has
never released, answers the same way an empty result does.
raw docstring

hive-build.collect.io

Filesystem, environment and registry reads.

Every function here is one effect and no decision, so everything above this layer can be pure. Nothing in here interprets what it reads.

Filesystem, environment and registry reads.

Every function here is one effect and no decision, so everything above this
layer can be pure. Nothing in here interprets what it reads.
raw docstring

hive-build.collect.proc

Runs a child process. One effect, no decision, never throws.

The exit code is the answer; stdout and stderr ride along untrimmed so a caller can show a program's own report verbatim.

Runs a child process. One effect, no decision, never throws.

The exit code is the answer; stdout and stderr ride along untrimmed so a
caller can show a program's own report verbatim.
raw docstring

hive-build.pipeline.changelog

Tags plus reads become a Changelog value. Pure.

Every effect arrives as an injected function, so the whole assembly runs against maps in a test and against git in a release.

Tags plus reads become a Changelog value. Pure.

Every effect arrives as an injected function, so the whole assembly runs
against maps in a test and against git in a release.
raw docstring

hive-build.pipeline.plan

Task + Project + Facts -> Plan. Pure and total.

A release is a value before it is an effect. Everything read from the filesystem or the network already sits in facts, so the whole decision — which jar, whether to skip, what gets published where — can be asserted without building anything.

Adding a task is a new steps method; adding a destination is a publish/register!. Neither edits an existing branch.

Task + Project + Facts -> Plan. Pure and total.

A release is a value before it is an effect. Everything read from the
filesystem or the network already sits in `facts`, so the whole decision —
which jar, whether to skip, what gets published where — can be asserted
without building anything.

Adding a task is a new `steps` method; adding a destination is a
`publish/register!`. Neither edits an existing branch.
raw docstring

hive-build.promote.api-surface

A namespace's PUBLIC surface as data, and the difference between two of them.

Pure: takes already-read top-level forms, returns values.

Surface shape: {"ns/name" {:kind :def|:defn|:defmacro|:defprotocol|:defrecord :arities #{0 1 :variadic} :methods {"method" #{1 2}}}}

What counts as public: anything a downstream repo can compile against — defn/def/defmacro without ^:private (and not defn-), plus every protocol and its method arities. Private vars are excluded on purpose: they are not part of the contract and freezing them would freeze refactoring.

A namespace's PUBLIC surface as data, and the difference between two of them.

Pure: takes already-read top-level forms, returns values.

Surface shape:
  {"ns/name" {:kind :def|:defn|:defmacro|:defprotocol|:defrecord
               :arities #{0 1 :variadic}
               :methods {"method" #{1 2}}}}

What counts as public: anything a downstream repo can compile against —
`defn`/`def`/`defmacro` without ^:private (and not `defn-`), plus every
protocol and its method arities. Private vars are excluded on purpose: they
are not part of the contract and freezing them would freeze refactoring.
raw docstring

hive-build.promote.changelog

A CHANGELOG.md, rendered from release notes. Pure.

Keep a Changelog 1.1.0 shape over the Note value defined by hive-build.promote.notes, so the file and the storefront show one derivation of the same commits rather than two accounts of them.

The generated document is disposable: every release rewrites it in full. The prose a generator cannot derive (what the version number promises, how to migrate off a break, a deprecation window) is authored in changelog.d/<version>.md and spliced in here, never overwritten.

A CHANGELOG.md, rendered from release notes. Pure.

Keep a Changelog 1.1.0 shape over the Note value defined by
`hive-build.promote.notes`, so the file and the storefront show one
derivation of the same commits rather than two accounts of them.

The generated document is disposable: every release rewrites it in full.
The prose a generator cannot derive (what the version number promises, how
to migrate off a break, a deprecation window) is authored in
`changelog.d/<version>.md` and spliced in here, never overwritten.
raw docstring

hive-build.promote.classes

Compiled classes as values: which classes a .class file links against, and which of those links the jar does not satisfy. Pure.

An AOT jar that hardcodes implements hive_addon.protocol.IAddon builds and publishes in silence, then fails to mount because the host loaded that protocol from source under a different class identity. The link is visible in the constant pool long before anyone tries to mount it.

Compiled classes as values: which classes a .class file links against, and
which of those links the jar does not satisfy. Pure.

An AOT jar that hardcodes `implements hive_addon.protocol.IAddon` builds and
publishes in silence, then fails to mount because the host loaded that
protocol from source under a different class identity. The link is visible
in the constant pool long before anyone tries to mount it.
raw docstring

hive-build.promote.elide

Source-level metadata elision, applied to a staged copy of the sources before AOT. Pure: text in, text out.

The compiler's :elide-meta reaches def metadata only. An ns form's docstring is part of a constant map the ns macro emits, so it survives into the generated __init class verbatim.

Source-level metadata elision, applied to a staged copy of the sources
before AOT. Pure: text in, text out.

The compiler's :elide-meta reaches `def` metadata only. An `ns` form's
docstring is part of a constant map the ns macro emits, so it survives into
the generated __init class verbatim.
raw docstring

hive-build.promote.examples

README code blocks as executable claims. Pure.

A fenced ```clojure block in a markdown file claims that its code runs against this library, and a ;; => value line after a form claims what that form answers. blocks finds the claims, examples reads a block into forms paired with their claimed values, and script renders one Clojure program that evaluates them in order, names each before it runs, and exits non-zero when a form throws or answers something else. The program runs in a cold JVM at the boundary (hive-build.api/readme-examples), never in the session that wrote the README.

Add no-run to a fence's info string (```clojure no-run) to keep a block out of the run. Rationale: hive memory 20260907084849-421ab665.

README code blocks as executable claims. Pure.

A fenced ```clojure block in a markdown file claims that its code runs
against this library, and a `;; => value` line after a form claims what
that form answers. `blocks` finds the claims, `examples` reads a block into
forms paired with their claimed values, and `script` renders one Clojure
program that evaluates them in order, names each before it runs, and exits
non-zero when a form throws or answers something else. The program runs in
a cold JVM at the boundary (`hive-build.api/readme-examples`), never in the
session that wrote the README.

Add `no-run` to a fence's info string (```clojure no-run) to keep a block
out of the run. Rationale: hive memory 20260907084849-421ab665.
raw docstring

hive-build.promote.exclude

Jar-entry exclusion: which entries a version.edn :jar-excludes list claims, and which entries of a built jar violate it. Pure.

Jar-entry exclusion: which entries a version.edn :jar-excludes list claims,
and which entries of a built jar violate it. Pure.
raw docstring

hive-build.promote.freeze

The freeze policy, evaluated. Pure.

A contract library's whole value is that consumers can pin it and forget it. Two things destroy that: a change they cannot survive, and a cadence that makes them re-pin constantly. This namespace decides both from data.

Policy shape (./freeze-policy.edn in the repo being released):

{:policy/version 1 :cadence {:mode :scheduled | :on-merge :min-days-between-releases 90 :exception-marker "release-exception:"} :compatibility {:additive-only? true :break-marker "BREAKING-CHANGE:"}}

Contract: evaluate never throws and never consults the world — every observation (the diff, the age, the commit message) is passed in.

The freeze policy, evaluated. Pure.

A contract library's whole value is that consumers can pin it and forget it.
Two things destroy that: a change they cannot survive, and a cadence that
makes them re-pin constantly. This namespace decides both from data.

Policy shape (./freeze-policy.edn in the repo being released):

  {:policy/version 1
   :cadence {:mode :scheduled | :on-merge
             :min-days-between-releases 90
             :exception-marker "release-exception:"}
   :compatibility {:additive-only? true
                   :break-marker "BREAKING-CHANGE:"}}

Contract: `evaluate` never throws and never consults the world — every
observation (the diff, the age, the commit message) is passed in.
raw docstring

hive-build.promote.license

Licence agreement between ./LICENSE, version.edn :license and the SPDX headers in the source tree, as an open rule chain. Pure.

A rule returns nil when satisfied, else a message. Unlike an access decision, every rule runs: a licence report that stopped at the first problem would hide the rest, and a published pom can never be retracted.

Licence agreement between ./LICENSE, version.edn :license and the SPDX
headers in the source tree, as an open rule chain. Pure.

A rule returns nil when satisfied, else a message. Unlike an access
decision, every rule runs: a licence report that stopped at the first
problem would hide the rest, and a published pom can never be retracted.
raw docstring

hive-build.promote.lint

clj-kondo invocations as values. Pure.

Constructing the argument vector is where a lint task silently stops failing, so it is stated here and asserted rather than inlined at the process call.

clj-kondo invocations as values. Pure.

Constructing the argument vector is where a lint task silently stops
failing, so it is stated here and asserted rather than inlined at the
process call.
raw docstring

hive-build.promote.manifest

Addon manifests as values. Pure.

A hive addon ships resources/META-INF/hive-addons/<id>.edn describing itself. The version in that file is the one an addon store reads, so it is derived from the coordinate being built rather than hand-maintained.

Addon manifests as values. Pure.

A hive addon ships resources/META-INF/hive-addons/<id>.edn describing
itself. The version in that file is the one an addon store reads, so it is
derived from the coordinate being built rather than hand-maintained.
raw docstring

hive-build.promote.naming

Names derived from a coordinate: the Maven symbol, artifact paths, the registry URL a publish check probes, and the namespace/path correspondence AOT compilation depends on. Pure.

Names derived from a coordinate: the Maven symbol, artifact paths, the
registry URL a publish check probes, and the namespace/path correspondence
AOT compilation depends on. Pure.
raw docstring

hive-build.promote.notes

A release note, derived from the commits between two published versions. Pure.

The single definition of what a hive release note IS. Two projections read it: the CHANGELOG.md this library generates at release time, and the note hive-store shows a subscriber. Neither authors it, so neither can disagree with the other or with git.

It can be derived at all because two facts already hold:

  • a hive version names exactly one commit, through its tag
  • every published pom records that commit in <scm><tag>

What a READER is shown is not the whole log. A range of sixty commits is typically half housekeeping, and printing it all buries the seventeen fixes among thirty dependency bumps. The kinds a reader deciding whether to bump cares about are published; the rest are counted.

A release note, derived from the commits between two published versions. Pure.

The single definition of what a hive release note IS. Two projections read
it: the CHANGELOG.md this library generates at release time, and the note
hive-store shows a subscriber. Neither authors it, so neither can disagree
with the other or with git.

It can be derived at all because two facts already hold:

  - a hive version names exactly one commit, through its tag
  - every published pom records that commit in `<scm><tag>`

What a READER is shown is not the whole log. A range of sixty commits is
typically half housekeeping, and printing it all buries the seventeen fixes
among thirty dependency bumps. The kinds a reader deciding whether to bump
cares about are published; the rest are counted.
raw docstring

hive-build.promote.opacity

Does the built artifact still carry the vendor's words? Pure: the strings the sources declare secret go in, the strings the artifact carries go in, and the ones present in both come out.

An AOT jar is audited today for what it LINKS against (promote/classes). Nothing audited what it SAYS. :elide-meta removes def metadata and the staging pass removes the ns docstring, but neither is observed after the fact, so an elision that silently stops running publishes a readable jar and reports success.

The check is set intersection rather than a heuristic on purpose. A detector that scored strings for prose would have to guess whether "Resolve user-facing cartography intent into stable indexed-world data." is a leaked docstring or a :summary the program prints, and it is the second one. Only the source knows which strings were meant to be private, so the source is what supplies them.

Does the built artifact still carry the vendor's words? Pure: the strings the
sources declare secret go in, the strings the artifact carries go in, and the
ones present in both come out.

An AOT jar is audited today for what it LINKS against (`promote/classes`).
Nothing audited what it SAYS. `:elide-meta` removes `def` metadata and the
staging pass removes the ns docstring, but neither is observed after the
fact, so an elision that silently stops running publishes a readable jar and
reports success.

The check is set intersection rather than a heuristic on purpose. A detector
that scored strings for prose would have to guess whether
"Resolve user-facing cartography intent into stable indexed-world data." is
a leaked docstring or a `:summary` the program prints, and it is the second
one. Only the source knows which strings were meant to be private, so the
source is what supplies them.
raw docstring

hive-build.promote.pom

The parts of a pom hive-build decides rather than delegates: the declared licence, the dependency set, the source roots, the SCM tag and the repository set. Pure.

The parts of a pom hive-build decides rather than delegates: the declared
licence, the dependency set, the source roots, the SCM tag and the
repository set. Pure.
raw docstring

hive-build.promote.project

The Project value object: raw version.edn data plus a resolved version, with every default applied. Pure.

Nothing downstream reads version.edn again, so a default lives here exactly once.

The Project value object: raw version.edn data plus a resolved version, with
every default applied. Pure.

Nothing downstream reads version.edn again, so a default lives here exactly
once.
raw docstring

hive-build.promote.publish

Publish destinations as data, behind a registry. Pure.

The registry is the dependency-inversion point: plan and the boundary depend on the Target schema, never on a particular registry. A new destination is a register! and no edit anywhere else.

Publish destinations as data, behind a registry. Pure.

The registry is the dependency-inversion point: `plan` and the boundary
depend on the Target schema, never on a particular registry. A new
destination is a `register!` and no edit anywhere else.
raw docstring

hive-build.promote.reproducible

What must be rewritten INSIDE a jar for two builds of identical inputs to be byte-identical. Pure.

Fixing ZIP entry timestamps is not enough: build tooling also writes wall clock time and host details into entry content, where a timestamp rewrite cannot reach them. Each such source is a rule, so a newly discovered one is an addition rather than an edit.

What must be rewritten INSIDE a jar for two builds of identical inputs to be
byte-identical. Pure.

Fixing ZIP entry timestamps is not enough: build tooling also writes wall
clock time and host details into entry content, where a timestamp rewrite
cannot reach them. Each such source is a rule, so a newly discovered one is
an addition rather than an edit.
raw docstring

hive-build.promote.version

Semantic versions as values: parse, render, order, bump. Pure.

Semantic versions as values: parse, render, order, bump. Pure.
raw docstring

hive-build.schema

Malli value objects for the release domain.

Every hive-build contract is stated over these schemas, and the property and mutation facets of the suite are synthesized from them. This namespace has no dependencies beyond clojure.string: schemas are plain data.

Generation: schemas whose validity is a regex carry an explicit :gen/schema + :gen/fmap so a generator exists without test.chuck.

Malli value objects for the release domain.

Every hive-build contract is stated over these schemas, and the property and
mutation facets of the suite are synthesized from them. This namespace has
no dependencies beyond clojure.string: schemas are plain data.

Generation: schemas whose validity is a regex carry an explicit
`:gen/schema` + `:gen/fmap` so a generator exists without test.chuck.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close