Skip to main content

0002. Dual development pathways: traditional + AI-assisted

Context and problem statement

An AI coding agent can take a GitHub Issue, open a draft PR, and iterate to green CI without a human author writing a line of code. The question is not “can we let it implement everything?”; that bar is too low, since current code-generation models are not reliable on architecture work. The question is “which subset of issues is the agent allowed to implement, and how do we make that boundary obvious to maintainers, contributors, and the tooling?”. If the boundary is implicit, two failure modes follow: the agent starts ghost-writing architecture (bad outcomes), or maintainers stop using it for the trivial work where it actually saves time (lost benefit). This decision is about the boundary, which is independent of which agent implements. For the implementer choice itself, see Decision outcome below.

Decision drivers

  • The review bar must not change. Maintainer effort per PR stays the same; the savings come from cheaper authorship, not cheaper review.
  • Pathway membership must be a single, visible signal, readable from the Issues list without opening each issue.
  • The boundary must be enforceable in the human triage step, not in code. Process beats automation here.
  • Architecture decisions must remain human-owned: a human must consciously authorize any change that would need an ADR. ADR existence (ADR-0000) is the canonical marker the plan flags for that decision.

Considered options

  1. No AI authorship. Humans implement everything.
  2. AI authorship on all issues. Copilot takes any assigned issue.
  3. AI authorship gated by issue label (path:ai-automation), applied by a maintainer at triage time per a fixed checklist.
  4. AI authorship gated by a CODEOWNERS file: paths declare whether AI may modify them.

Decision outcome

Chosen option: gate by issue label, applied at triage time. The label is path:ai-automation. Default is path:traditional (or the absence of any path label). The label is the entry signal; the plan stage then surveys the change for risk and the assignee decides. This replaces the original hard gate (see the 2026-06 update below): the agent no longer refuses or self-routes on scope grounds, because a human consciously authorizes every implementation. What the plan assesses and records, as plain notes, so the reviewer sees the shape of the work:
  • Size and layer span (one layer typical; two or more is fine when the plan is clear).
  • DB schema changes or migrations.
  • New runtime dependencies.
  • Public-API contract changes.
  • Whether an architectural decision is involved (an ADR may be warranted).
The plan raises an explicit ⚠️ warning only for the two genuinely higher-risk traits:
  • A security-sensitive surface (auth, crypto, file uploads, deserialization).
  • A destructive or irreversible database migration.
A warning is a flag for the assignee, never a refusal. The assignee is the gate: commenting /approve-plan is the explicit human authorization to implement the plan in full, warnings included; declining (closing the PR, or relabelling path:traditional) sends the work to a human author. The review and merge gate at the end is unchanged.

Update (2026-06): warn-and-approve, not a hard gate

Originally (2026-05) this decision was a hard, mechanical gate: a change qualified for the AI pathway only if all of a checklist held (small and self-contained, no schema or migration, no new dependency, no public-API change, no security-sensitive surface, no ADR needed, quickly verifiable), and a single unchecked box forced the issue to the traditional pathway. In practice that bar excluded almost anything that persisted or exposed data, so the plan or implement stage refused most labelled issues even after a maintainer approved them, which defeated the point of approval (see PRs #72 and #74, approved then refused). We keep the human in the loop but move the decision from a checklist to the assignee. The plan still assesses the same signals and records them, and it warns (⚠️) on the two traits where caution genuinely pays (security-sensitive surfaces, and destructive or irreversible migrations), but it no longer refuses or self-routes. /approve-plan is now a real authorization: once a maintainer approves, the implement stage builds the plan in full rather than stopping on triviality grounds. Architecture stays human-owned because a human reads the plan, sees the warnings, and consciously authorizes the work; the final human review and merge gate is unchanged.

Implementer: provider-agnostic, not Copilot-specific

The pathway is implemented with GitHub Agentic Workflows (gh-aw) running a configurable model (default: Claude Opus, set via the AI_MODEL repo variable) on the repository’s own ANTHROPIC_API_KEY, not the GitHub Copilot Coding Agent. The reason is access: Copilot’s coding agent is entitlement-gated to the initiating user, so only maintainers holding a paid Copilot seat could dispatch it. Running the agent inside GitHub Actions on the repo’s key means any maintainer with write access can drive the full flow without a Copilot seat, and all AI cost falls on the repo (API key + Actions minutes). The trade-off is that we own the prompt-injection hardening (mitigated by the four guardrails in ai-pathway.md: write-access-only triggers, no secrets to forks, least-privilege read-only agents, human-only merge). Copilot remains a drop-in alternative implementer for anyone who has a seat. The as-built flow is documented in ai-pathway.md. Update (2026-06): the implementer is now selectable per issue via the pathway label, without changing this decision. path:ai-automation-claude runs the Claude engine on the repo’s ANTHROPIC_API_KEY, seat-free; path:ai-automation-codex runs Codex/OpenAI (OPENAI_API_KEY), also seat-free; path:ai-automation-copilot (and the bare path:ai-automation alias) runs Copilot, which still needs a Copilot seat (COPILOT_GITHUB_TOKEN). The bare path:ai-automation label now defaults to the Copilot engine (changed from Claude, 2026-06). Assigning the HAI-Coco bot account to an issue automatically adds path:ai-automation, triggering the Copilot pipeline without a separate labelling step. Per-engine models are set with AI_MODEL_CLAUDE / AI_MODEL_CODEX / AI_MODEL_COPILOT (AI_MODEL still feeds Claude), and each stage can be overridden independently via the optional AI_MODEL_<ENGINE>_<STAGE> variables (STAGE in PLAN/IMPLEMENT/ITERATE/REVIEW), which take precedence over the per-engine value. See ai-pathway.md §2.6.

Positive consequences

  • The pathway membership is one click in the labels UI, visible on the issues list, the Project board, and to every reviewer.
  • The two pathways converge at the same review gate. CODEOWNERS approval, branch protection, and CI are all unchanged.
  • The agent never ghost-writes architecture by accident: an architectural change surfaces in the plan (warned where it touches a security-sensitive surface or a destructive migration), and a human must consciously authorize it with /approve-plan before any code is written.

Negative consequences

  • The maintainer is the bottleneck: every issue gets one human-applied label. We accept this; triage is already a 30-min/week activity.
  • The checklist is a judgement call, not a regex. The benefit is that borderline cases get a human eye, which is the right outcome.
  • We need a different PR-side signal for who authored the change. The agent’s PRs carry the path:ai-automation label and are authored by the automation token’s account; the issue’s assignee is carried onto the PR as the PR assignee (falling back to the maintainer who applied the label when the issue is unassigned).

Pros and cons of the options

Option 1: No AI authorship

  • + No risk of bad architecture.
  • Throws away the real benefit of trivial-work acceleration.

Option 2: AI on all issues

  • + Fastest path on the trivial subset.
  • The agent will attempt architecture. Bad outcomes.

Option 3: Label-gated (chosen)

  • + Visible, reversible, requires no code changes to enforce.
  • Relies on maintainer discipline at triage.

Option 4: CODEOWNERS-gated

  • + Mechanically enforceable on PRs.
  • Mixes ownership with authorship. CODEOWNERS is about review, not authorship. The wrong axis to overload.