* 🐛 Refuse saves to a branch kept after its merge
A branch kept after its merge stays an ordinary file with status
"merged", so every save passed the edition check and appended ops to
an op log that no command integrates any more. Refuse such saves with
a :branch-merged validation error instead of stranding them. An
archived branch still takes saves: restoring it brings them back.
AI-assisted-by: claude-opus-5-5
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
* ✨ Tell merged and archived branches apart
The workspace treated "merged" and "archived" as one state: an
archived branch read "Merged branch" and lost every action, and a
merged row offered Restore, which the backend always refused.
Each status now has its own presentation. A kept merged branch keeps
"Merged branch" and View in main, and opens read-only: the workspace
permissions drop :can-edit while it is the open file, the way a
viewer gets a read-only workspace. An archived branch says so in the
banner and offers Compare and Restore. The header notes each status,
the switcher lists merged and archived branches in two collapsible
groups, the all-branches dialog gets a Merged tab, and the branch info
dialog offers Restore and Compare for an archived branch.
AI-assisted-by: claude-opus-5-5
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
* ✨ Refuse saves to an archived branch
An archived branch is now read-only, like a merged one: the user
restores it, or turns it into an ordinary file, to keep editing.
persist-branch-file! refuses its saves with a :branch-archived
validation error, distinct from :branch-merged so the client can say
which way out applies. A restored branch takes saves again, and so
does an archived branch turned into an ordinary file.
AI-assisted-by: claude-opus-5-5
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
* ✨ Open archived branches read-only with their ways out
An archived branch now opens read-only, like a merged one. Its banner,
its branch info dialog and its row in the all-branches dialog offer
the two ways back to editing, Restore and Turn into an ordinary file,
next to Compare. The header and switcher note reads "Archived, read
only".
A save the server refuses because the branch is merged or archived
now shows a warning that names the way out, instead of the generic
autosave error with a report link.
AI-assisted-by: claude-opus-5-5
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
---------
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
Files that use a shared library read its main, never a branch, so a
branch of a library is not isolated in the sense the create dialog
promised. On a shared library the create dialog now says that files
using the library can adopt changes from main only, the chip of a
library branch says the same, and the note beside main reads
"Default branch (read by library consumers)". Other files keep their
copy.
get-file-branch-info returns source-is-shared so a branch knows its
main is a library.
AI-assisted-by: claude-opus-5-5
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
* ✨ Move the branch switcher to the workspace header
* ✨ Add branch DS components and the all-branches dialog
* 💄 Polish the branch switcher and its menu entry
* ✨ Keep the dashboard to switching branches
* 💄 Polish the branch and pull request review UI
* ♻️ Move the branching UI onto the design system
* 🐛 Address the review of the header branch switcher
The bottom banner turned the nil counts that get-file-branch-info sends
for a branch it cannot compare into zeros, so it said "Up to date with
main". It now says "Couldn't compare this branch with main" in the
warning colour, as the header row already did.
During a review the review banner replaces the branch banner, which was
the only component loading the branch context. The header row now loads
it too, so a review link opened fresh shows the branch under review
instead of "Main".
On a branch, "New branch" in the all-branches dialog is disabled with a
tooltip saying branches are created from main: the server refuses to
branch a branch.
With "Try interactions" gone, the create-review note says reviewers
open the live branch and View mode plays it, and the unused
open-pull-request-viewer event goes.
The pull request specs follow the new banners, and three tests cover
the fixes above.
AI-assisted-by: claude-opus-5-5
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
---------
Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
Co-authored-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
This commit carries the design-branching preview by Juan de la Cruz:
elhombretecla/penpot:branching at 0ac265a3f5, which holds 45 commits
and 3 develop merges and was last synced with develop on 2026-09-16.
The branch is squashed together with a merge of origin/develop at
7c039231f7, so the tree is the merged result.
The merge resolved conflicts in six files:
- backend/src/app/migrations.clj: develop's 0155 and 0156 steps run
first, then the branching steps; the names differ.
- backend/src/app/rpc/commands/viewer.clj: both requires stay.
- common/src/app/common/flags.cljc: both flags stay.
- frontend/src/app/main/ui/dashboard/file_menu.cljs: "Create branch"
becomes a menu-item* with the same id, guard and handler.
- frontend/src/app/main/ui/dashboard/grid.cljs: the portal goes with
develop's menu rewrite; the branches popover stays in the trigger.
- frontend/translations/en.po: both sides' entries stay, with
develop's source references.
Co-authored-by: Juan de la Cruz <delacruzgarciajuan@gmail.com>
AI-assisted-by: mixed models