# How to undo any of this

Written 5 August 2026. Kept current as work lands.

Every piece of work is one branch, merged fast-forward into `dev` and then
deleted. That means `dev` is a straight line with no merge commits, and any
commit can be undone on its own without disturbing the ones after it.

## The rule this relies on

**One subject, one branch, one commit.** A branch that does two things cannot
be half reverted, and the first time somebody needs to undo one of the two is
the moment that stops being a matter of taste.

Branch names say what kind of change they carry:

| Prefix | Means |
| --- | --- |
| `feature/` | something a person can now do that they could not before |
| `fix/` | behaviour that was wrong |
| `chore/` | housekeeping, no behaviour change |
| `docs/` | prose only |

## Undoing one thing

Find it in the list below, then:

```sh
git revert <commit>          # keeps the history honest, adds a commit
```

Not `git reset`. `dev` is pushed and shared, and rewriting it moves the ground
under anybody else's checkout. A revert says what happened; a reset pretends it
did not.

If the commit touched the database schema, read the migration note beside it
first. **A revert of application code does not undo a migration.**

## What is on `dev`, newest first

Each line: what it does, and what to know before undoing it.

| Commit | What it does | Undoing it |
| --- | --- | --- |
| `859e97e` | removes a dead menu on `/positions` | safe, cosmetic |
| `328b64f` | notifications arrive over SSE | safe; the outbox below keeps working without it |
| `cc47c73` | `<html lang>` follows the reader | safe; also memoised `currentUser`, which is what makes it free |
| `3c2899e` | the eleven-account development panel | **archives a person**, so reverting the code leaves the data. Run `db:panel` notes |
| `295779c` | the notification outbox and the in-app channel | **adds two tables.** Reverting the code leaves `domain_events` and `notifications` behind, harmless but present |
| `d7dc40f` `1b7e8fd` | Better Auth documentation | prose only |
| `e6b525d` | `/settings`, changing your own password | safe; also closed `/change-password` on HTTP |
| `55a7099` | ten failed sign-ins per ten minutes | safe; counters are in memory and vanish on restart |
| `dda3ee8` | closes three auth routes nobody uses | safe, and reopening them is what the issue argued against |
| `5094565` | `/team` rebuilt as counters and collapsed runs | safe |
| `b4447b4` | an admin can hold several departments | safe |
| `b994bb3` | `/team` exists at all | safe |
| `d357881` | every built screen is reachable, `/preview` gone | safe |
| `ee8e98c` | `/admin/people`, HR opens a login | safe; logins already opened stay opened |
| `0816b68` | the week is six days | **a migration and a data change.** See below |

## The two that need care

**`0816b68`, the six-day week.** It changed a column default and rewrote all 193
rows. Reverting the code puts the default back; it does not put the rows back,
and it should not, because the six-day week is the client's answer and the
five-day one was a placeholder nobody chose. If it ever has to go back, it is a
deliberate `UPDATE`, not a revert.

**`295779c`, the outbox.** Two new tables. Reverting the application code stops
anything writing to them and leaves them in place. That is the right order: drop
a table only when nothing has referred to it for a while, and never in the same
step as the code that stopped using it.

## When a revert is not enough

Anything that changed data rather than code needs its own undo, and there is no
general one. The scripts under `tmp/` from the session that made the change are
usually the fastest way to see what was touched; they are throwaway by
convention and gitignored, so they will not be there later. If a change to data
matters enough to undo, the way to undo it belongs in the commit message.

## Running more than one agent at once

Two things went wrong on 5 August and both are cheap to avoid.

**Two agents shared one working tree**, and the second switched its branch
under the first. Nothing was lost, because the first had written nothing yet,
but it could have been. Every concurrent agent gets its own git worktree, and
the worktree is removed and its branch deleted the moment the work is merged.
An abandoned worktree is several gigabytes and a branch nobody remembers.

**Two agents shared one database**, and one restored a `pg_dump` over it while
the other was working. Again nothing committed was lost, because code lives in
git and the database was about to be rewritten anyway. It was still the wrong
move.

The rule that follows: **a worktree isolates code, not data.** Postgres is one
server and every agent points at the same one. So an agent that needs to change
data at scale works on a copy, and an agent that only needs to read or to touch
a handful of rows snapshots what it touches and puts it back, comparing against
its own snapshot rather than a number from a brief that another agent may have
invalidated in the meantime.

Anything an agent is told about counts in the database is true when the brief is
written and possibly false ten minutes later.

## Two things deliberately left dangling

**The branch `feature/team-5a-visual`, and the stash on it.** A visual pass at
`/team` was started on 4 August and stopped part way, because it was making the
screen worse rather than better. The branch carries no commit of its own; the
work is in `stash@{0}`, labelled `passe visuelle 5a, inachevee`.

Neither is worth reviving as it stands, and neither is deleted, for the same
reason: the pass failed on a premise rather than on execution. It was written
against the palette in the design project's `app/globals.css`, which is a
different design system from the one this repository implements. The mockup is
indigo and amber on dark cards; this application's `--primary` is a bright
cyan and it has no warning colour at all.

**That is the decision nobody has taken**, and it is worth taking before
anybody spends another hour on the look: either the repository adopts the
design system the mockups are drawn in, which changes every screen, or the
mockups get redrawn in the palette that exists. Until then no amount of work on
one screen will make it resemble its design, which is what that stash proves.

`git stash show -p stash@{0}` reads it. `git stash drop` is a decision, so it
has not been taken here.
