From an idea to a landed change
Aether's contributor workflow is direct-drive. The baseline is ordinary: an issue for planned work, one focused branch, one focused pull request, and green CI as the merge gate. GitHub Actions supplies build and test checks, not lifecycle orchestration.
On top of that baseline the repository keeps a set of scoped-issue skills —
scope, approve, implement, land, and their neighbours — that add
issue-body Plan artifacts, a digest-bound approval, an owned worktree,
head-bound review evidence, and priced surface overflow. They are checked in
and current, and a session that invokes one is bound by its contract. They are
not, however, the only route a change may take: a change that does not enter
that pipeline lands as a plain reviewed PR on green CI.
The rest of this page describes the journey those skills define, because that is the part with invariants worth stating. It does not copy mutation procedures from the skills. Read the matching skill and shared contract before changing repository or GitHub state.
Authority depends on the question
Use the source that owns the question:
| Question | Authoritative source |
|---|---|
| What does the user want, and what consequential action is authorized? | The current user or repository-owner request |
| How does Codex perform a repository workflow? | AGENTS.md, the active Codex tool schema, and the matching Codex skill |
| How does Claude Code perform it? | CLAUDE.md, the active Claude tools, and the matching .claude/skills/ contract |
| What behavior is implemented? | Current code and tests |
| Why is a load-bearing design shaped this way? | The applicable Accepted ADR and its supersession chain |
| What arguments does a live tool accept? | The active tool schema, not a prose copy |
| What does this running engine contain? | Live introspection such as describe_kinds and describe_component |
| What work is approved? | For a scoped issue: its managed sections plus a trusted matching hidden approval record. Otherwise: the user's own request |
| Is a draft ready to land? | Its exact head, approval ancestry, actual diff, checks, native reviews, threads, priced surface overflow, and merge state |
| What does hosted automation do? | Checked-in workflow YAML plus current repository protection and check state |
The guide is the digested, navigable explanation. When it disagrees with a current tool schema or implementation, report the drift and trust the owning source for the immediate task.
Agent surfaces are intentionally distinct
Codex uses .agents/skills/
and their shared contracts. Those files are written for Codex's current tools;
they do not runtime-translate Claude instructions.
Claude Code uses CLAUDE.md and .claude/skills/. The two surfaces share the
same issue-body artifact, approval, surface overflow pricing, review, and
landing invariants, while command syntax, pause mechanics, worker routing, and
worktree roots may differ. A prompt or task name cannot select a model or role
that the active tool did not actually select.
The durable journey
idea or rough issue
→ managed Plan sections + declared surface + body routing lines
→ trusted hidden approval bound to Plan digest + exact base
→ owned issue worktree + branch
→ draft pull request closing the issue
→ current-head checks + native reviews + threads + priced surface overflow
→ explicitly authorized landing
→ merged pull request + closed issue + safe local cleanup
These artifacts are independent facts. A branch does not prove approval. Green CI does not clear a native change request or an unresolved thread. A closed issue does not prove that a named pull request merged.
Issue labels are taxonomy only. They can identify the conventional-commit type, affected Cargo scopes, or other searchable classifications, but they do not carry workflow progress, approval, or model routing. Read the body and concrete implementation artifacts instead.
Choosing the workflow
These are the checked-in skills, when a session uses them. Each name authorizes its own documented workflow and nothing adjacent.
| Intent | Codex workflow | Durable result |
|---|---|---|
| Explore a felt absence | wish | An idea tree, not automatically an issue |
| Capture a rough single idea | sketch | An open unscoped issue |
| Ground the problem, design, Plan, surface, and route | scope | Complete managed issue-body artifacts |
| File selected unrelated scope observations | scope-spinoff | Linked unscoped issues |
| Answer open questions from the design rulebook | settle | Settled answers applied; Leaning and Open ones for the owner |
| Authorize a complete Plan | approve | A trusted hidden digest/base-bound record |
| Implement approved work | implement | A reviewed, green draft PR with priced overflow reported |
| Audit existing code or a non-PR change | review | A read-only findings rollup |
Merge current main into a content-conflicted draft | resolve | The same draft, green and re-reviewed on a merge commit |
| Land an accepted draft | land | Merged PR, closed issue, and safe cleanup |
| Reclaim proven-stale local state | sweep | Only the explicitly confirmed cleanup |
| Capture repeatable session friction | retrospect | Confirmed unscoped issues, if any |
| Draft a load-bearing decision | adr | Proposed ADR draft in its own worktree |
Claude Code exposes the corresponding slash-prefixed skills. Always read the current skill frontmatter before invoking it. One workflow name does not authorize an adjacent consequential action; implementation never implies landing.
Scope and routing live in the issue body
scope owns the managed sections for the problem statement, design notes,
implementation plan, optional sub-issues and dependencies, declared surface,
and optional side findings. The Plan ends
with exact Size, Implementation model, and Routing reason lines. Those
body lines—not labels—select the implementation route.
Plan steps and acceptance criteria cite the symbol that defines a protocol value, never the value itself — exit codes, wire discriminants, ports, and limits. The value is free to move; naming the symbol is what makes the move greppable, and a pinned numeral that later means something else is a silent mis-implementation.
The declared surface is the prepaid forecast: it bounds approval-policy
resolution, and paths outside it are priced at landing rather than forbidden.
Declare it at crate granularity — crates/<crate>/src/** plus
crates/<crate>/tests/** — and narrow to a module glob only when one crate
hosts two genuinely separate things. Naming an individual file is a forecast of
which files the work will touch, and that forecast is wrong often enough to be
worth avoiding unless approval-policy.toml itself names that file. Read the
policy for which files those are rather than copying the list; it moves. A
necessary edit outside the declared surface is overflow priced at landing, not
evidence that the Plan must change. A pure umbrella declares that it has no
implementation PR and closes only after its children and coordination
obligations are complete.
The canonical Plan digest covers the approval-bearing managed sections and their exact bytes. Side findings and unmanaged prose are outside that identity. Use the checked-in parser; do not recreate its normalization in prose or a new script.
Approval binds intent to code history
approve re-reads the issue, verifies its structure, dependencies, ADR needs,
targets, declared-surface containment, routing, and policy against a freshly
captured origin/main. It appends a canonical hidden aether-approval:v2
record to the issue body's unmanaged prefix. The record binds:
- the issue number;
- Plan digest;
- size and implementation model;
- policy and effective approval tiers;
- permitted authority; and
- the exact base commit.
Trust comes from the effective issue-body editor reported by GitHub, not from an authority string inside the payload. An edit to approval-bearing managed bytes changes the digest; a different base needs another approval. Older records stay as history but do not authorize the current Plan.
The policy tiers are auto, judge, and human. Their authority rules do not
weaken structure, freshness, dependency, ADR, or surface-grounding gates.
Approval does not edit scope or start implementation.
Implementation creates one reviewable artifact
Fresh implementation requires a current trusted approval whose base is current
origin/main. The active surface creates one issue branch and one issue
worktree from that exact commit:
- Codex and Claude Code alike:
.agents/worktrees/issue-<N>.
The implementation follows the Plan literally, runs focused verification plus
cargo fmt -- --check and
cargo clippy --workspace --all-targets --all-features -- -D warnings, reviews
the complete diff, computes priced surface overflow, then plain-pushes and opens
a draft PR that closes the issue. Existing artifacts are possible live ownership
claims and require a verified resume, never opportunistic deletion or
recreation.
GitHub Actions proves the build/test tree. main is protected by the
Protect main ruleset: changes land only through a pull request, force pushes
and deletion are refused, and no one bypasses it. No pull-request review is
required. CI pass and Lint title are the checks a head must pass before it
lands, but the ruleset does not enforce them.
The checked-in workflow README
owns the exact hosted inventory.
Native review blockers are head-bound
The workflow has no review step of its own and no review record: the implementer does not review its own draft, and landing requires no verdict. Review happens by direction, when the owner or a contributor reads a draft and says what to change. Two native GitHub facts carry that into the workflow, and each blocks a draft independently of its checks:
- no reviewer's latest active native decision is changes requested; and
- every review thread is resolved.
PR reviews, comments, and thread replies contain ordinary human prose; they never carry machine JSON/HTML review markers.
A native change request or an unresolved thread enters the implementation's repair loop. Verify each item, fix it at any path; overflow is priced, or give a concrete justification, push an ordinary commit, rerun local checks, reply to its anchored thread, and resolve the thread only after the disposition is visible. The changed head then needs green checks again. A root-level or out-of-scope problem returns to the appropriate managed scope artifact instead of being silently waived.
An agent ends at a wait
In Claude Code every subagent's prompt cache lasts five minutes, while the main session's lasts an hour. A subagent that goes longer than five minutes between calls, blocked on CI, parked on its own background task, or resumed later by a message, re-reads its whole context on its next call. The wait buys nothing, because the workflow already resumes from observable facts.
So the Claude Code implement and resolve skills end when the head is
pushed: they hand back the pull request number and head SHA. The session that
dispatched the work waits on the checks with one background
scripts/wave-status.sh --wait <PR> and, on a red head, invokes
/implement <issue> --resume, which makes one fix and one push and ends again.
That dispatching session owns the retry count.
Hooks refuse the waits in a subagent rather than rely on the instruction; they
are listed under Hooks are defense in depth.
No agent type is exempt, the implementer (.claude/agents/implementer.md)
included.
A build or check a worker needs before it can continue is the one wait that
stays with the worker, in slices that keep its cache warm.
scripts/agent-job.sh start <name> -- <command> detaches the command, and
scripts/agent-job.sh wait <name> blocks at most 225 seconds and prints one
line whose first word is the answer:
| Answer | Meaning | The worker's move |
|---|---|---|
done | the job ended; the line carries its exit status and log path | continue |
running | the slice ran out | wait again |
handoff | the tenth running answer, about 40 minutes | end the turn with the job name |
lost | the job's process is gone and it recorded no status | read the log |
Each running answer re-reads the worker's context from cache, about a tenth
of the price of rebuilding it cold, so ten of them cost what a fresh worker
would. Past that the dispatching session takes the wait with
scripts/agent-job.sh wait <name> --until-done, which the hooks refuse in a
subagent, and dispatches a fresh worker from the job's exit status and log.
The Codex skills keep their own check loop: the cache behavior and the hooks
are Claude Code's.
Conflicts preserve both intents
Landing predicts the merge against current main. A content conflict is not
permission to choose a resolution inside the landing step. Landing hands the
draft to resolve ($resolve <PR> in Codex, /resolve <PR> in Claude Code),
which merges current main into the same branch, resolves every hunk in
three-way context at any path, with overflow priced at landing, and pushes the
resulting head, which must pass its checks again. It does not rebase,
force-push, open a second PR, or merge. A genuinely incompatible product intent
returns to scope rather than manufacturing a merge.
Landing is a separate authorization boundary
A draft can be landable without being authorized to merge. land independently
revalidates the current issue digest and approval, base ancestry, actual diff
and priced surface overflow, required checks, native review state, threads,
branch ownership, and predicted merge result.
Only then does the explicitly authorized landing clear draft state and perform an ordinary squash merge. Cleanup starts only after GitHub confirms that named PR merged and its closing issue is closed. The exact issue worktree and local branch are removed only when clean; uncertain or dirty artifacts remain for an explicit sweep.
Human contributors
Humans do not need to imitate agent tool syntax, but they should preserve the
same invariants: one focused concept, a linked and scoped issue for planned work,
Conventional Commit titles, isolated implementation, no direct push to main,
and no merge while current-head facts or findings remain open.
The executable Codex contracts are the Codex harness and GitHub workflow contract. Return here for the journey; read the applicable skill before mutating state.