# `leeroy-wip` history rewrite process (non-destructive, auditable)

This document defines the **end-to-end process** to rebuild the `leeroy-wip` branch into a clean, coherent commit history while **keeping the original branch untouched** so other agents can continue working.

Scope: **planning + execution of the rewrite**, not feature changes.

## Goals

- Keep `leeroy-wip` **unchanged** and available for ongoing work.
- Build a new branch (`rewrite/clean-stack`) with a **clean linear history**:
  - commits represent the **final correct state** of each feature/fix (not the “evolution”)
  - keep **useful commit granularity** (avoid 1 mega-commit per PR)
  - improve commit subjects/bodies so reviewers understand **what/why**
- Create **PR boundary markers** so we can later cut stacked PR branches mechanically.
- Preserve provenance in a **ledger** (old commits → new commits) so we can:
  - prove equivalence (`range-diff`, `diff --stat`)
  - audit that no commits/features were dropped unintentionally

## Non-goals

- Do not rebase or otherwise rewrite `leeroy-wip`.
- Do not “fix” unrelated code during rewrite (rewrite should be behavior-preserving vs the frozen baseline).
- Do not create backups early “just in case”; backups are taken **right before** rewrite execution.

## Source-of-truth inputs

- Commit-by-commit deep review: `docs/commit-audits/happy/leeroy-wip.commit-manual-review.md`
- Commit → final PR assignment (source of truth): `docs/commit-audits/happy/leeroy-wip.pr-assignment.working.tsv`
- PR definitions: `docs/commit-audits/happy/leeroy-wip.pr-catalog.draft.md`
- Split guidance: `docs/commit-audits/happy/leeroy-wip.split-plan.draft.md`
- Patch artifacts (Pass2): `/tmp/leeroy-wip-pass2/NNN.patch`

## Tracking outputs (rewrite execution)

These two files are the execution control plane (always update them as you go):

- Rewrite ledger: `docs/commit-audits/happy/leeroy-wip.rewrite-ledger.tsv`
  - one row per **original commit NNN**
  - records whether it was cherry-picked, split, squashed into another commit, or dropped as a net no-op
  - records the **new commit SHA(s)** created in `rewrite/clean-stack`
- Rewrite status board: `docs/commit-audits/happy/leeroy-wip.rewrite-status.tsv`
  - one row per **PR slice**
  - records start/end new SHA, boundary tag, validation commands run, notes

### Deferred fragment tracking (mandatory when splitting/deferring)

To ensure each PR slice represents the **final state** of that feature/fix (and to ensure we don’t “lose” parts of mega-commits), we also maintain:

- Deferred fragments tracker: `docs/commit-audits/happy/leeroy-wip.rewrite-deferred-fragments.tsv`
  - one row per **intentionally deferred file/hunk** from an original commit
  - records the **target PR**, path, reason, and resolution status (`pending` → `resolved`)

Hard rule:
- If you split an original commit and do **not** bring all its changes into the current PR slice, you **must** add rows for the deferred pieces immediately.

## Hard invariants (must follow)

- All git operations must go through `happys wt git ...` (no raw `git` directly).
- Never modify default checkouts under `components/<component>`; use worktrees only.
- Never rebase `leeroy-wip`. Never force-push it. Never amend commits on it.
- Rewrite happens only in the rewrite worktree/branch.
- Every original commit in scope **must** be accounted for in the ledger (pick/split/squash/drop).
- By default: **i18n is folded into the owning feature PR**, not centralized, unless explicitly decided otherwise.

## Ensuring “final state per PR” is actually true

We cannot “prove” final-state correctness until the full rewrite completes and we compare to the frozen baseline (Phase E).
But we can enforce strong guarantees during execution:

1) **PR slices are defined by final feature buckets**, not chronology:
   - The picklist for PRxx includes *all* original commits assigned to PRxx (even if they happened late in `leeroy-wip`).
   - Therefore, bugfixes for a feature are applied in the same PR slice, yielding the feature’s “final state” at the PR boundary.

