Docs / Start here
Concepts
The change lifecycle
Every change, whatever the system, follows the same state machine:
proposed → planned → rehearsed → (auto-approved | awaiting-approval → approved | rejected)
→ applying → applied → verifying → verified → (undoing → undone)
- Plan: the adapter works out the exact effect without changing anything.
- Postgres and MySQL: the statement runs in a transaction that is always rolled back. That captures the rows, before/after values, locks taken and tables rewritten.
- Kubernetes: a server-side dry run against the live objects.
- Terraform: a plan file.
- Config files: validated (e.g.
nginx -t) without a reload. - REST APIs: the manifest's
beforeread.
- Decide: policy turns the plan into
approve,require(approval needed, with a channel and approvers) ordeny. - Apply: only the planned operation is executed, and only if the target still matches the plan. Postgres checks that the rows haven't changed; Kubernetes, the desired-state hash; Terraform, the exact plan file. Otherwise the apply stops with a conflict and you plan again.
- Verify: an adapter-specific check that the effect matches the plan: the same rows, an empty Terraform re-plan, a healthy rollout, passing health checks.
- Undo: the recorded inverse is applied, guarded the same way. It touches only what is still as the change left it.
Each change has a plan ID (p_…) and a change ID (c_…), and a step number (#3) in its session.
Commands accept any of them.
Two lanes
| Direct lane | CI lane | |
|---|---|---|
| Who | An agent (or a person) acting on a live system | A pull request |
| Entry points | MCP server, changeward exec, hooks, SDKs, executor, gateways |
rehearse + gate, tf review, k8s gate, GitHub Action, GitLab component |
| Evidence | A live dry run against the target | A rehearsal on a throwaway copy, or a dry run against the cluster |
| Result | Applied and undoable, on a session timeline | A PR comment, a commit status, a merge or deploy gate |
The same policy file governs both; rules can check change.lane.
Promotion
Direct changes in dev shouldn't stay only in dev. changeward promote turns a session's applied changes into
migration files for your framework. The up is the SQL as run. The down is generated from the recorded undo
data, so the rollback is one that was actually exercised.
With --pr, it opens a pull request carrying the session timeline, and the CI lane then rehearses it.
Kubernetes changes are promoted to manifests (--k8s-dir). For changes made directly to Git-managed systems
during an incident, changeward reconcile opens the matching PR. changeward drift reports any that are still
unreconciled.
Environment classes
A target's class is set when you connect it, and an agent can never change it:
| Class | Built-in default for direct writes |
|---|---|
personal |
Reversible changes, or checkpoint-only changes with a checkpoint taken, are auto-approved. Anything else asks you inline, in the agent's UI. |
shared-dev |
Auto-approved if reversible, non-destructive and under 1,000 rows; otherwise you confirm. |
staging |
Auto-approved if reversible, non-destructive and under 10,000 rows; otherwise a second person approves, out of band. |
prod |
Needs an incident or ticket reference, plus out-of-band approval by someone other than the proposer. |
prod-restricted |
Read-only in the direct lane. |
In CI: reversible, rehearsed and non-destructive changes are auto-approved as standard changes; anything else needs review by code owners. Your own rules take precedence (policy.md).
Reversibility classes
| Class | Meaning | Examples |
|---|---|---|
reversible |
Exact undo from recorded state | Postgres DML (row images); additive DDL; soft-dropped DROP TABLE/DROP COLUMN/TRUNCATE; Kubernetes object changes; a config-file change |
compensatable |
An inverse operation exists, but it isn't byte-for-byte | Closing a GitHub issue to undo creating it; re-creating a deleted resource under a new id |
checkpoint-only |
Undo needs a checkpoint of the whole target | ALTER TYPE, column type changes, INSERT … SELECT on MySQL |
irreversible |
Nothing can bring it back | Sending email, terraform destroy of a database, an unmatched API call |
Policy sees the class, so "irreversible in prod" can be denied or sent to a DBA.
Sessions
A session groups an agent's work on one target, with who (agent and delegating human), when, and why
(--incident). The MCP server starts one automatically. On the command line, use changeward session start.
changeward log: the timeline.changeward undo STEP: undo a step. Later steps that touched the same objects are undone first, or listed if you don't pass--yes.changeward rewind: undo the whole session, newest first.
Checkpoints
Checkpoints make checkpoint-only changes safe. They are taken with session start --checkpoint,
changeward checkpoint, or the agent's checkpoint tool, and restored with changeward restore.
| Postgres strategy | How |
|---|---|
template (local) |
CREATE DATABASE … TEMPLATE |
dump |
pg_dump / pg_restore |
| Neon | A branch at the current LSN (neon_project_id, neon_api_key); restore keeps an ancestor branch |
changeward branch create points a session at a private copy of the target (a Neon branch, or a template copy)
so an agent can experiment freely. changeward branch discard throws the copy away.
Approvals
- Inline: confirmed by the delegating human in the agent's own UI, through MCP elicitation. Allowed only
where policy says
channel: inline(personal and shared-dev defaults). - Out of band:
changeward approve PLAN_ID, with--executoron a shared executor, Slack buttons throughchangeward serve, or the web view. The approver must be someone other than the proposer. - An approval binds to the plan hash. If the data or the change moves after approval, the change must be planned again and approved again.
- Agents can't approve. The hooks block
changeward approvefrom agent shells, and the executor's roles keepproposeandapproveseparate.
Changesets
changeward changeset plan -f changes.yaml plans ordered steps across systems, for example a migration and a
Kubernetes rollout. changeset apply runs them as a saga: if a step fails, the earlier steps are undone in
reverse order. changeset undo reverts the whole set.
Audit log
Every event goes to an append-only, hash-chained log: proposals, plans, decisions, approvals, applies, undos,
blocked hook attempts and gateway decisions. changeward audit verify checks the chain.
With telemetry.otlp_endpoint set, each change is also exported as an OpenTelemetry trace, with a span per
state. Attributes only, never row values.
What Changeward never does
- It never sends row values anywhere. Plans shown to agents redact
sensitivecolumns, and production plans hide values. CI reports contain counts and checksums only. - It never runs a statement with outside effects while planning.
- It never lets an approval carry over to a different plan.
Edit this page on GitHub · synced from 89c04c9