Delivery boundaries
- GitHub Issues and labels are the only state store; Orbi has no database, message queue, or web UI.
- The Python Runner is not a daemon: a systemd user timer starts one tick every five minutes, and each tick processes at most one Issue or resumes one opened PR before exiting.
- Orbi has no task DAG, multi-agent parallelism, risk model, policy engine, or fallback path. Command errors fail fast and leave the scene in the journal and Issue comment.
- There is no business task timeout: a slow model is not a failure. Command errors, an unavailable environment, or an unresolvable review fail fast.
- Orbi does not discover repositories, merge or push protected branches itself, or run without a working model endpoint.
The AI never merges or pushes protected branches
- The implementer Pi stops at the committed delivery: it does not
fetch the base, does not push, and does not create the PR — the Runner
pushes the task branch (plain push, never force) and opens one PR
(Issue #186). The Pi does not merge, does not push
main/master, does not force push, and never auto-resolves conflicts. - The Runner is the only merge actor, and it merges only through the
reviewed PR: a clean
REVIEW_VERDICT— read by a backwards scan that tolerates the reviewer’s natural-language wrapping (Issue #774), never adopts aREVIEW_VERDICTmention that is not a verdict line, fails on two conflicting verdicts, and is bound to the reviewed head SHA (Issue #591: a verdict line injected through the Issue body, the diff or a comment never overrides the reviewer’s conclusion, and a verdict naming another head never merges) — the merge gate (PR head contains the latest remote base, PR mergeable, remote head still the reviewed head), andgh pr merge --match-head-commitso exactly the reviewed head lands. - GitHub branch protection on the default branch is the final boundary: keep the protected branch restricted to the account that runs the Runner (or to no one — the Runner’s token performs the merge).
- Delivery state is derived, never trusted from public text: the resume
scene is only read from comments posted by a trusted maintainer
(OWNER/MAINTAINER/MEMBER/COLLABORATOR), and branch/worktree paths are
derived from the configured repo, Issue number and run id — a public
comment can never steer the Runner into an arbitrary local path. The
machine-readable record is the hidden versioned
orbi:scene:v1block rendered and parsed bysrc/orbi/scene.py; the readable text beside it is display only.
GitHub token (API) and SSH (git data) — two channels
- GitHub API operations (Issue, PR, label, comment, merge)
authenticate with
gh(gh auth statusmust succeed). Use a fine-grained personal access token scoped to the repositories the Orbi actually works on, with the minimum permissions: contents (read/write), pull requests (read/write), issues (read/write), and metadata (read). Avoid organization-wide or classic broad-scope tokens. - Git data operations (fetch, push — including
.github/workflows/*.yml) authenticate with the machine’s SSH key over[email protected]:owner/repo.git(Issue #114), or — withgit_transport = "https"(Issue #580) — with theghcredential helper overhttps://github.com/<repo>.git(the token-only sandbox path). A workflow push must never depend on the OAuth Appworkflowscope — the HTTPS/OAuth transport that blocked Issue #106. The pre-start check verifies the configured transport and fails fast when it is broken (no fallback). - The channels are never mixed: SSH is never an API authentication, and
the GitHub API never authenticates over SSH. In the default
sshtransport mode theghtoken is not a git-data credential (the machine’s SSH key is); inhttpstransport mode (Issue #580) the token IS the git-data credential — by explicit configuration, supplied to git by theghcredential helper. The token lives ingh’s local credential store on the Runner machine; the SSH key lives in the user’s SSH agent/config. Neither is written into the repository, the config file, the journal, or a GitHub comment. - Logs are redacted by construction: command lines carrying secrets are
logged as
<redacted>, and tool summaries are truncated and masked. The full prompt, Issue body and token never reach the journal or the progress comments. - Rotate the token on a normal schedule; a compromised token is contained to the repositories it can see.
Local state files
Orbi keeps local state that never leaves the machine:- Config (
orbi.toml): local, gitignored. The repository only ships the packaged example (src/orbi/example_config.toml). - Run artifacts: plan, test log, session JSONL and review evidence
live in the task worktree (
.worktrees/..., gitignored). - Slots:
<repo_dir>/.orbi/slots/slot-Nlock files (gitignored via the.orbi/directory convention of the checkout). - KV cache files (only if you run the optional
local-llm-kv-cache proxy): the disk-backed prefix
and session KV state (e.g.
~/.llama-slot-cache/*.bin) contains serialized model state derived from your prompts — treat it as sensitive local data, keep it on the same machine, and delete it if you no longer need the cached sessions.
Repository-level config: the trust model
A repository may carry a delivery-policy file at.github/orbi.toml
(see Workflow). It is read from the default branch tip
at claim time. The trust argument for allowing it is the same one that
already applies to CI workflows:
- A contributor without merge rights cannot land the file on the default branch, so it is out of scope.
- A maintainer who can merge already controls CI workflows on the default branch — arbitrary code execution plus the repository’s secrets. The marginal risk of a policy key is therefore ≈ 0.
- Orbi itself can merge its own reviewed output, unlike
Dependabot/Renovate. If prompt injection ever crossed the review gate,
the worst case for a whitelisted policy key is a visible, reversible
policy change — the run comment always records
repo_config: <sha>and annotates a change with its effective diff.
ORBI_GITHUB_TOKEN and the model API keys are sent — pi_provider,
pi_model, pi_thinking, pi_providers, pi_extensions, the
model_wait_probe_url endpoint and every other endpoint/key field —
stay permanently host-only. A deployment host serves several pools
(zcode-website / zcode-e2e / production), so one compromised repository
config must not be able to redirect all host credentials or move work
across pools. For the same reason source_repos/repo_dir/
deploy_home/workspace_root (cross-pool movement) and
prompt/prompt_review/skills (a persistent injection channel into
the system context) are host-only. A repository file that declares any
host-only key fails the claim fast and the Issue becomes ai-blocked
with the offending keys named. An unrecognized key is ignored with a
warning instead (Issue #1329); the host-only set is unchanged by that.
These delivery-policy keys are repository-writable:
base_branch, active_milestone, auto_next_milestone, context_files,
dispatch_label, steering_enabled, steering_poll_seconds,
steering_max_rounds, release_confirmation and clarify_thin_tickets.
The steering values affect only that repository; omitted keys fall back to
host configuration. Because a policy change is a default-branch change,
protect the file with GitHub’s native review mechanism — add
.github/orbi.toml to CODEOWNERS so changing it requires an owner’s
review.