Send a change

From your branch to main. Open a pull request with qq try, read the gate's verdict with qq status, and land through the merge queue with qq land.

When your change builds and tests locally, three commands take it the rest of the way: qq try opens the pull request, qq status tells you what the gate thinks, and qq land lands it once the gate passes. None of them makes you wait at the terminal while CI runs.

Today: these commands are built and tested, but a live qq try or qq land on a product repo has not been shown yet. A plain git push and a pull request on GitHub go through exactly the same gate.

Before you start

You need the GitHub CLI, gh, signed in with gh auth login. qq's change commands are thin wrappers over it. Work on a branch, with your commits on it.

1. Open the pull request

qq try

qq try pushes your branch, opens its pull request (or updates it if one is open), prints a run ID and exits at once. The presubmit check now runs on GitHub. To open the pull request without starting a watch, use qq upload.

Both take --title, --body and --draft, and --base to land somewhere other than the default branch. Without --title, the title comes from your commits, and --body is refused without --title.

2. What the presubmit checks

The presubmit is one required check named after the repo, such as innernet-presubmit. It first checks that the generated CI workflows were not edited by hand, then installs, builds and tests the repo and stores the results. Only success passes. A skipped or neutral check is a refusal; a check still running, or not reported yet, is pending (qq status exits 3).

3. Read the verdict

qq status
Exit codeVerdict
0pass (or already landed)
1refused (or closed)
2error
3pending: checks are still running

Scripts should decide on the exit code. Add --json for the full verdict.

4. Land it

qq land

qq land queues nothing until the gate passes. It then hands the pull request to GitHub's merge queue, which tests it again on top of the changes ahead of it and merges it into main, with the merge method gate sets for the repo (squash otherwise). --method overrides it. A refused change is never queued, and a change the queue drops is reported as dequeued.

Who must approve

ReposApproval needed
The 13 infra reposnone: green checks land them
Products: xo-space, innernet, websiteone approval, never from the author
toolchains' build and promotion pathssuraj's code-owner review

In xo-space, don't use qq land. qq land lands through GitHub's auto-merge, and xo-space is the one repo with auto-merge off. Use qq try and qq status there; once the gate passes and the pull request is approved, suraj clicks Merge when ready.

For agents: never hold a call open

qq try and qq land return a run ID at once. A watcher follows the change and writes the verdict (pass, refused, landed, dequeued, superseded by a newer push, closed, timed out or error) to $QQ_HOME/verdicts/<run ID>.json (QQ_HOME is ~/.cache/qq by default). It also runs your --notify command (default $QQ_NOTIFY), which gets the verdict as JSON on stdin and QQ_VERDICT set in its environment. That is where an agent harness plugs in its own channel.

If the watcher dies, for example after a reboot, qq status still gives the verdict. The --notify command line shows in ps, so pass secrets through the environment, never in the command.

Which change

qq try, qq status and qq land act on the current branch's pull request. Pass a number, URL or branch to act on another one, and --repo OWNER/NAME to act outside this checkout:

qq status 42
qq land https://github.com/quirq-ai/innernet/pull/42

Next: after it lands.