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:

QuestionAuthoritative 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.

IntentCodex workflowDurable result
Explore a felt absencewishAn idea tree, not automatically an issue
Capture a rough single ideasketchAn open unscoped issue
Ground the problem, design, Plan, surface, and routescopeComplete managed issue-body artifacts
File selected unrelated scope observationsscope-spinoffLinked unscoped issues
Answer open questions from the design rulebooksettleSettled answers applied; Leaning and Open ones for the owner
Authorize a complete PlanapproveA trusted hidden digest/base-bound record
Implement approved workimplementA reviewed, green draft PR with priced overflow reported
Audit existing code or a non-PR changereviewA read-only findings rollup
Merge current main into a content-conflicted draftresolveThe same draft, green and re-reviewed on a merge commit
Land an accepted draftlandMerged PR, closed issue, and safe cleanup
Reclaim proven-stale local statesweepOnly the explicitly confirmed cleanup
Capture repeatable session frictionretrospectConfirmed unscoped issues, if any
Draft a load-bearing decisionadrProposed 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:

  1. no reviewer's latest active native decision is changes requested; and
  2. 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:

AnswerMeaningThe worker's move
donethe job ended; the line carries its exit status and log pathcontinue
runningthe slice ran outwait again
handoffthe tenth running answer, about 40 minutesend the turn with the job name
lostthe job's process is gone and it recorded no statusread 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.