The CLI, the environment, the record’s vocabulary, the status
projection and the files, in one place. The chapters explain; this
page lists. spec/dna.md
is the contract behind all of it.
hale dna --help prints every verb. Here the same lines are grouped by
the part each verb drives, word for word. Most verbs take the project
directory as an optional argument and default to the current one.
hale dna head [project] [--port P] [--api-port P] [--oidc-port P] [--commands-port P] [--source-drafts]
the head: the project service serving the browser face (8792), its API child, the stub
OpenID provider and, with a project, the reflexes — built once into the toolchain cache,
no checkout needed (from a checkout, dna/face/start.sh); with a project, the head's
memory DSN derived as `memory migrate` derives it (`hale dna head --help`)
hale dna ui [project] [--port N]
under `git config dna.principal oidc` a hosted head: sign-in through dna.oidc.issuer,
subjects mapped by dna.oidc.member, the secret the vault's oidc-client-<client>;
with no principal source it refuses to start (trusted-local is a test fixture's mode)
the DNA surface in a browser, from the record alone: the Board's queue, the Reviews
with their three views, the fleet, the history; verdicts, intent and pressure from forms
hale dna board [project] the Board's queue: what needs its verdict, escalations, proposals, reports
hale dna review the pending Reviews
hale dna review <id> [--iris] render a Review: source diff, semantic diff, evidence (works offline)
hale dna review <family> approve|reject
decide every pending Review of a group in turn: purpose, design, operating, using, library, holes, practices, holds, positions, changes, ingest (a library family is one Review for all its ideas)
hale dna review all approve|reject
every group with a pending Review, in the order a new organization is ratified, each waited for before the next
hale dna review <id> approve|revise|reject|abstain [--as <reviewer>] [--authority <a>] [--comment <c>] [--digest <sha>] [--no-wait]
write a verdict into the record, which a node relays; the Review decides
hale dna route [--json] (<path>… | --diff <range>)
who must sign a change set, and the gates it is judged against
hale dna github sync mirror pending Reviews to pull requests and read their reviews back as verdicts
hale dna task create [--to <locus>|position:<name>] [--as <who>] [--judgment] [--size quick|standard|deep] [--no-wait] <outcome…>
ask for an outcome (--judgment: an assessment, a leg's to perform; --to position:<name>: a change the leg holding that position makes): a row in the record, which a node relays to the organism; prints the Task born or the refusal
(on an adopted ledger it prints the request's digest: see `hale dna ledger`)
hale dna task done <id> a person reports a handed Task done (--as <who>, --note …); `task reassign <id> --to <who>`
under an acceptance practice requiring evidence: --evidence <digest>, or --exception <why> --authorized-by <who>
hale dna task authorize <id> --exception <why> authorize an exception, in your name (not the assignee's)
hale dna task decide <id> report a decision someone else made (--decided-by <party> --via <channel> --evidence <digest>, --as <reporter>)
hale dna retire <who> a person retires: the handed Tasks they hold move to --to <successor>, as rows
The variables you set yourself. Everything else the CLI and the body
set for the processes they start.
variable
what it does
HALE_DNA_MEMORY_DSN_OWNER
a Postgres of your own instead of dna/compose.yaml’s: the owner role that migrates memory (memory migrate, dev, show)
HALE_DNA_NATS_URL_OWNER
a NATS server of your own instead of compose’s: the owner user that creates the stream (nerves migrate, dev)
HALE_DNA_MEMORY_DSN_SPINE
the spine role’s DSN, which hale dna run needs; memory migrate prints it
HALE_DNA_NATS_URL_SPINE, HALE_DNA_NATS_ORG
the spine’s nerves URL and the organization’s token, which hale dna run needs; nerves migrate prints them
HALE_DNA_MEMORY_DSN_HEAD
the head role’s DSN, for a head and nothing else; memory migrate prints it
HALE_DNA_RECEIPT_KEY
sixteen characters or more: the key protected evidence is sealed under, given to memory migrate once
HALE_DNA_OWNER_KEYS
<owner>=<key> …: the owners of a shared record, for memory migrate
HALE_DNA_API, HALE_DNA_ID_TOKEN
the head a leg’s hale dna work verbs talk to without --api, and the bearer token it presents
HALE_DNA_GENOME_POLL
seconds between polls of the record’s remote for a changed genome (300)
HALE_DNA_NO_BUILD_CACHE
build every seed, instead of reusing a build of the same sources
HALE_VAULT_DIR, HALE_VAULT_ADDR, HALE_VAULT_TOKEN
where the vault is: a local directory, or a vault’s HTTP API and its token
Every HALE_DNA_* variable, with its default and effect, is in the
spec’s Environment
table; a test fails when the tree names one the table does not. The
vault’s three are in the runtime’s
environment table.
The record’s settings live in the clone’s git config:
key
what it does
dna.remote
the remote the record syncs with (origin when unset)
dna.trust
local (every writer to the record is trusted) or signed (a relayed row needs a verified signature)
dna.owner
on a shared record, the organization this body is
dna.body
<user@host>, set by body provision (or new --body): where body start, stop, logs and secret set go without --body
dna.unix.member
uid:<n>=<name>: who a local uid is, for the head’s socket
Every row has a kind, an entity, a body and an author. The memory
column is where the row lives once the ledger is adopted: record is
git (refs/dna/journal), ledger is memory (Postgres). Before
adoption every row is the record’s, and the two are read as one
sequence either way (Memory and the record). The table
in dna/core/routing.hl (memory_of) decides. A reader that meets a
kind it does not know keeps walking.
the compiler’s model of one of the application’s parts, at init
graph.node / graph.edge / graph.retired
record
a node of the repository’s graph; a hyperedge of it; one leaving it (also inside a ratified graph proposal’s receipt)
graph.ingested
record
hale dna ingest read the repository at a commit (added, changed, retired, the review_id of its proposal)
graph.requested / graph.proposed / graph.refused
record
hale dna ingest asks the running organization to open its Review; opened, or not. graph.refused <row id> with by: memory is a graph row memory would not project; the projection goes on past it
model.rule
record
the size a selector’s Work needs, and the sizes a more specific selector may move it to (hale dna models rule, task create --size)
model.category
record
which model fills <mode>.<size>, whether it returns tool calls, and its price (hale dna models category)
responsibility.proposed
record
a one-line responsibility inferred for a part, not yet ratified
candidate.dropped
record
a kept candidate is no longer kept, here and at every clone’s sync
ledger.adopting / ledger.adopted
record
the move of the day’s work into the ledger asked for, and done at a checkpoint
ledger.abandoning / ledger.abandoned
record
its undoing asked for, and done
receipt.filed
ledger
an internal document filed as evidence
receipt.classified / receipt.withheld
ledger
a protected body memory keeps sealed, or one withheld because no memory could keep it
receipt.disclosed
ledger
a reader authorized, for a purpose
receipt.read / receipt.read_refused
ledger
a read in the reader’s name, or its refusal
receipt.held / receipt.hold_released
ledger
a hold that refuses redaction, and its release
receipt.redacted
ledger
the body removed, the digest kept
connection.proposed / connection.closed
record
a connection to another record, for the Board; and its closing
handoff.published / handoff.refused
ledger
a fact written into a connected record, or why not
handoff.received
ledger
an envelope in the receiving record’s mailbox
handoff.accepted / handoff.accepted_by_peer
ledger
an acceptance in the receiving record, and its admission back in the origin
task.transfer_requested / task.transfer_accepted
ledger
a Task offered across a connection or to another owner, and accepted
the evidence a completion links, or the exception it carries
exception.authorized
ledger
an exception to a Task’s acceptance, in the authorizer’s name
decision.reported
ledger
a decision someone else made, reported by the assignee
person.retired
record
someone left, and who took their work
hold.requested / hold.proposed / hold.refused
record
a holder asked for a position (hale dna fill), proposed to the Board, or refused
batch.proposed
record
a batch hale dna apply proposed as one Review in changes, with its steps (and planned_on, the pending Reviews it was planned on); graph.requested under the same id asks the organization to open it
The projection status prints, as one JSON document on one line;
hale dna ui serves the same at /api/status. Here it is for a fresh project with nothing
running, indented, with twenty-two of its twenty-three pending Reviews cut:
organism is running (this clone's body holds the lease) when a body
here holds the lease. chain is verified or BROKEN. As the
organism works, the arrays fill:
a task: id, outcome, state, since, and detail when there is
one;
a settled Review adds settled (and reasoned); a Mutation’s Review
adds mutation_id, change_class, seed, disposition,
base_commit, candidate_commit, candidate_shape, evidence,
magnitude, diff_text, diff_json and author;
a Mutation: id, candidate, disposition, class, task,
objective, detail and worktree when set, and its events;
last_restart_request and last_observed: mutation, what,
seq.
the record’s identity; a sync publishes it to the remote
refs/dna/lease/<key>
leases with fencing tokens; refs/dna/lease/body is the body lease
refs/dna/candidates/<mutation>
a Mutation’s candidate, kept whatever its Review decided
refs/dna/revisions/<rev>
a revision a deploy asked the nodes to express
refs/dna/exchange/<identity>
a connected record’s mailbox in this one
refs/dna/remote/…
what the last fetch brought from the remote (journal, lease/body, genome)
.git/config
the record’s settings (dna.trust, dna.unix.member, … above)
.hale/dna/
this clone’s scratch: status.json, the organization’s log org.log, the topology artifacts, embedded.digest, the seed build cache build/, sandboxes worktrees/, scratch/, the built leg legs/, a person’s kept worktrees work/<attempt>, an ingest’s checkout ingest/<sha>/ (removed after)
.hale/node/<name>/
on a node: its instances’ pid files and artifacts
memory
Postgres, schema dna_<record identity>: the ledger, the graph and protected evidence, under the spine’s and the head’s roles
the nerves
one JetStream stream per organization, named after its token in capitals
the vault
HALE_VAULT_DIR, else $XDG_CACHE_HOME/hale/vault, else ~/.cache/hale/vault; one file per secret, mode 600. HALE_VAULT_ADDR names a vault’s HTTP API instead
HALE_DNA_HEAD_STATE
the project head’s state (${XDG_STATE_HOME:-$HOME/.local/state}/hale/dna/head when unset)
Once the ledger is adopted, the day’s work is in memory, not in
refs/dna/journal; hale dna ledger status says where things stand.
hale dna secrets lists every vault entry the organism needs.