How no-mistakes Orchestrates Pipeline Steps: Review, Test, Lint, Docs, Push, PR, and CI
The no-mistakes CLI orchestrates review, test, lint, docs, push, PR, and CI pipeline steps through a sequential executor that runs each step in order while sharing state via an executionContext, pausing for human review gates when needed.
The no-mistakes repository implements a robust automation framework that coordinates complex software development workflows through a deterministic pipeline. Its architecture executes discrete steps—from initial intent parsing through continuous integration monitoring—while maintaining safety through lease-guarded operations and human-in-the-loop gates. Understanding how these pipeline steps are orchestrated reveals the extensible design patterns that make the tool suitable for both manual CLI usage and autonomous agent operation.
The Core Pipeline Architecture
All steps in the no-mistakes pipeline implement a common interface defined in internal/pipeline/steps/common.go. The orchestrator creates a run object, builds the step list, and executes them sequentially while passing a shared executionContext to each step.
Each step resides in its own source file under internal/pipeline/steps/ and follows a consistent pattern: initialize state, execute core logic, record results to the database, and return control to the executor.
The Eight Pipeline Steps Explained
The default step order is defined as a static slice in the executor. While users can trim or reorder steps via configuration, the standard sequence follows the development lifecycle from intent to CI monitoring.
Intent: Parsing User Commands
The intent step (internal/pipeline/steps/intent.go) parses the user's request to determine which subsequent steps are required. For example, a command to only run tests will trim the lint, push, and PR steps from the execution list.
Review: Human-in-the-Loop Gates
When a run requires human validation, the review step (internal/pipeline/steps/review.go) creates a gate that pauses execution. It sets awaiting_agent_since in the database via db.SetRunAwaitingAgent and surfaces findings to the user. The run remains in a "parked awaiting agent" state visible in axi status until the user responds, at which point db.ClearRunAwaitingAgent clears the flag and execution resumes.
Test: Executing the Test Suite
The test step (internal/pipeline/steps/test.go) executes the repository's test suite using go test -race ./... by default. Results are stored in the SQLite database (internal/db/run.go) and displayed in the CLI UI (internal/cli/axi_render.go). Failures generate evidence objects that can trigger auto-fix routines.
Lint: Static Analysis and Evidence Generation
Running configured linters (such as golint or staticcheck), the lint step (internal/pipeline/steps/lint.go) converts failures into structured evidence objects. These evidence artifacts, defined in internal/pipeline/steps/evidence.go, enable the auto-fix system to programmatically correct issues without human intervention.
Document: Documentation Generation
The document step (internal/pipeline/steps/document.go) acts as a thin wrapper around repository-specific documentation commands. It generates or validates markdown and API documentation, ensuring artifacts remain current before pushing to remote.
Push: Lease-Guarded Force Strategy
Before pushing changes, the push step (internal/pipeline/steps/push.go) calls resolveForcePushDecision from internal/pipeline/steps/forcepush.go to prevent accidental loss of upstream work. The safety check compares the remote tip against the last-seen SHA using git rev-list --cherry-pick. If the push would discard commits not part of the current run, the step aborts with forcePushWouldDiscardError.
PR: Opening and Updating Pull Requests
The pr step (internal/pipeline/steps/pr.go) opens or updates Pull Requests on configured SCM platforms (GitHub, GitLab, Bitbucket). It generates a formatted summary using prsummary.go and attaches relevant evidence and test results to the PR description.
CI: Monitoring and Auto-Fixing
Finally, the ci step (internal/pipeline/steps/ci.go) monitors the CI pipeline for the PR. It implements timeout logic using the ci_timeout configuration from internal/config/config.go, re-arming the idle timeout when the upstream default branch advances. The step auto-fixes failing checks when possible and re-bases the branch if the target changes.
How the Executor Orchestrates Steps
The pipeline execution follows a strict lifecycle managed by the executor in internal/pipeline/steps/common.go.
First, the CLI creates a run record in the SQLite database. Then, pipeline.NewRunExecutor builds the step slice:
steps := []pipeline.Step{
intent.New(),
review.New(),
test.New(),
lint.New(),
document.New(),
push.New(),
pr.New(),
ci.New(),
}
The executor initializes an executionContext (internal/pipeline/steps/execution_context.go) containing references to the repository, database transaction, logger, and a StepState map. It then iterates through the steps, calling step.Run(ctx) for each.
After each step, the executor checks ctx.State.IsCancelled() or the awaiting_agent_since flag. If a gate is hit, the run persists to the database and returns control to the CLI. Otherwise, the executor records the StepResult (success status and evidence) and proceeds to the next step.
Safety Mechanisms and State Management
The orchestration layer implements several safety mechanisms to prevent data loss and ensure reliable execution.
Force-Push Safety: The push step uses resolveForcePushDecision to verify that force-pushing will not discard upstream commits. It aborts with an error if the safety check fails, protecting against race conditions with other developers.
Evidence and Auto-Fix: Steps can produce evidence objects that describe failures in a machine-readable format. When the executor detects auto-fixable evidence, it calls runFix from internal/pipeline/steps/common_fix.go to automatically correct issues before proceeding.
Database Persistence: Run state, including the awaiting-agent timestamp and step results, persists to internal/db/run.go. This allows the CLI to resume interrupted runs and enables the axi commands to display live, color-coded progress bars.
Summary
- Sequential Execution: The executor runs steps in a fixed order (intent → review → test → lint → document → push → pr → ci) defined in
internal/pipeline/steps/common.go. - Shared Context: Each step receives an
executionContextcontaining the repository, database handle, and logger, enabling stateful operations across the pipeline. - Human Gates: The review step pauses execution by setting
awaiting_agent_since, allowing human validation before continuing. - Safety First: The push step implements lease-guarded force-push logic via
resolveForcePushDecisionto prevent accidental commit loss. - Auto-Fix Capability: Lint, test, and CI steps generate evidence that triggers automatic fixes through
runFixwhen possible. - CI Monitoring: The CI step monitors external pipelines with configurable timeouts and auto-rebases when target branches change.
Frequently Asked Questions
How does no-mistakes handle pipeline interruptions or user review?
When a step requires human intervention, the review step sets awaiting_agent_since in the database via db.SetRunAwaitingAgent and returns control to the CLI. The run enters a "parked awaiting agent" state visible in axi status. Once the user responds, db.ClearRunAwaitingAgent clears the flag and the executor resumes from the next step.
What prevents no-mistakes from overwriting remote commits during push?
The push step calls resolveForcePushDecision in internal/pipeline/steps/forcepush.go to compare the remote tip with the last-seen SHA using git rev-list --cherry-pick. If the push would discard any upstream commits not present in the current run, the step aborts with forcePushWouldDiscardError, preventing accidental loss of work.
Can individual pipeline steps be skipped or reordered?
Yes. The intent step (internal/pipeline/steps/intent.go) parses the user's command to determine which steps are necessary. Users can configure the pipeline to skip specific steps (such as linting) or the executor can trim the default step slice before execution begins.
How does the CI step handle long-running pull requests?
The CI step uses the ci_timeout configuration from internal/config/config.go. It re-arms the idle timeout whenever the upstream default branch advances, ensuring that long-lived PRs are not terminated merely because they remain open. The step also auto-fixes failing checks and re-bases the branch when the target changes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →