Key terms desk roster claim evidence three-state

assay · methodology · the layer between the desks and the forge

Desk tools

The desk tools are the only sanctioned way an agent session writes to the forge. Each one is a single workflow verb with its policy compiled in: which role may run it, on which repositories, how often, and what it refuses. They are not a wrapper over the forge's CLI. A session holding a role's credential and calling the forge directly gets none of the guards below and can perform any write the credential allows; the same session going through a verb gets an audit line, a rate meter, a body scan, an enumerated operation set, and a refusal it must respect. The credential is a ceiling. The verbs are the control.

Write classes3read-only · outward-write · local-only
Exit codes5ok · disabled · rate-limited · refused · unverifiable
Forge operations15enumerated on the seam
Raw passthrough0no generic call, no caller-supplied endpoint

The verbs, by role

One binary per verb, named for what it does. Read the table by class: read-only verbs only query the forge and print; outward-write verbs can change something on the forge and are the only ones the write meters gate; local-only verbs touch state under your own configuration home. Every verb echoes its effective configuration before its output, so a widened repository scope shows up in run output rather than in someone's memory.

RoleVerbsWhat they do, and what they refuse
every desk desktoken, deskboard, statusgen desktoken <role> mints or reuses a short-lived installation token for one role; deskboard reads the open pull requests, checks, and queue across the configured repositories and writes nothing; statusgen generates and lints the board and runs a brief's Verify table.
worker deskpr, deskreply, deskfile deskpr create opens a pull request draft-only by construction: the draft flag is hardcoded into the command it builds and there is no flag to remove it, no force-push it can emit, and no ready, close, or merge verb anywhere in the toolset. deskpr update pushes follow-ups; deskpr edit corrects the body. deskreply comments only on the worker's own pull request. deskfile new files an issue after a dedupe search, as the role.
worker-desk deskdispatch Claims one item through a durable, shared claim marker (a second dispatcher asking for the same item is refused), cuts an isolated checkout in the item's own repository, assembles the worker prompt, and records the model-tier stamp. A brief carrying a human gate is still dispatched: the gate binds approval, not implementation.
pr-review-desk deskpost, deskflip, deskmerge, deskclose deskpost review posts the verdict under the reviewer identity, which the implementer cannot hold. deskflip flips draft to ready and refuses unless the reviewer approved at the current head, checks are green, the pull request is mergeable, a risk-classed change carries a security verdict at head, and the caller is the review role. deskmerge check reports merge-currency in three states; deskmerge merge merges main into a branch, never a branch into main. deskclose closes an issue only on a fetched human authorization or a two-role propose-and-confirm.
verify-desk deskevidence, statusgen deskevidence commit lands an Evidence row through the forge's contents API as the verifier identity, so the row names who ran it and the author could not have written it. statusgen's execution witness re-runs the Verify table and records a three-state result per row.
intake-desk deskfile, deskclose, scanloop Files exactly one tracked exit per inbound item, applies the trust gate before anything is queued, and batches the mechanical scan behind one branch and one pull request per pass.
the-desk deskpr, deskfile, deskrelease Authors briefs and files findings through the same write verbs as everyone else. deskrelease cut creates a tag and can only create; it never moves or deletes one.

The named verbs above are the everyday surface. The full toolset is larger (loop planners, the claim lock, worktree and fetch verbs, the guards installed as git and harness hooks), and the reference for all of it is the desk-tools README in the public repository, which is the authority when this page and it disagree.

The read path

The desk tools are the only sanctioned write path to the forge. Reads are a different question, because a read cannot change the record, so the rule is looser and there are three lanes:

LaneWhat reads through itCredential
Desk read-only verbs The board and queue reads a desk makes before it acts: deskboard, statusgen board reads, the verify loop's plan, the dispatcher's pre-claim reads. Through the Forge seam, so the same enumerated operations and the same refusals apply. The role's App token, read scopes only.
git itself The canonical board read is git fetch followed by git show FETCH_HEAD:<path>. Briefs, registers and the board are read from the default branch, never from a worktree that may be stale or mid-edit. None on a public repository; the checkout's own fetch credential on a private one.
The operator's forge CLI, reads only gh pr view, run logs, API GETs. Permitted to humans and sessions alike, because a read cannot change the record; forbidden for any write, because a write under a personal login is exactly the workaround the role identities exist to close. Whatever the shell already holds; never used to write.

The rule in one sentence: writes go through a role identity and a policy verb; reads may use anything.

The honest wrinkle: the third lane holds capability the role identities do not carry today. CI run logs need an Actions read grant that the worker identity does not hold, so a session shepherding a red check reads the log through the operator's CLI rather than through a verb. That asymmetry is known and is why a read-path verb for run logs is on the roadmap: the target is that every read a desk depends on is available under its own identity, so the ambient lane becomes a convenience rather than a dependency.

