Reference implementation behavior
Behavior that is specific to dk0 and may differ in other implementations.
Workspace directories
Section titled “Workspace directories”dk0 keeps its durable workspace configuration under etc/dk/ (transient
build state lives under t/; see the Configuration and Security options for
the t/d, t/c and t/k defaults). dk0 drops a self-ignoring .gitignore
(*) into t/ and each of its build directories, so a project keeps its t/
tree out of git without a hand-written /t/ line. The etc/dk/ directories
are:
| Directory | Contents | Written by | Read for |
|---|---|---|---|
etc/dk/d | Prepared distribution keys: <MAJOR.MINOR>.<PATCH>.dist.json files carrying the producer public key and signed continuations for the version lines this workspace releases. Author-owned; commit them. | prepare-version | distribute and combine (signing); every import (the keys are locally prepared trust anchors). |
etc/dk/i | The import directory: verified release <LIBRARY>.<VERSION>.values.json files, plus the values.unattested.json download scratch file. On the workspace include path, so the imported distributions resolve values and traces. The files double as prior-import trust anchors. Machine-written but committable, so a clone can carry them for clone-and-build (see "Committing imports for clone-and-build repositories"); update garbage-collects entries its resolution no longer uses, and an import prunes the strictly older releases it supersedes on the same MAJOR.MINOR line. | add, import, restore, and workspace import declarations | distribution resolution; prior-import trust anchoring. |
etc/dk/t | Consumer trust records. Four kinds: (1) byte-identical copies of directly imported release values files (<LIBRARY>.<VERSION>.values.json), recorded only after the consumer trust checks pass; (2) imports.json, the machine-written import ledger. Each entry records a values_sha256 (SHA-256 of the dos2unix-ed content) that an import/restore verification accepted, its kind (record for the imported values.json file, or scriptmodule for an exported values.lua whose hash the producer signed into build_to_sign.build_script_module_sha256s), and the distribution's producer pubkey_base64. A rule whose run-time content SHA matches a keyed entry is attributed to that producer; (3) capabilities.json, the human-authorized request.ui capability grants (run, write) keyed by producer public key (pubkey_base64) or by local values content (values_sha256); (4) acceptances.json, the durable dk0 trust accept records keyed by package name, each carrying an optional pinned producer key and optional pending capabilities that become grants at the first successful import. A .gitignore written by dk0 keeps the machine-written records (1) and (2) out of git while leaving capabilities.json and acceptances.json committable so a repository can carry its trust decisions into CI. Deliberately not an include directory, so no values or traces are ever resolved from a record; a record only anchors the producer key and rotation of later imports, gates producer-key grants (ledger), carries grants, or carries acceptances. | import local (record copies); every import/restore (ledger, and acceptance resolution); trust grant and the capability prompt's [a]lways answer (grants); trust accept (acceptances) | prior-import trust anchoring; producer-key grant activation (ledger); request.ui capability decisions (grants); import-time key acceptance (acceptances). |
etc/dk/v | Authored values files (*.values.jsonc, *.values.lua) belonging to the workspace. On the workspace include path. distribute seals them into the distribution manifest together with the workspace script and dist/*.u. | the workspace author | distribution resolution; manifest sealing. |
Lua interpreter
Section titled “Lua interpreter”dk0 uses a pure-OCaml version of Lua (lua-ml), which is fully type-safe,
re-entrant, and can have Lua evaluations bounded in time and
sandboxed to the project directories. The internal table of packages is stored in
an OCaml analog of the Lua C registry.
- Lua scripts should minimize the use of global variables.
dk0does not yet enforce the complete removal of global variables, but it will in the future. - bug:
string.len( "a\000bc000" )is 9 indk0(https://github.com/diskuv/dk/issues/54).
Limits and platform quirks
Section titled “Limits and platform quirks”- A few internal buffers are bounded by
dk0'sSys.max_string_lengthlimit on 32-bit systems. - The byte positions, lines and columns embedded in the AST for error reporting
are Unix byte positions. On Windows the byte positions may be inaccurate if the
JSON file is checked out by
gitwith CRLF endings; this may be fixed ifdk0moves exclusively to lines and columns. dk0only recognizes theOSFamilyproperty (as of 2025-11-09).- The
execution_abiwildcard defaults to the ABI of this build executable; it can be set bydk0(see--execution-abi).
Change detection
Section titled “Change detection”An implementation chooses how it detects changes to the globbed files. dk0
scans all the globs at startup, with optimizations to skip directories it can
prove will never match a glob. Invalidation can be forced with the --invalidate TARGET global option.
Reading an asset index
Section titled “Reading an asset index”dk0 loads the index file for an asset once per command and gives every later
request in that command that same index.
dk0 keys that index on (values_file_sha256, form, index-asset-key):
values_file_sha256is the SHA256 of the values file (V256) that declares the asset, as the specification defines it.formis the value type letter of that values file,jfor a values.json file andlfor a values.lua file.index-asset-keyis the key of the index asset.
Under that key dk0 stores four things in memory: the i value id, that
value's SHA-256, the index file the value id names, and the dependency fetches
the first load made. dk0 stores that entry after the load finishes. A load
that reports pending stores nothing, and the requesting task asks again when it
runs again. dk0 frees the entry when the command ends.
dk0 still re-runs the cheap dependency fetch, so the calling task's recorded
trace is identical to what it would have been without the memo. Before dk0
gives a task an index it loaded earlier in the command, it fetches for that task
the same dependencies the first load fetched, in the same order.
Reusing a resolved redirect
Section titled “Reusing a resolved redirect”A remote asset is often served through redirects: the origin answers one, a
content delivery network answers another, and only the last response carries
bytes. dk0 reads one byte range per request, so a command reading several
ranges of one asset repeats that chain on every range.
dk0 remembers the target the redirects resolved to, keyed by the origin URL it
asked for, and sends the next range of that asset straight to that target. It
remembers a target only when the response carrying bytes followed a redirect, so
a URL that never redirects is requested exactly as it was before.
A resolved target is short lived, because a store usually signs it with an
expiry. dk0 keeps one for at most 60 seconds. On any response other than
success it forgets the target and repeats the request against the origin URL,
which is what a first request would have done.
Reading the value stores of a lazy import
Section titled “Reading the value stores of a lazy import”dk0 --import lazy reads the value stores a command needs by the rule in
Reading the value stores a lazy import needs. A part name ends in an ABI
name when its last dash-separated term is one of Android_arm32v7a,
Android_arm64v8a, Android_x86, Android_x86_64, Darwin_arm64,
Darwin_x86_64, DragonFly_x86_64, FreeBSD_x86_64, Linux_arm32v6,
Linux_arm32v7, Linux_arm64, Linux_x86, Linux_x86_64,
Linux_x86_64_musl, NetBSD_x86_64, OpenBSD_x86_64, Windows_arm32,
Windows_arm64, Windows_x86, Windows_x86_64, Js_nodejs or Js_web.
- Under
-d perf,dk0printsimport narrowed distribution=PACKAGE kept=K dropped=Dwhen the request slot leavesDof the distribution's value stores unread. - Under
-d perf,dk0printsimport widened distribution=PACKAGE (missing pointer)when a key with no lazy value file makes it read every value store of the distribution. - Under
-d perf,dk0printsimport widened distribution=PACKAGE (script module values file)when a script module's values file is in none of the value stores it read, and it then reads every value store of the distribution.
Reading an entry through an asset index
Section titled “Reading an entry through an asset index”A value store zip is published by the distribution, and each value in it is one
entry of that zip. A lazy import records a pointer to an entry, and dk0 reads
that entry with byte range requests to the asset when a command first needs the
value. The index file of the asset tells dk0 where the entry starts and how
large it is.
dk0sends one byte range request for each entry. The range starts at the entry's local file header and covers its file name, its extra field and its compressed data.dk0sizes that range from the entry's record in the central directory of the index, adds up to 128 bytes of padding, and ends the range no later than the end of the asset.- When the entry's local file header is longer than that size allows,
dk0reads the compressed data with a second byte range request.
Assets and the library cell
Section titled “Assets and the library cell”When a unified.asset declaration runs, the origin is named after the library id
and its mirrors are set to the library cell. In dk0:
- when run with a directory-based unified script (e.g.
dk0 test unifiedscript.u/), the library cell is set to the unified-script directory while the script is evaluated - when the unified script being evaluated is the workspace script, the library cell is set to the directory containing the workspace script
- the
dk0 combinecommand can adjust the mirrors permanently during distribution.
In the workspace, asset libraries are implicitly trusted, so no
--trust-local-package ASSET_LIBRARY is needed to access the workspace assets.
Distributions
Section titled “Distributions”dk0 addplaces distribution metadata in the source tree at<workspace>/etc/dk/i/<LIBRARY>-<VERSION>.values.json.dk0 addplaces lazy value files in the value store by default, to avoid the time and space to download every binary artifact from a distribution.dk0 adddownloads an internal copy of the GitHub CLI and uses it to download from GitHub releases and validate attestations.dk0accepts only the JSON request derived from command-line name-values. There is no ability today to accept the form document directly from an HTML form (per the W3C HTML JSON Forms specification) or a JSON document.
Values
Section titled “Values”- A
values.luafile added to the valuestore is an in-memory file indk0.
Other behavior
Section titled “Other behavior”- Before submitting work,
dk0prints the resolved inner argument vector (it can pass the exact argument vector to a subshell/remote engine). dk0asks for confirmation before a rule runs a program or writes a file, unless a matching capability grant is recorded (dk0 trust grantor a prior[a]lwaysanswer; see Security).