Docs/CLI reference

CLI reference

tama attestation

An agent's own attestation, read without any model. A commit carries its attestation in its own message: every claim of the commit standard, word for word. review-push reads every commit a push adds and refuses the push at the first commit whose message lacks a claim, naming the commit and each missing claim. When every ref passes, each pushed commit is recorded in Oko's claim register as a push claim on <repository>@<commit> (the checkout's folder name) carrying review-push's structural verdict, which holds: oko claims list --subject <repository>@<commit> and Oko Desktop's Claims section show it, and Tama keeps no review record of its own. A claim that cannot be recorded is said on stderr (review-push: commit <sha> is not recorded as a claim: <cause>) and does not change the push's verdict; a machine without Oko says this machine has no Oko, so the pushed commits are not recorded as claims. An answer that ends a turn carries the claims each turn-end stop hook declares (check-stop-asking, block-false-blockers, block-stop-on-own-work), and those hooks refuse an answer that lacks one in the same way. Nothing is asked to judge either: no model, no key, no Brama, so a push and a turn end are judged the same on a machine with nothing but Git and Tama. A session's attestation that its task is finished is different: it is recorded, and on a machine that declared no model (tama model-provider set --none) the stop gates that would otherwise ask a model read it instead.

An agent's own attestation, read without any model. A commit carries its attestation in its own message: every claim of the commit standard, word for word. review-push reads every commit a push adds and refuses the push at the first commit whose message lacks a claim, naming the commit and each missing claim. When every ref passes, each pushed commit is recorded in Oko's claim register as a push claim on <repository>@<commit> (the checkout's folder name) carrying review-push's structural verdict, which holds: oko claims list --subject <repository>@<commit> and Oko Desktop's Claims section show it, and Tama keeps no review record of its own. A claim that cannot be recorded is said on stderr (review-push: commit <sha> is not recorded as a claim: <cause>) and does not change the push's verdict; a machine without Oko says this machine has no Oko, so the pushed commits are not recorded as claims. An answer that ends a turn carries the claims each turn-end stop hook declares (check-stop-asking, block-false-blockers, block-stop-on-own-work), and those hooks refuse an answer that lacks one in the same way. Nothing is asked to judge either: no model, no key, no Brama, so a push and a turn end are judged the same on a machine with nothing but Git and Tama. A session's attestation that its task is finished is different: it is recorded, and on a machine that declared no model (tama model-provider set --none) the stop gates that would otherwise ask a model read it instead.

While it reads a push's commits review-push says on stderr, before each one, which commit it reads and how many of how many it has read, and once one is read the time so far and the time the rest should take at that pace: review-push: reading commit <sha>, <read> of <total> read; <seconds>s so far, about <seconds>s for the rest. A push of many commits names what it stands on instead of standing silent; nothing limits how long the reading takes.

A commit that already exists — made before the commit standard asked for an attestation, or already shared — is never rewritten to carry one. Its attestation is kept beside it instead, as a Git note under refs/notes/attestation that tama attestation attest writes, and a commit stands when its message or its note carries every claim. review-push, check and Tama Desktop read both.

#Invocation

tama attestation standard (--commit | --turn | --session ID) [--json]
tama attestation check (--commit REV [--repository PATH] | --turn HOOK --file PATH) [--json]
tama attestation attest --commit REV --file PATH [--repository PATH] [--json]
tama attestation pending [--repository PATH] [--json]
tama attestation record --file PATH --session ID [--json]
tama attestation record --kind KIND --subject SUBJECT --statement TEXT [--json]
tama attestation show --session ID [--json]
tama attestation remove --session ID [--json]
tama attestation list [--kind session|file|cua|ssh|test|build] [--json]
tama attestation verify [--kind KIND] [--subject SUBJECT] [--json]
tama attestation revoke --kind KIND --subject SUBJECT [--json]
tama attestation migrate [--json]
  • standard --commit prints the commit standard's claims, one per line and nothing else, so the output is pasted into a commit message as it is. The harsh review the last claim speaks of is written in Git trailers, in the message's last paragraph, which standard --commit names on stderr: at least one Harsh-Review-Attacked: <what was attacked, what was checked, why the attack failed>, and no Harsh-Review-Finding: <defect>, because a finding is a defect the claims deny and is repaired in source before the commit is attested. Tama reads them with Git's own trailer grammar (git interpret-trailers --parse, tokens compared without regard to case); required_trailers and the trailer of must_be_empty in standards/commit.json declare them. With --json: {"kind": "commit", "claims": [...], "trailers": {"required": [{"trailer", "why"}], "mustBeEmpty": [{"trailer", "why"}]}}.
  • standard --turn prints every turn-end claim as <hook>: <claim>. With --json: {"kind": "turn", "hooks": {"<hook>": [...]}}.
  • check --commit REV reads the attestation of the commit REV names in --repository (the current directory when it is not given): its note under refs/notes/attestation when one is kept and stands, otherwise its message, and names every claim and required trailer it lacks and every finding it names, the same items review-push would name. A finding the commit's own message names is not answered by a note. check --turn HOOK --file PATH reads the answer in PATH against the claims HOOK declares, the same verdict the hook gives. Exit 0 when the attestation stands, 1 when it does not.
  • attest --commit REV --file PATH keeps the text in PATH as the attestation of the existing commit REV in --repository (the current directory when it is not given): a note under refs/notes/attestation, the commit itself unchanged. The note is kept only when the text carries every claim of the commit standard and the harsh review's trailers with no finding; otherwise nothing is written and what it lacks or names is printed, exit 1. A text that stands replaces a note already kept for the commit, so a note the commit standard has since outgrown, or whose Repairs: lines are malformed, is brought up to today's standard; attest then prints attestation: commit <sha> is attested in refs/notes/attestation, replacing the note kept before. The note is published with git push origin refs/notes/attestation; review-push lets a notes ref through without reading its notes commits as work. Git pushes no notes ref unless the push names it, so review-push refuses a push that adds a commit standing only in its note unless the same push carries refs/notes/attestation or the remote's refs/notes/attestation (read with git ls-remote) already names this checkout's notes commit: review-push: BLOCKED: <remote ref>: <commits> stand only in the refs/notes/attestation note kept beside them, and <remote> does not hold that note (its refs/notes/attestation names <commit>|it has no refs/notes/attestation; this checkout's names <commit>), so a clone of <remote> reads them with no attestation: push the note with the branch, `git push <remote> <remote ref> refs/notes/attestation`; when Git refuses the note as not a fast-forward, <remote> keeps notes this checkout lacks: `git fetch <remote> refs/notes/attestation:refs/notes/attestation-<remote>`, `git notes --ref attestation merge refs/notes/attestation-<remote>`, then push both again. A remote Git cannot ask refuses the push with review-push: the remote's attestation notes cannot be read: <git's words>.
  • pending reads every commit the branch at --repository (the current directory when it is not given) carries over its upstream, oldest first, as review-push will: whether each attestation stands and where, each missing claim or trailer, each finding, and each commit of the same range it patches — the commits Git's blame of its first parent names for the lines its patch removes or replaces. When a commit stands only in its note, it asks the upstream's remote whether it holds this checkout's notes, as review-push does, and the report does not stand when it does not. Prints attestation: <checkout> over <upstream>, oldest first:, then per commit attestation: <sha> <subject>: stands in its <message|refs/notes/attestation> or does not stand with missing:, finding: and patches: <sha> <subject> lines, and last the notes refusal review-push would print, after attestation: ; with --json, {"repository", "upstream", "stands", "notes", "commits": [{"commit", "subject", "stands", "carriedIn", "missing", "findings", "patches": [{"commit", "subject"}]}]}, where notes is null when no commit stands only in its note and otherwise {"remote", "local", "remoteNotes", "unpublished"} (the two notes commits, null where the ref does not exist, and the refusal or null). Exit 0 when every commit stands, none patches another and the remote holds the notes they stand on, 1 otherwise. A branch with no upstream is refused, exit 1: pending reads the commits HEAD carries over its upstream, and HEAD names none: <git's words>; an upstream that names no remote branch is refused, exit 1: the upstream of <branch> names no remote and remote branch (`git for-each-ref` printed "…"); a changed path Git quotes is refused naming it. Any other flag is a usage refusal, exit 2: pending reads one checkout's unpushed commits: [--repository PATH].
  • review-push does not take the claim that no commit patches another commit of the push on the attestation's word: a pushed commit that changes lines another commit of the same push added, as Git's blame reads it, and names none of them on a Repairs: line is refused with commit <sha> changes lines <earlier sha> of this push added and names none of them as repaired: add `Repairs: "<subject>" <the defect it repairs there>` for each to its message or to its attestation note (`tama attestation attest`); `tama attestation pending` lists every such pair, and nothing reaches the remote. A repository's first commit patches nothing.
  • A later commit that patches an earlier one of the same push says so on a line of its message or attestation note, Repairs: "<subject of the repaired commit>" <defect it repairs there>; once every patched commit is named so, pending and review-push let both through as their own commits. A line is read against each patched commit's subject: it names that commit when its text after the opening quote starts with the whole subject and a closing quote, so a subject that holds double quotes of its own, such as Name what a report left out instead of printing "unknown", is named as written. A line that does not open a quote is refused with `Repairs:…` does not quote the subject of the commit it repairs, one that never closes it with does not close the quoted subject, and one with no defect after its subject with names no defect after, each followed by the form to write.
  • standard --session ID prints the task standard a session's recorded attestation confirms, each claim as attestation: claim <key>: <claim> and each list that must stay empty as attestation: empty <key>: <why>.
  • record judges the JSON document in --file against the task standard and keeps it only when it stands, under the Tama state root in attestations/session/<id>.json; recording again replaces the kept record, and a refused attestation leaves the kept one as it was. show prints the kept record and how it stands against today's standard, remove deletes one.
  • A document whose "standard" is "build" is a session's build attestation instead: record judges it against standards/build.json (building is not marginal; whether open work holds the build is Oko's admission, oko admit build, never attested) at the same word minimum and keeps it under attestations/build/<id>.json, where the build gate reads it before every build, compile, format or test and spends it on the build it admits (how the build gate decides a build). A "standard" that is neither "build" nor "session" is refused, exit 1: standard is <value>: an attestation names the build standard as "build", or names none (or "session") for a finished task.
  • Every attestation is one record in one format kept in one ledger, attestations/ledger.json under the Tama state root (or the file TAMA_ATTESTATION_LEDGER names): {kind, subject, statement, attester, scope, lifetime, verification, store, recordedAt}. Every verb that writes one — tama justify record|remove|rename for file, CUA and SSH, tama tests approve|revoke, tama attestation record|remove|revoke — writes it through that one primitive and, beside it, into the registry the gate reads, which store names. The registries stay where the hook catalogue declares them, as views, so no gate or hook configuration changes. Build consents are the operator's answers in Oko and are read from there.
  • migrate brings what the registries hold into the ledger: once for what they held before the ledger existed, and again for anything a registry gained outside the verbs. A record already kept is left as it is, so a second migration brings nothing. Prints attestation: brought <n> attestation(s) into the ledger <path>; with --json, {"ledger", "brought", "attestations"}. Installing a release (tama hooks install-release) migrates and records the outcome as attestationLedger in installed.json, the cause also on stderr when it fails. Until the ledger has been written, list and verify are refused: the attestation ledger <path> has not been written; `tama attestation migrate` brings every registry into it.
  • list reads every attestation the ledger keeps, and the build consents Oko holds, as one record each, whichever registry is its view: the session records above (session), the file, CUA and SSH justifications in ~/.shared-hooks/ (file, cua, ssh), the operator's test approvals in ~/.config/agent-policy/approved_tests.json (test) and the build consents, standing in Oko's rulings or spent on a build (build). Each record says kind, subject (the session, path, application, targets or ask attested), statement (the attester's own words), attester (agent for what an agent states about its own work, operator for a grant, an approval or a consent), scope, lifetime, verification (artifact, transcript or ruling) and store, the registry the gate reads it from; --kind reads one kind. Printed as attestation: <kind> <subject> by the <attester>, verified by <verification>, from <store>.
  • verify re-reads what each record names, with no model: a session record must stand against today's task standard, a file justification's and a test approval's path must exist — a path whose existence cannot be examined does not verify, naming the examination's error — and an operator's CUA or SSH grant must cite a sentence that stands as the operator's own message in the session's transcript, so a sentence an agent wrote into a registry itself does not verify. Asked of every subject, it also names each place the ledger and a registry disagree, as an entry with no record: <registry> holds the <kind> attestation of <subject> that the ledger lacks; `tama attestation migrate` brings it in and the ledger keeps the <kind> attestation of <subject> that <registry> no longer holds. --subject verifies the records naming one subject. Each record is printed with verifies or does not verify: <why>; with --json, [{"record", "verified", "failure"}], record null for a disagreement. Exit 0 when every record verifies and nothing disagrees, 1 otherwise.
  • revoke withdraws one attestation whichever registry keeps it, through that registry's own removal, so list no longer shows it and the gate that read it no longer admits what it attested: a session record as remove does, a file justification by its path, and a CUA or SSH grant by the subject list names, removed by the sentence it cites. Prints attestation: revoked the <kind> attestation of <subject>; with --json, {"kind", "subject", "removed"} with each registry's own answer.
  • record --kind KIND --subject SUBJECT --statement TEXT records an attestation through its registry's own writer, so list shows it and the gate that reads that registry admits it: a file justification (--kind file, the subject a path) is written as tama justify record --kind file writes it and prints attestation: recorded the file attestation of <path> in <registry>; with --json, {"recorded", "kind", "registry"}. What only the operator gives is refused, exit 1, naming the act that records it and writing nothing: a cua|ssh grant for <subject> is the operator's consent and cites his own sentence: `tama justify record --kind ssh --quote <his sentence> ...` records it, the approval of <subject> is the operator's own act; he gives it from his terminal with `tama tests approve <subject>`, build consent <subject> is the operator's answer in Oko; an agent records none; a session attests its task with record --file PATH --session ID. Without --subject or --statement it is a usage refusal, exit 2: record --kind attests one subject: --subject SUBJECT --statement TEXT; --statement on another verb is refused with <verb> takes no --statement; record --kind does.

#Quickstart

A commit that carries its attestation, checked before it is pushed:

$ git commit -m "Parse a balance from its text"
$ tama attestation check --commit HEAD
attestation: commit <sha> does not carry its attestation
    missing: "<claim>"
    …
$ git commit --amend -m "Parse a balance from its text

$(tama attestation standard --commit)

Harsh-Review-Attacked: an empty or signed text; parse trims and returns the error it gets"
$ tama attestation check --commit HEAD
attestation: commit <sha> carries every claim in its message
$ git push            # review-push reads the same message and lets it through

A commit that already exists, attested without being rewritten:

$ tama attestation standard --commit > attestation.txt
$ printf '\nHarsh-Review-Attacked: …\n' >> attestation.txt
$ tama attestation attest --commit <sha> --file attestation.txt
attestation: commit <sha> is attested in refs/notes/attestation
$ tama attestation check --commit <sha>
attestation: commit <sha> carries every claim in its refs/notes/attestation
$ git push origin main refs/notes/attestation

An answer checked before the turn ends with it:

$ tama attestation standard --turn
$ tama attestation check --turn check-stop-asking --file answer.md

A session on a machine with no model:

$ tama model-provider set --none
$ tama attestation standard --session "$SESSION"
$ tama attestation record --file done.json --session "$SESSION"
attestation: session <session> stands
attestation: recorded at ~/Library/Application Support/Tama/attestations/session/<session>.json

Everything an agent or the operator has attested, and whether each still holds:

$ tama attestation list --kind ssh
attestation: ssh ["build.example"] by the operator, verified by transcript, from ~/.shared-hooks/ssh_justification.json
$ tama attestation verify --kind ssh
attestation: ssh ["build.example"] by the operator, verified by transcript, from ~/.shared-hooks/ssh_justification.json
attestation:   does not verify: ssh grant for ["build.example"]: no direct user message matches "…" in OMP session <session> under ~/.omp/agent/sessions

#How a carried attestation is read

Every claim the declaration lists must stand in the text word for word. Runs of spaces and line breaks count as one space, so a claim wrapped over lines reads as written; nothing else is forgiven: a reworded, shortened or translated claim is missing. The claims come from standards/commit.json (its required[].claim) and standards/turn.json (each hook's list) beside the attestation module, the same files the gates read. A claim is carried only when it is true; a false one is the agent's defect, on record in the commit or the transcript.

A claim that only scopes others names them in the declaration (implied_by, their keys) and is carried by a text that carries every one of them word for word: the claim that a commit's line claims hold as the push leaves them is carried by a text stating all six claims about the commit's lines — no defect, no needless abstraction or copy, no swallowed error, no guessed number, no hidden failure, no narration or internal name — unscoped, as every commit attested before that claim was declared states them. A text that lacks any of them lacks the scoping claim too, and both are named missing.

Every commit carries its own: the tip of a push speaks for no commit under it. For a ref the remote does not hold yet, the commits read are those no ref Git keeps for that remote already holds. A note kept under refs/notes/attestation that carries every claim is the commit's attestation, its Repairs: lines included, so a malformed Repairs: line in a message is answered by a note without it; without a standing note the message is read, and a finding the message names is never answered by a note.

Every claim speaks of the commit that carries it: its own message and patch, which its committer read. A push is the commits it adds, each standing on its own committer's attestation, so nobody claims to have read commits other sessions made, and a checkout whose branch carries other sessions' unpushed commits can still take an honest one. That a commit patches no commit the remote lacks is not taken on its claim alone: review-push also reads it from Git's blame. A commit whose message carries an earlier wording of the claims is attested beside it with a note carrying today's.

#What a session's recorded attestation holds

{
  "attestations": {
    "<claim key>": {"confirmed": true, "how": "…"},
    "…": {"confirmed": true, "how": "…"}
  },
  "next_steps": [],
  "harsh_senior_review_findings": []
}

Every claim of standards/task.json must be present with "confirmed": true and a how that explains, in the agent's own words, how the claim holds, in at least the number of words the operator stated (attestation_min_words in the stated-numbers declaration). next_steps and harsh_senior_review_findings must be present and empty: a step that continues the task is the task's work, and every finding means the task is not finished.

#Output and refusals

  • review-push: BLOCKED: <local ref> -> <remote ref>: commit <sha> carries no standing commit attestation in its message or in its refs/notes/attestation note: followed by one missing: "<claim>" line per missing claim, one missing: "<trailer>: <why>" line per required trailer the text carries no value of, and one finding: "Harsh-Review-Finding: <defect>" line per finding (the note's, when a note is kept and the message names no finding, else the message's), then the instruction to carry the block tama attestation standard --commit prints with the trailers it names in the message of a commit not yet made, or to keep it beside an existing commit with tama attestation attest; the push exits 1 and nothing reaches the remote. A pushed commit Git cannot list or read, a notes list Git cannot give, or a text git interpret-trailers --parse cannot read, is refused with review-push: the pushed commits cannot be read: <cause>. The commit gate (tama hook review-commit) refuses a message the same way before the commit is made: the message carries no standing commit attestation; … with the same lines.
  • Once the message carries its attestation, the commit gate (tama hook review-commit) checks that each staged change stands where the working tree has it: for every file HEAD and the working tree both hold, the staged change of HEAD is merged into the working file with git merge-file --object-id (blobs only; the checkout is not written), and it is in place when the working file comes back unchanged, byte for byte, so a text file in any encoding is judged. A file Git counts as binary (- for both counts in git diff --cached --numstat, by its content or a binary attribute) is not judged: Git cannot merge it and git add -p stages it whole, though a patch applied to the index can still carry part of one. A working path that is gone or is no longer a file has nothing to place; one that cannot be examined refuses the review with the working file <path> cannot be examined to check where its staged change lands: <cause>. Sessions sharing one checkout commit their own hunks from it; a hunk applied at the wrong lines is refused before the commit exists: review-commit: commit refused before history changed: the staged change of <n> file(s) does not stand where the working tree has it, so a hunk was applied at the wrong lines; stage the hunks again against their own lines (git add -p, or a patch with context): followed by <path>: the staged change lands elsewhere than in the working tree, right after its first <n> line(s), which agree or <path>: the staged change overlaps lines the working tree changes differently per file. A git command that cannot run or ends on a signal, a merge-file that exits negative, or any other git command that does not succeed refuses the review with its words.
  • BLOCKED: <hook>: the answer this turn ends with does not carry its turn-end attestation: followed by the missing claims in the same form; a transcript that cannot be read is refused as TAMA_HOOK_INFRASTRUCTURE: <hook>: <cause>. A turn that ends with no text, or only whitespace, states nothing to the operator, whom block-text-outside-tool-calls forbids an agent with open work to address, so it owes no claim: the stop gates pass it and check --turn answers it as standing, while the open-work gates still decide whether the turn may end.
  • check prints attestation: <kind> <id> carries every claim in its <message|refs/notes/attestation|answer> or attestation: <kind> <id> does not carry its attestation and the missing items and findings; with --json, {"kind", "id", "stands", "missing", "findings", "carriedIn"}. attest prints attestation: commit <sha> is attested in refs/notes/attestation, with , replacing the note kept before when it replaced one, or the missing items and findings; with --json, {"kind", "id", "stands", "missing", "findings", "keptIn", "replaced"}, replaced the text of the note it replaced or null. <rev> names no commit in the repository at <place>: <git's words>, git notes --ref refs/notes/attestation add --force … ended with <status>: <git's words>, git interpret-trailers --parse ended with <status>: <git's words> and standards/turn.json declares no turn-end attestation for the hook <hook> exit 1.
  • record prints attestation: session <id> stands and attestation: recorded at <path>, or does not stand with every reason, exit 1, nothing kept: attestations.<key> is missing, .confirmed is not true, .how is missing, .how explains in N words …; the operator asks for at least M, <list> names N item(s). show or remove with nothing kept: no attestation is recorded for session <id>, exit 1.
  • Flags that do not fit the verb are refused with the usage text before anything is read, exit 2: standard prints one standard: --commit, --turn or --session ID, check reads one text: --commit REV [--repository PATH], or --turn HOOK --file PATH, <verb> needs --session ID, record needs --file PATH, <verb> takes no --file, <verb> takes no --commit, --repository or --turn, <verb> reads every registry, so it takes only --kind, --subject and --json, list takes no --subject; verify and revoke do, <verb> is not a verb of tama attestation, <flag> is not an option of this command, <flag> needs a value, <flag> is given twice.
  • attest without both --commit REV and --file PATH, or with --turn or --session, is refused with attest keeps one commit's attestation: --commit REV --file PATH [--repository PATH], exit 2; a file that cannot be read is named with its cause, exit 1.
  • list, verify and revoke exit 1 with <word> is not a kind of attestation; the kinds are session, file, cua, ssh, test, build, no attestation names <subject>, a registry that cannot be read or holds no authorizations array named by its path, and an entry of <store> carries no <field>; a record that cannot be verified because it names no session or no sentence says the <kind> attestation of <subject> carries no <field> to verify it by (read from <store>). revoke also refuses no <kind> attestation names <subject>; `tama attestation list --kind <kind>` lists them, a test approval with the approval of <path> is the operator's own act; he withdraws it from his terminal with `tama tests revoke <path>`, and a spent build consent with build consent <ask> records an answer a build already used; …. Without both flags it is a usage error: revoke withdraws one attestation: --kind KIND --subject SUBJECT.

#Tama Desktop

The Install screen's Carried attestations section shows every claim a commit message carries, with a Copy block button that puts them on the clipboard one per line, the harsh review's trailers (At least one Harsh-Review-Attacked, No Harsh-Review-Finding, each with why), and each stop hook's turn-end claims. Its form checks a commit in a chosen repository, or an answer typed for a chosen hook, and shows the verdict with each missing claim or trailer and each finding as the gate would name it. It sends tama request attestation/required and attestation/check with {"commit": "<rev>", "repository": "<path>"} or {"turn": "<hook>", "answer": "<text>"}; a commit without its repository, or a body naming neither, is refused with attestation/check needs "commit" with "repository", or "turn" with "answer". The Recorded attestations section records a chosen file for a session, shows, removes and lists records, and shows the task standard, through attestation/record, show, remove, standard and list with {"session": "<id>"}.

The same form keeps the attestation of an existing commit: the attestation typed under the answer and Keep attestation beside commit send tama request attestation/attest-commit with {"commit": "<rev>", "repository": "<path>", "attestation": "<text>"}. A text that lacks a claim or a required trailer, or names a finding, is an answer, shown with each missing item and each finding and nothing kept; a kept note is shown as Kept in refs/notes/attestation; the commit is unchanged, and a check of a noted commit says where its attestation is carried. A body without all three fields is refused with attestation/attest-commit needs "commit", "repository" and "attestation"; a note Git refuses to add is shown with Git's words.

Its Every attestation section lists every record the ledger keeps, as list prints it, narrowed to one kind with the picker; Verify shows each record with what fails and each disagreement between the ledger and a registry; Migrate brings what the registries hold into the ledger and says how many records it brought; each listed record has a Revoke button. It sends tama request attestation/registries, attestation/verify, attestation/migrate (any body) and attestation/revoke with {"kind": "<kind>"} (left out for every kind) and, for verify and revoke, "subject"; revoke needs both and is refused with attestation/revoke needs "kind": "<kind>" and "subject": "<subject>" otherwise; refusals carry the command's sentence prefixed with the request's name.

The kind picker offers every kind Tama names, whether or not a record of it exists yet, read with tama request attestation/kinds (any body), which answers the kinds in the order list reads them. Under it, Subject and Statement with a Record button record an attestation of the picked kind as record --kind does, then list again. It sends tama request attestation/attest with {"kind": "<kind>", "subject": "<subject>", "statement": "<text>"}, all three required, refused with attestation/attest needs "kind": "<kind>", "subject": "<subject>" and "statement": "<text>" otherwise; a kind only the operator gives is refused with the sentence record --kind prints, prefixed attestation/attest: .

#Tests

tests/review/attested.rs pushes a real commit through Git to a bare remote with Brama's address removed and no resolver state: the push without the attestation is refused naming the commit and its missing claims, tama attestation check --commit and the Desktop's attestation/check say the same; with the claims and a Harsh-Review-Finding trailer the push is refused naming the finding alone, and check and the Desktop name it in findings; once the message carries the block standard --commit prints and a Harsh-Review-Attacked trailer, both pass and the commit reaches the remote. tests/commit-review/attested.rs commits through Git's commit-msg hook: a message without the claims, one with the claims and no attack trailer (naming missing: "Harsh-Review-Attacked: …"), and one naming a finding are each refused with the branch unmoved, and the message with the claims and an attack becomes a commit. tests/task-attestation/turn.rs runs each turn-end hook the declaration names against an answer without and with its claims, wrapped over lines, and checks standard --turn and check --turn. desktop.rs runs the Desktop's requests, record.rs the recorded session attestation and every malformed command, and no_model.rs a model-asking stop gate reading a recorded session attestation.

tests/review/push/noted.rs pushes real commits through Git to a bare remote: the push of commits carrying no attestation is refused naming the note and the missing claims; attest with a text lacking a claim, or naming a finding, exits 1 and keeps no note, and the Desktop's attestation/attest-commit answers the same with the finding in findings; once every unpushed commit has its note with an attack trailer, a second attest with a standing text replaces the note and says so, the commits keep their object names, check and the Desktop's attestation/check name the note, the same commits reach the remote and refs/notes/attestation is pushed beside them.

tests/review/push/patched.rs pushes real commits through Git to a bare remote: a commit that changes lines an earlier commit of the push added, whose subject holds double quotes, is refused by review-push and pending naming the pair; a Repairs: line naming that subject and no defect is refused with names no defect after; a note whose Repairs: line names the quoted subject and its defect makes pending stand, and the same line in the message lets both commits reach the remote, each as its own commit.

tests/attestation-registries/verify.rs runs list, verify and revoke in an isolated home: an SSH grant whose sentence the session's transcript does not hold is listed with the operator as attester and does not verify, naming the session, and verifies once the operator's own message holds the sentence; a file justification recorded with tama justify record verifies while its path exists and not after; an unknown kind is refused naming every kind; a revoked SSH grant is no longer listed and a second revoke is refused naming the subject, a test approval is refused naming tama tests revoke, and revoke without --subject is a usage error.

tests/attestation-registries/record.rs runs record --kind in an isolated home: a file justification is recorded, listed with the agent as attester and verifies; --kind ssh, test and build are refused naming the act that records each and leave their registries empty; a record without --statement is a usage refusal. It also sends the Desktop's requests: attestation/kinds names every kind in an empty home, attestation/attest records a file justification that list then shows, refuses a test approval naming tama tests approve, and refuses a body without its statement.

tests/attestation-registries/ledger.rs runs the ledger in an isolated home: list before any migration is refused naming migrate; a file justification already in its registry is brought in once and a second migration brings nothing; a justification recorded and revoked through the verbs is kept in and withdrawn from the ledger and the registry together, its record naming the registry; a test approval is kept with the operator as attester; and a registry entry written outside the verbs is named by verify as what the ledger lacks.

Return to the complete CLI tree.