The policy layer

Five mechanisms, each compiled into every outward-write verb rather than asked of the session running it.

  1. Role identities

    Every write is made as a role, never as a person and never as an ambient login. desktoken mints a short-lived token from the role's App key and the verb acts as that identity; a verdict posted by the reviewer role names an identity the worker role cannot post as. That is separation of attribution, and it is the weaker claim the stronger ones rest on. On GitHub the roles are Apps; on GitLab, service accounts (see the GitLab profile).

  2. Three-state verdicts

    Every check reports checked-clean, checked-failed, or could-not-check, and the third is never rounded to either of the other two. A verifier that cannot reach a sibling repository, a preflight whose token will not mint, a push guard that cannot determine the base branch: each says so, in those words, and the desks treat could-not-check as a stop, not a pass.

  3. Refusals, with exit codes

    A verb that will not do what it was asked says why on one line and exits with a code that tells the caller what to do next. The distinction that matters is 5 against 6: a refusal is the tool saying the thing is not allowed, and reaching for the raw CLI to do it anyway is defeating a gate, not routing around a bug; unverifiable is the tool saying it could not tell, which is the one case where a documented fallback is authorised.

    ExitMeaningWhat the caller does
    0ok, or an idempotent no-opnothing: it worked, or it had already been done
    3disabled: a kill switch or stop flag is armedstop; a human clears the flag
    4rate-limited: a write meter or the breaker is openread retry-after, sleep it once, attempt once; never poll
    5refused: a deliberate safety stopstop and fix the input; never a fallback trigger
    6unverifiable: the tool could not confirm statethe documented fallback for that verb, and only that
  4. Budgets and breakers

    Every outward-write verb runs behind two write meters (a rolling hourly budget per verb, charged only on a write that lands) and a circuit breaker that opens on a run of failures. A session that loops on a failing write is stopped by the meter, not by its own good judgement, and the audit line records the attempt either way. The limits are the toolset's own, set below the forge's, so the forge's rate limit is never the first thing that trips.

  5. Human gates

    No verb merges a pull request into the default branch. No verb approves the author's own work; the forge refuses that too. No verb creates an App, changes a ruleset, or alters repository administration. deskflip makes a draft ready and stops; deskclose closes only on a human authorization it can fetch; deskmerge merge is gated on a fetched human sign-off and, unsigned, merges nothing. The tools are built so that the decisions which are yours cannot be taken for you, and a session that reaches for the forge's CLI to take one anyway is stepping outside the toolset, visibly.

The Forge seam

Every verb reaches the forge through one interface, and that interface is deliberately closed: fifteen enumerated operations, no generic call, no caller-supplied endpoint, and a continuous-integration check that refuses a shell-exec or passthrough shape anywhere in the tree. A new forge is a new backend behind the same interface; the verbs, their guards, and the desks above them do not change.

Forge
  GetPullRequest        GetIssue            OpenChangeForBranch
  SearchIssues          ListLabels          ListOpenChanges
  ListOpenIssues        ListChangedFiles    ReviewsAtHead
  ChecksAtHead          PRTrustEvents       IssueTrustEvents
  ...                   (writes: comment, review, flip, file, close, evidence)
  no Do(), no Raw(), no endpoint argument

The seam is what makes the coverage numbers on the layers page measurable at all: an operation is either on the interface with a backend for a given forge, on it with a partial backend, or not on it. There is no fourth state where a verb quietly does its own HTTP.

Limits, stated

GitHub first. The fleet that builds Assay runs on GitHub, so the GitHub backend is complete and continuously exercised, and the desk-role work the verbs cover there is measured at 85 percent. Everything on this page is proven on GitHub before it is claimed anywhere else.

GitLab is partial. A published profile maps every control onto GitLab's mechanisms, and the backend implements 62 percent of the Forge interface fully, 86 percent counting partial implementations, measured 2026-09-13. Until a live pilot has round-tripped a brief through the verbs rather than around them, GitLab is a design you can plan against, not an install you can run.

Human-only rows stay on the forge's CLI, by design. Across the whole software-delivery lifecycle the verbs cover 41 percent of actions on either forge. The remainder is not a backlog to be closed: repository administration, ruleset and branch-protection changes, App or service-account creation, token custody, and the merge itself are an administrator's or a reviewer's acts on the forge's own surface, and a toolset whose purpose is to bound what an agent may write has no business performing them. The repository-hardening checker reads those settings under an identity that can write nothing, and reports could-not-check on the ones it is not allowed to see.

The guards are client-side. A verb's refusal binds the session that calls it. What binds everyone is the server-side layer beneath: branch protection, rulesets, the per-role permission set, and the forge's own refusal to let an author approve their own change. The verbs are built to make the sanctioned path the easy one and every other path a visible step outside it; they are not, on their own, the thing that makes the forge safe.