Appearance
Chapter 3 - The Terminal Loop: Writing and Refactoring
Once intent and context are established, the work moves to the terminal. In classic Extreme Programming (XP), two engineers sat at one keyboard, passing control back and forth in symmetric collaboration. In aiXP, the dynamic is fundamentally asymmetric: the AI generates code at machine speed, but possesses zero organic awareness of architectural intent.
Four disciplines govern this active pairing loop at the terminal:
- Asymmetric Pairing: Dividing responsibility cleanly between human intent and automated execution.
- Test-Driven Development: Authoring tests upfront as mechanical prompt constraints and binary verification gates.
- Bounded Refactoring: Enforcing strict blast-radius controls against unrequested code modifications.
- Simple Design and YAGNI: Pruning machine-speed over-engineering before it enters trunk.
Asymmetric Pairing
Asymmetric Pairing assigns mutually exclusive, non-overlapping responsibilities: the human engineer navigates intent and verification, while the AI driver generates execution within bounded constraints.
The Failure Mode
When an engineer abdicates navigation and attempts to "co-type" with an agent, or asks open-ended questions like "How should we design this feature?", architectural coherence degrades immediately. The agent generates plausible, verbose abstractions to solve hypothetical problems the system does not have. Overwhelmed by streaming diff volume, the human slips into passive observation, skimming changes rather than applying rigorous review.
The Mechanism
In classic XP pairing, the Navigator caught typos, suggested variable names, and anticipated the next function. With an AI pair partner, generation outpaces manual line-by-line proofreading. The Navigator's responsibility moves up the abstraction ladder:
- The Human Navigator: Maintains the mental model, polices architectural boundaries, reviews diffs against acceptance criteria, probes edge cases, and retains exclusive authority to merge or revert changes.
- The AI Driver: Generates implementations, drafts test cases to specification, runs local build commands, and executes scoped refactoring passes within explicit boundaries.
The pairing cadence relies on short, bounded round-trips: the Navigator issues a constrained instruction, the Driver executes, the test runner validates, and the Navigator audits the diff before moving to the next step.
Trade-Offs and Boundary Conditions
- Cost: Asymmetric pairing demands active, critical concentration. The Navigator cannot zone out while tokens stream across the console; every generated line must be justified.
- When NOT to use: Routine, deterministic boilerplate updates (e.g. updating dependency versions across twenty microservices) do not require active pairing; those can be offloaded to headless batch scripts with post-hoc pull request review.
Test-Driven Development (TDD)
In aiXP, Test-Driven Development is load-bearing infrastructure. The test is authored before the implementation, serving simultaneously as the unambiguous prompt constraint for the AI Driver and the automated verification gate.
The Failure Mode
If an agent writes implementation code first and generates tests afterward, it writes tests that conform to its own internal assumptions. The tests prove only that the code does what it does, not what the specification requires. If the implementation contains an off-by-one calculation, a race condition, or a missing validation check, the post-hoc test suite dutifully asserts that incorrect behavior as the baseline truth.
The Mechanism
The test-first loop remains strictly disciplined:
- Red (Test First): The human Navigator directs the AI to write tests encoding the acceptance criteria from the micro-spec. The test must execute and fail with the expected diagnostic message before any feature code is written.
- Green (Minimal Implementation): The AI generates the minimal code necessary to satisfy the failing test. The Navigator inspects the diff to verify that no unrequested helper functions or side effects were introduced.
- Refactor (Clean Up): The implementation is cleaned, typed, and formatted while the test harness runs continuously to verify zero regressions.
Because language models generate plausible, incorrect syntax with equal ease, TDD provides the fastest mechanical boundary available. It converts ambiguous natural language into binary passes and failures.
Trade-Offs and Boundary Conditions
- Cost: Requires writing concrete assertions before seeing a working implementation in the terminal or browser.
- When NOT to use: Visual and tactile exploratory work (such as tweaking UI animations, evaluating typography contrast in varied lighting, or testing touch gestures on mobile hardware) cannot be fully captured in headless unit tests. In Perception-Gated Work, visual verification takes precedence, but underlying state transitions and data contracts must still be anchored by automated tests.
Bounded Refactoring
Bounded Refactoring strictly limits AI modifications to pre-approved scope, rejecting changes that expand beyond the active task.
The Failure Mode
In manual programming, typing effort acts as a natural brake against excessive refactoring. With an AI pair partner, generation is computationally free. When asked to fix a bug or add a parameter, an agent will frequently reformat surrounding methods, rename variables in adjacent files, swap working dependencies for alternative libraries, and reorder imports. These unprompted changes produce bloated diffs that obscure the core change and introduce silent regression risk.
The Mechanism
aiXP shifts refactoring discipline from encouraging clean code to constraining change volume:
- Separate Commits: Refactoring passes and functional behavior changes are isolated in separate commits. Never combine a refactor and a feature update in a single prompt.
- Diff Screening: The Navigator audits every diff against a strict criterion: "Did I authorize this specific line to change?" Any unrequested modification is reverted immediately.
- Explicit Scope Directives: Prompts explicitly lock down files and directories outside the task boundary:
text
Fix the off-by-one boundary check in calculate_retry_delay().
Constraint: Do not reformat neighboring functions, do not modify package imports,
and touch no file other than src/network/retry.ts.Simple Design and YAGNI
Simple Design and You Aren't Gonna Need It (YAGNI) defend the codebase against machine-speed over-engineering and premature abstraction.
The Failure Mode
Because LLMs are trained on massive corporate repositories and academic code samples, they exhibit a strong bias toward defensive over-engineering. Prompted for a simple lookup table, an agent will readily generate generic repository interfaces, abstract factories, dynamic registries, and multi-tenant configuration handlers. Because generating 200 lines of boilerplate takes three seconds, the friction that once discouraged unnecessary complexity is gone. The resulting code is noisy, brittle, and difficult to verify.
The Mechanism
In aiXP, architectural waste is an output-volume problem. The Navigator enforces the four rules of simple design as a filter on all generated code:
- Passes all tests: Verification gates are satisfied.
- Reveals intent: Names and data flows are direct and legible without layers of indirection.
- No duplication: Eliminate accidental duplication, but recognize that duplication is far cheaper than the wrong abstraction.
- Fewest elements: Delete speculative interfaces, unused configuration parameters, and hypothetical extension points. If a lookup requires a plain dictionary, reject the abstract factory.