AGENTS.md) applies to
human contributors too.
Issue granularity
One Issue is one runtime outcome, in one of two shapes: a fix (when X, should Y, actually Z) or a change (when X, the user should be able to Y; today they cannot because Z) — one observable behavior, a handful of related files, tests included. The title should work as a test name. Open an Issue once the root cause or the desired behavior is pinned — not as a vague wish.- Dependencies between Issues use GitHub’s native
blockedByrelation (gh issue edit N --add-blocked-by M); do not writeDepends on #Nin the body — the Runner does not parse body dependencies. - Multi-task work is organized as an Epic (see Workflow): the Epic coordinates, the sub-Issues deliver.
Minimal implementation (KISS/LEAN)
Orbi implements the smallest complete change that satisfies the Issue’s acceptance criteria — KISS and LEAN are the development contract (AGENTS.md, Issue #118):
- No speculative features, no no-benefit abstractions, no extra framework layers, no fallbacks, no future-proofing, no scope expansion beyond the acceptance criteria.
- 如无必要勿增实体 — do not multiply entities beyond necessity: every new file, dependency, state, label, command and abstraction must map to an acceptance criterion of the Issue.
- When two designs both satisfy the requirements, the simpler one wins: fewer concepts, fewer files.
- The MVP boundary stays intact: no database, queue, DAG, daemon, risk engine or fallback.
Creating an Issue
Write the Issue title in English. The body may include Chinese, but put the English description and acceptance criteria first so English-speaking readers can follow the task without translation. Dispatch a task for Orbi by creating an Issue and labeling itai-ready (the CLI does both in one step):
ai-ready + ai-ops-only: a dev ticket whose agent
correctly delivers no commit fails the delivery criterion and is burned
ai-blocked (see the workflow page). Before changing anything Orbi
reads the Issue, the repository’s AGENTS.md, the files it will change
plus their callers, and the related tests — the README and the rest of
the repository only when the task is actually about them (Issue #180).
User-centered acceptance
Use the same four sections for every new Issue: User outcome (what the user can accomplish), Preconditions (the configuration and command), Acceptance (the system action and the success result the user sees), and Evidence (a real entry point plus inspectable output). Include both a success path and a failure path: name the concrete error the user sees and the repair action. Unit tests are necessary local evidence, but do not replace the user path. Match depth to impact: documentation changes need the rendered docs page/preview and link checks; provider changes need a real provider/configuration check; concurrency changes need contention; setup changes need the setup entry point; UI changes need a real browser flow; and pure internal refactors need the existing public caller and regression tests. Record evidence in tests, journal, Issue/PR, or UI without adding infrastructure just for E2E.Reporting a bug
Open an Issue with thebug label and include:
- the command that failed and its return code / stdout / stderr;
- the journal scene (
journalctl --user -u [email protected] -u [email protected]around the failure, or therun_failedline with its run id); - the Issue/PR state (labels) and the run id from the progress comment;
- the environment: OS, Python version, Pi version, model endpoint type.
ai-ready Issues are picked up before new features, and
p0-labeled urgent Issues are picked up first of all (see the workflow
page), so a broken delivery loop — or a production outage — gets fixed
first.
Contributing code
-
Read
AGENTS.md— it is the development contract (TDD, the tiered coverage gate (Issue #234): whole repository line >= 95% and branch= 95% checked separately, changed Python code and core paths at 100% line/branch, fail fast, no database/queue/daemon/fallback, no business task timeout).
- Work on a feature branch; never push the protected branch directly.
- Write the failing test first, then the smallest implementation, then refactor. External interfaces (CLI flags, HTTP paths, config fields) are asserted against the official docs or one real call — never against a guessed shape.
- Run the full contract locally (see Testing for the exact commands). How you set up your local environment is your own business — it is not a repository contract, and the repository maintains no local test chain (Issue #569).
-
Open one PR per Issue. The PR description must contain
Fixes #<issue-number>so GitHub closes the Issue natively on merge (the full contract: Workflow, PR body contract). - CI must be green (same contract as local). The independent review and merge are performed by the Runner for Orbi-dispatched work; for human PRs, review and merge follow the repository’s normal GitHub flow.
External PRs (public repository)
Orbi is a public repository: external Issues and PRs are a mainline input, not an edge case. You keep full freedom over your branch name — the integration duty is the system’s, never the contributor’s (Issue #608). What happens to an external PR, in order:- CI runs on every PR, exactly as on the maintainers’ own branches.
- A red CI files one triage Issue per failed job, and that Issue
always links the PR. An external PR (any branch name outside the
Runner’s internal
orbi/<owner>-<repo>-issue-<n>delivery naming) is additionally marked in the Issue body, so neither the Runner nor a human reviewer can mistake it for an internal redo. - When the delivery loop claims that triage Issue, it reviews the
external PR first — the same independent review loop the Runner
applies to its own deliveries (review findings are fixed on your
branch, CI green applies unchanged). The review’s outcome is the
engine’s FINAL step: the conclusion (what changed, risks, test
coverage, CI status) is posted on the triage Issue and the Issue
waits at
ai-blockedfor a maintainer. The engine NEVER merges an external PR and never picks its milestone — accepting the contribution and choosing the version is the maintainer’s decision (Issue #842). - Only an abandoned, stale or unfixable PR is superseded by an internal redo — and the PR thread then explains the supersession to the contributor. A withdrawn or rejected external PR returns the triage Issue to the ready queue automatically. When a maintainer merges the external PR, the triage Issue closes as delivered.