CLI reference¶
assent is a single static binary. Every command below is dispatched by the shipped
binary — this page is pinned to the binary's own help table by a test, so it cannot
drift from the tool.
Install it first (see Install), then check what you have:
assent version
Help output¶
assent --help (also -h, -help, help) prints the command listing on stdout
and exits 0. A bare assent, or an unknown command, prints the same listing on
stderr and exits 2 — the contract wrapper scripts rely on.
assent — deterministic, policy-driven auto-merge for self-service repositories
Usage:
assent <command> [arguments]
Commands:
run
Evaluate a merge request against its policy and reconcile the decision on the forge
usage: GITLAB_TOKEN=<pat> assent run --project <id> --mr <iid> --subject file:<path> --bot-author <user> [flags]
doctor
Report whether this environment can arm auto-merge, and why not when it cannot
usage: assent doctor
lint
Check a repository's .assent/** policy tree for hard errors
usage: assent lint <dir>
test
Run a repository's .assent/tests/** adopter cases against the real engine
usage: assent test [--update] [--coverage] <repo>
compare
Replay a comparison suite of baseline vs candidate policy and apply the promotion gates
usage: assent compare <dir> | assent compare --suite <dir>
catalogue
Emit the generated rule catalogue for a policy tree as JSON on stdout
usage: assent catalogue <dir>
render
Render a committed finding fixture as markdown for local preview
usage: assent render --finding examples/render/<case> [--artifact finding-thread|summary] [--presentation-minimal|--presentation-full]
eval-input
Assemble the EvaluationInput and pinned SHAs from the CI environment
usage: assent eval-input
version
Print the assent version
usage: assent version
help
Print this help listing
usage: assent help
assent run -h, assent compare -h and assent render -h list their flags.
Full command reference: https://platformrelay.github.io/assent/usage/cli/
assent run¶
Evaluate a merge request against its policy and reconcile the decision on the forge:
read the MR, load the policy from the target ref, diff → classify → aggregate →
build and schema-validate the DecisionRecord, emit the record, then reconcile against
GitLab. The record is emitted before any forge write, so a run whose emit fails
aborts without touching the forge (D-122 — no record, no action).
GITLAB_TOKEN=<pat> assent run --project <id> --mr <iid> --subject file:<path> --bot-author <user> [flags]
The GitLab personal access token is read from the GITLAB_TOKEN environment variable
and is never a flag; without it the command exits 2 before contacting the forge.
assent run -h prints the same flag list.
| Flag | Default | Meaning |
|---|---|---|
-project |
— | GitLab numeric project id (required) |
-mr |
— | merge-request IID (required) |
-subject |
— | governed-subject entryRef (file:<path>) — the file diffed for evaluation (required) |
-bot-author |
— | bot username for the author-identity filter (required) |
-gitlab-endpoint |
https://gitlab.com |
GitLab instance base URL |
-policy |
.assent/merge-policy.yaml |
MergePolicy path, loaded from the target ref |
-binding |
.assent/ruleset-binding.yaml |
RulesetBinding path, loaded from the target ref |
-config |
— | optional Config path; when set, provider posture is validated |
-pack |
— | optional Pack path; its spec.phase caps every rule's phase |
-checkout |
— | local checkout dir (base/ + head/ subtrees) used to enumerate the MR's full changed-file set; when unset, the forge snapshot is the sole enumerator (see below) |
-emit |
stdout | path to write the DecisionRecord JSON |
-arm |
off | sandbox arming override — approve and merge only when set and the decision is APPROVE |
Exit codes: 0 the run completed and produced a valid receipt (an advisory
REVIEW/BLOCK, or an APPROVE without --arm, is still a clean 0); 1 a hard error
during orchestration; 2 a missing flag, a missing GITLAB_TOKEN, or -h.
Checkout-less runs and enumeration completeness¶
Without -checkout, the forge snapshot's changed-file list is the only thing that can
see a .assent/** policy edit outside the governed subject — so an incomplete list
would silently starve the self-edit guard. Per ADR-0020
the adapter must therefore prove completeness (paginated /diffs, cross-checked
against the MR's changes_count, below a page ceiling). When it cannot, the run does
not guess and does not fail silently: the change set is marked opaque and the decision
degrades to REVIEW with finding code changeset.undecidable, carrying the gap
reason. A DecisionRecord is still emitted and a thread still posted; approve and
merge are impossible on that path. A .assent/** path that is visible in a partial
list still dominates to BLOCK.
With -checkout the local tree is the sole authority (D-077) and snapshot completeness
is not consulted.
assent doctor¶
Report whether this environment can arm auto-merge, and why not when it cannot.
assent doctor
With GITLAB_TOKEN set (plus CI_PROJECT_ID and CI_MERGE_REQUEST_IID) it probes the
forge for verified capabilities. Without a token it falls back to an env-only
diagnostic and prints an explicit INSECURE banner, because env self-assertions are
spoofable by an author-editable CI job.
Exit codes: 0 arming precondition met; 1 not armed (each blocking reason is
listed); 2 the forge probe could not run.
assent lint¶
Check a repository's .assent/** policy tree for hard errors. The directory argument
is the repository root — assent joins .assent itself.
assent lint <dir>
Exit codes: 0 no error diagnostics; 1 at least one error diagnostic; 2 usage or
discovery failure.
assent test¶
Run a repository's .assent/tests/** adopter cases against the real engine: each case
diffs its base/ ↔ head/ trees with the production differ, stubs facts.yaml into
the resolved-fact envelope, evaluates the pack, and asserts the produced decision
equals expect.yaml.
assent test [--update] [--coverage] <repo>
| Flag | Meaning |
|---|---|
--update |
rewrite each failing case's expect.yaml from the produced actual. Refused when a CI environment variable is set — auto-accepting actuals in CI would ratify a regression. Run it locally and review the diff. |
--coverage |
read-only both-polarity completeness gate. Never writes goldens, and supersedes --update when both are passed. |
Exit codes: 0 every case matched (or, under --update, every failing case was
refreshed); 1 a mismatch, write or load error; 2 usage, discovery or CI-guard
refusal.
assent compare¶
Replay a comparison suite of baseline vs candidate policy and apply the promotion gates: load immutable replay bundles, evaluate both sides through the same engine, classify the deltas, and gate the promotion.
assent compare <dir> | assent compare --suite <dir>
| Flag | Meaning |
|---|---|
--suite |
PolicyComparisonSuite directory, or a suite.yaml/suite.json path |
--baseline-profile |
baseline PolicyProfile name (overrides the suite default) |
--candidate-profile |
candidate PolicyProfile name (overrides the suite default) |
--record |
directory to write one ComparisonRecord JSON per case id |
Exit codes are the promotion-gate contract: 0 all gates pass; 1 a missed
destructive change; 2 a missed authorization/ownership change; 3 an unexpected
obligation removal; 4 auto-merge widening beyond the bound; 5 deltas that were not
explicitly accepted; 6 fail-closed — a load, schema, digest or classification error.
Two paths sit outside that contract and are easy to misread. 6 is also what an
unreadable or missing input directory returns, so a wrapper invoking
assent compare "$DIR" with $DIR unset reports fail-closed rather than a usage
error — check the stderr message before assuming a classification failure. And
assent compare -h prints the flag list and exits 0, which here means "help was
printed", not "all gates pass".
assent catalogue¶
Emit the generated rule catalogue for a policy tree as JSON on stdout, for the docs
pipeline. Catalogue generation is a docs artifact, not a gate, so it is a separate
command rather than a lint flag.
assent catalogue <dir>
Exit codes: 0 catalogue emitted; 2 usage, discovery or load failure.
assent render¶
Render a committed finding fixture as markdown for local preview, without a live merge request.
assent render --finding examples/render/<case> [--artifact finding-thread|summary] [--presentation-minimal|--presentation-full]
| Flag | Default | Meaning |
|---|---|---|
-finding |
— | render fixture directory under examples/render/<case> (required) |
-artifact |
finding-thread |
artifact to render: finding-thread or summary |
-presentation-minimal |
off | omit evaluation details (verbosity minimal) |
-presentation-full |
off | show all evaluation detail blocks (verbosity full) |
Exit codes: 0 markdown emitted; 1 the fixture failed to load or validate; 2 a
usage error.
assent eval-input¶
Assemble the EvaluationInput and pinned SHAs from the CI environment and print a one-line summary. This is the CI-adapter smoke path: it proves the environment boundary end-to-end without touching a policy.
assent eval-input
Exit codes: 0 assembled; 1 a required CI variable is missing or empty.
assent version¶
Print the assent version.
assent version
Release archives and the Homebrew build stamp the real semver at link time. A binary
built with go install reports 0.0.0-dev — see Install.
assent help¶
Print the command listing shown above on stdout and exit 0.
assent help