2) **PR boundary means “no more changes for this feature”**:
   - Before tagging `rewrite/prXX-end`, ensure:
     - the working tree is clean
     - all PRxx commits are accounted for in the ledger
     - any deferred fragments have explicit rows in `rewrite-deferred-fragments.tsv`

3) **Post-boundary drift detection**:
   - If a later PR slice touches “owned” files from an earlier PR (beyond expected cross-cutting infra), treat that as a signal:
     - either the change belongs in the earlier PR and should be pulled down, or
     - the PR boundaries/ownership need explicit documentation.

## Phase A — Freeze a baseline snapshot (right before rewrite execution)

Purpose: create immutable anchors so we can prove “rewritten history == baseline end state”.

Run in the `leeroy-wip` worktree:

1) Record anchors (copy into `leeroy-wip.commit-inventory.md`):
- `happys wt git happy slopus/tmp/leeroy-wip -- rev-parse upstream/main`
- `happys wt git happy slopus/tmp/leeroy-wip -- merge-base HEAD upstream/main`
- `happys wt git happy slopus/tmp/leeroy-wip -- rev-parse HEAD`

2) Create immutable refs pointing at the baseline HEAD:
- `happys wt git happy slopus/tmp/leeroy-wip -- branch backup/leeroy-wip-YYYY-MM-DD HEAD`
- `happys wt git happy slopus/tmp/leeroy-wip -- tag -a backup/leeroy-wip-YYYY-MM-DD -m "leeroy-wip rewrite baseline" HEAD`

3) Create a portable bundle snapshot:
- `happys wt git happy slopus/tmp/leeroy-wip -- bundle create /tmp/leeroy-wip-YYYY-MM-DD.bundle upstream/main..HEAD`

## Phase B — Create one rewrite worktree + one rewrite branch

Create a new worktree from `upstream/main` (example names):

- Worktree: `slopus/tmp/leeroy-rewrite`
- Branch: `rewrite/clean-stack`

Example:
- `happys wt new happy tmp/leeroy-rewrite --from=upstream --use`
- `happys wt git happy slopus/tmp/leeroy-rewrite -- checkout -b rewrite/clean-stack upstream/main`

## Phase C — Lock the PR execution order

We reconstruct a single linear branch by applying **PR slices** in an intentional order (dependency-safe, but still feature/fix oriented).

Rule:
- Write the final PR order into `leeroy-wip.rewrite-status.tsv` (top-to-bottom).
- Do not change that order mid-flight without documenting the reason (and updating the TSV).

## Phase D — The reconstruction loop (PR slice by PR slice)

For each PR (in the locked order):

### D1) Compute the PR picklist

Use `leeroy-wip.pr-assignment.working.tsv` to list all commits where `finalPr == PRxx`.

Picklist must be:
- ordered by `n` (oldest → newest)
- include `needsSplit` / “drop/squash” notes

### D2) For each commit in the picklist, decide the action (must be ledgered)

For commit `NNN`:

1) Read the full commit section:
   - `docs/commit-audits/happy/leeroy-wip.commit-manual-review.md` `## NNN ...`
2) Read the patch (mandatory for split decisions and safety-critical changes):
   - `/tmp/leeroy-wip-pass2/NNN.patch`
3) Choose one action and record it immediately in the ledger:
   - `pick`: cherry-pick as-is (maybe with message rewrite)
   - `split`: cherry-pick `-n`, then `git add -p`, produce multiple focused commits
   - `squash-into`: do not cherry-pick this commit; absorb its change into another new commit in this PR slice
   - `drop-net-noop`: only when it is a revert pair or true net no-op (must explain)
   - `defer`: only when the *entire* original commit belongs to a later PR slice due to ordering dependencies

If the action is `split` and some changes are intentionally not applied:
- add rows to `leeroy-wip.rewrite-deferred-fragments.tsv` for each deferred file/hunk.

### D3) Apply the change in the rewrite worktree

Commands (examples; always use `happys wt git happy slopus/tmp/leeroy-rewrite -- ...`):

