Docs / Incidents
Server mode and the draft pull request
In server mode ivralo may commit and push one kind of branch, for one purpose: a draft pull request a person reviews. This page covers how the mode is set, the identity and credential ivralo uses, and every rule the push follows.
What server mode grants
A mode is a set of grants for runs that nobody is watching, such as a job, a schedule or an alert. It changes nothing about what a person at the keyboard is asked.
IVRALO_MODE | What an unattended run may do beyond asking |
|---|---|
developer (default) | Nothing. Every call that would ask a person is refused. |
server | git.commit and git.push: make a branch, stage and commit, push the branch ivralo made and open a draft pull request for it. |
The tools' own refusals still hold in server mode, and nothing anywhere merges.
IVRALO_MODE, IVRALO_FORGE_GH and IVRALO_GITHUB_URL are read from the home's .env and the environment only, never from a repository's .ivralo/.env. A repository cannot grant itself a push.
ivralo init --server writes the mode, the identity and the credential described below:
GITHUB_ACCESS_TOKEN=... ivralo init --server --git-name "ivralo" --git-email ivralo@corp.example
The full install is on Install on a server.
ivralo's git identity
On a server, ivralo commits as itself. init --server writes a name and an e-mail into <home>/gitconfig, a git config file of ivralo's own. Your global config and the repository's config are only read, never written.
- The address must be ivralo's own, never yours. ivralo tells its commits from a person's by that address, so init refuses the operator's global
user.emailand the repository's. - At a terminal both are asked (
ivralooffered as the name). Under--yesthey must come from--git-nameand--git-email. git_commitandgit_revert_commitcarry the identity as author and committer through git's own environment variables, and record each commit on the session.
Without that file, commits are yours as usual and open_pull_request is not on the team at all.
The forge credential
There is one forge: github.com, or the host of IVRALO_GITHUB_URL for a GitHub Enterprise server. The API is never read off the remote. init --server finds the credential in this order:
GITHUB_ACCESS_TOKENalready in the home's.env, kept and checked again;GITHUB_ACCESS_TOKENexported in the environment init runs in, written into.env(never put it on the command line itself);- at a terminal only,
gh's own login for the forge host: a yes writesIVRALO_FORGE_GH=true, and the login is read at each call, nothing stored; - at a terminal, the token itself, asked for hidden.
Use a fine-grained token with contents: write on the repositories ivralo works in and pull requests: write, nothing else. Init checks it once: the forge host against the egress policy, whose token it is, its kind and scopes, and whether it reaches the repository. A token that the forge refuses, that does not reach the repository, or that carries admin:*, delete_repo or workflow is not written. With no credential at all, ivralo investigates and reports and opens no pull request.
ivralo doctor shows all three in its forge section:
forge
ok git identity ivralo commits as ivralo <ivralo@corp.example> (/home/ops/ivralo/gitconfig)
ok forge credential GITHUB_ACCESS_TOKEN of ivralo-bot · fine-grained · ... · reaches team/shop
ok mode server - an unattended run may commit, push the branch ivralo made and open a draft pull request for it; nothing merges
open_pull_request: the one push
open_pull_request(branch, title, summary, incident) pushes a branch to origin and opens a draft pull request for it. The main agent and the Code Engineer hold it; an instance never does. It asks a person on every call, and no session-wide approval lifts that. With nobody to ask, it runs only in server mode.
Before anything leaves the machine it refuses, saying why:
| Refused | Why |
|---|---|
A name starting with + or - | The push never forces and takes no options. |
The remote's default branch, and main always | ivralo never pushes to them. |
| A branch the remote already has | ivralo creates a branch there; it never updates one. |
| Any commit ivralo did not make | Every commit the push would send, listed against the remote's actual heads, must carry ivralo's identity as author and committer and be one git_commit made in this session by this ivralo process. A rebased, amended or merged-in commit, one from another session, and one from another process are all refused. |
| ivralo's identity being your address | ivralo could not tell its commits from yours. |
| A commit that changes a hook, or uncommitted changes there | .githooks/, .git/hooks or whatever core.hooksPath names: the push runs your pre-push hook. |
An origin that is not https on the forge host | For fetch and every push URL. ssh is refused, since the push uses the token over https, and plain http would send it in clear. |
| A forge host the egress policy refuses | The host is judged before any connection. |
| No forge credential | Nothing to sign in with. |
| A folder you have not trusted | The push runs the repository's pre-push hook. |
| More than 200 commits | One push sends at most 200. |
The push sends refs/heads/<branch> with no force of any kind, no tags and no submodules.
The token reaches git through one inline credential helper, registered for the forge's https://<host> alone, reading an owner-only file under the home that is removed after the push. Every other configured helper is reset first, and nothing is stored. Your pre-push hook, and anything it runs, can reach the token for the length of the push; that is why the folder must be trusted and the hooks clean.
.ivralo/changes/commits.jsonl lists ivralo's commits for you to read. Nothing trusts it: a line written there lifts no refusal.
The pull request's body
The body is written by code, not by the model alone: the summary and, when an incident id is given, the filed incident report, each inside a fenced block so nothing in them renders as the forge's markup; the branch's commits; and a last line with the run id that says ivralo never merges. The body is kept under 60,000 characters, the report cut first and the cut said.
Nothing merges
There is no call anywhere in ivralo that merges, approves or turns on auto-merge. The shell policy's built-in deny list, which permissions.json cannot lift, also refuses the other ways out in every spelling, including through env, command or a VAR= prefix:
git push,git send-pack,git subtree push;gh pr merge,gh pr ready,gh pr review --approve;gh repo edit --enable-auto-merge;- a
gh apicall that names a merge or ready.
So the draft pull request is the only way out, and the merge is yours, on the forge. See Shell commands for the rest of the policy and Git for the commit tools.