07efb856
Correct the merge-detection section of the revision-refs design
a73x 2026-08-09 16:47
Commit message
docs/superpowers/specs/2026-08-09-patch-revision-refs-design.md
| Old | New | ||
|---|---|---|---|
| @@ -131,12 +131,32 @@ Four things depend on `PatchState.branch` today and each needs a replacement. | |||
| 131 | |---|---| | 131 | |---|---| |
| 132 | | `resolve_head` looks up `refs/heads/<branch>` (`state.rs:433-446`) | Latest `r/<n>` | | 132 | | `resolve_head` looks up `refs/heads/<branch>` (`state.rs:433-446`) | Latest `r/<n>` | |
| 133 | | Staleness, ahead/behind against base tip (`state.rs:448-456`) | Unchanged; anchored to latest `r/<n>` | | 133 | | Staleness, ahead/behind against base tip (`state.rs:448-456`) | Unchanged; anchored to latest `r/<n>` | |
| 134 | | Merged detection by reachability from base (`state.rs:460`) | Unchanged; anchored to latest `r/<n>` | | 134 | | Merged detection (`check_auto_merge`, `state.rs:464-486`) | See below — not unchanged | |
| 135 | | `patch checkout` creates a local branch (`patch.rs:663-668`) | Unchanged; branches from `r/<n>` | | 135 | | `patch checkout` creates a local branch (`patch.rs:663-668`) | Unchanged; branches from `r/<n>` | |
| 136 | 136 | ||
| 137 | `resolve_head` already accepts an OID before falling back to a name lookup | 137 | `resolve_head` already accepts an OID before falling back to a name lookup |
| 138 | (`state.rs:436`), so the OID path is partly built. | 138 | (`state.rs:436`), so the OID path is partly built. |
| 139 | 139 | ||
| 140 | ### Merge detection needs explicit rework | ||
| 141 | |||
| 142 | `check_auto_merge` reads `self.base_commit` to decide whether the base branch has | ||
| 143 | moved (`state.rs:475-479`), and treats `None` as "not moved" via | ||
| 144 | `unwrap_or(false)`. Dropping `base_commit` as proposed above would therefore | ||
| 145 | silently disable merge detection for every patch — `base_moved` would always be | ||
| 146 | false and no patch would ever reach `Merged`. This must be rewritten to read the | ||
| 147 | base of the *latest* revision, not deleted and left to default. | ||
| 148 | |||
| 149 | It also calls `resolve_head`, so today it silently no-ops when | ||
| 150 | `refs/heads/<branch>` is absent — `resolve_head` errors, the `let Ok(..) else` | ||
| 151 | returns, and the patch stays `Open` with no diagnostic. This was confirmed | ||
| 152 | behaviourally while writing server tests: merge detection requires the source | ||
| 153 | branch to have been pushed to the server, not merely the base branch. Anchoring | ||
| 154 | to `r/<n>` removes that requirement, since the revision ref is pushed by `sync` | ||
| 155 | whether or not any branch was. | ||
| 156 | |||
| 157 | Both are reasons the "Merged detection" row is not the no-op it first appears to | ||
| 158 | be, and it should be treated as its own unit of work with its own tests. | ||
| 159 | |||
| 140 | Revision recording is the one behaviour that is genuinely lost. Revisions are | 160 | Revision recording is the one behaviour that is genuinely lost. Revisions are |
| 141 | currently inferred while applying events: an observed commit not already in the | 161 | currently inferred while applying events: an observed commit not already in the |
| 142 | revision list becomes a new revision (`state.rs:578-581`). With no branch to | 162 | revision list becomes a new revision (`state.rs:578-581`). With no branch to |