- Pick:
  - `cherry-pick <oldSha>`
  - optionally `--edit` to rewrite subject/body to Conventional Commits

- Split:
  - `cherry-pick -n <oldSha>`
  - `git add -p` (multiple times)
  - `git commit -m "feat(scope): ..." -m "<why + constraints + key behavior>"`
  - repeat until the working tree is clean

- Squash-into:
  - do not cherry-pick the commit
  - apply the relevant hunks when you build the “final” commit for the feature
  - ledger must point to the “destination” new commit SHA(s)

### D4) Commit message rules (mandatory)

Each rewritten commit must have:
- Conventional Commit subject (`feat|fix|refactor|test|chore(scope): ...`)
- body that answers:
  - **what changed** (observable behavior)
  - **why** (user problem / reliability / safety / invariants)
  - any **constraints** (back-compat, migrations, ordering)

Do **not** copy-paste old SHAs into commit messages.
Provenance is preserved in `leeroy-wip.rewrite-ledger.tsv`.

### D5) Close the PR slice

When all commits assigned to PRxx are accounted for (ledger complete for those NNNs):

1) Run validation appropriate to the slice:
   - `happys typecheck ...`
   - `happys test ...`
2) Record validation commands + results in `leeroy-wip.rewrite-status.tsv`.
3) Create a boundary marker at HEAD:
   - tag: `rewrite/prXX-end`
4) Record:
   - `prEndNewSha`
   - `boundaryTag`

## Phase E — Final equivalence proof

When `rewrite/clean-stack` is complete:

1) Compare to the frozen baseline:
   - `range-diff upstream/main...backup/leeroy-wip-YYYY-MM-DD upstream/main...rewrite/clean-stack`
   - `diff --stat upstream/main...backup/leeroy-wip-YYYY-MM-DD upstream/main...rewrite/clean-stack`
2) If differences exist:
   - decide if intentional
   - otherwise fix the rewrite branch (do not touch `leeroy-wip`)

## Phase F — Cut stacked PR branches from boundary markers (later)

Once the full rewrite stack is validated:

- PR01 branch = `rewrite/pr01-end`
- PR02 branch = `rewrite/pr02-end` (base is PR01 boundary)
- …

Because each PR slice has a boundary tag, branch cutting is mechanical and safe.

## Handling new commits landing on `leeroy-wip` during rewrite

1) Audit only the delta (append to docs; update TSV).
2) Assign new commits to existing PRs when they belong to an existing final feature/fix.
3) Only create a new PR bucket when it’s truly a new final feature/fix.
4) In the rewrite branch:
   - if PR slice not yet closed → incorporate into that PR slice
   - if PR slice already closed → add a new PR slice on top (or reopen only with explicit decision + new boundary tag)

## Resume prompt (copy/paste)

Use this exact prompt to resume work without losing process invariants:

“Continue the `leeroy-wip` rewrite on `slopus/tmp/rewrite-clean-stack`.
Work on the current PR slice (see `docs/commit-audits/happy/leeroy-wip.rewrite-status.tsv` for which PR is `in_progress`).
For the next unprocessed original commit(s) in that PR slice:
1) Read its section in `docs/commit-audits/happy/leeroy-wip.commit-manual-review.md` and its Pass2 patch under `/tmp/leeroy-wip-pass2/NNN.patch`.
2) Apply via `happys wt git ...` as `pick` or `split` (or explicit `defer`/`drop-net-noop` only when justified).
3) If splitting and deferring any file/hunk, add rows immediately to `docs/commit-audits/happy/leeroy-wip.rewrite-deferred-fragments.tsv`.
4) Update `docs/commit-audits/happy/leeroy-wip.rewrite-ledger.tsv` for each original commit touched (old→new mapping + notes).
5) Update `docs/commit-audits/happy/leeroy-wip.rewrite-status.tsv` notes with what was completed.
6) Keep the rewrite worktree clean after each commit (`git status` clean).
Stop after a small batch (5–10 commits or ~1–2 hours of work) and report: new SHAs, which old commits were accounted for, any new defers, and any reclassifications.”
