Skip to content

Add merge-to-master / cut-release actions to Branches & Releases - #92

Merged
stolau merged 1 commit into
mainfrom
branch-merge-release-cut-viewer
Jul 28, 2026
Merged

Add merge-to-master / cut-release actions to Branches & Releases#92
stolau merged 1 commit into
mainfrom
branch-merge-release-cut-viewer

Conversation

@stolau

@stolau stolau commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Fixes #78.

Summary

  • The backend endpoints (POST /api/branches/<id>/merge, POST /api/releases) already existed and were already fully tested/documented — an earlier PR deliberately scoped viewer wiring out ("those stay curl/CI-only for now"). This PR wires them in: a "Merge to master" button per branch row, and an inline "Cut release" text-input + button in the Releases section.
  • No confirm dialogs — matches every other write action already in this app (bulk approve, delete category, delete mask all fire immediately, error banner only on failure). Confirmed as the right call via an explicit product-judgment question before designing.
  • Race-safety, not cosmetic: all branch rows' "Merge to master" buttons disable together (mergingBranch !== null, not per-row) while any merge is in flight. The Branches section lists several branches side by side — unlike every prior write action in this app, which only ever has one button in its whole view — so a shared result-state slot needs a genuine one-at-a-time invariant to stay race-free.

Process

  • Design went through two rounds of architect SOLID review: first CONCERNS (caught the exact per-row-disable race described above, plus a missing clear-state-before-each-attempt convention), then SOUND after revision.
  • Build went through propose-review: proposer → plan-reviewer (one REVISE round, forcing an explicit fresh snapshot name in the e2e merge test — reusing an existing name would've silently overwritten another test's already-established master baseline via the suite's permanently-flipped variant state, and made the test's pass/fail assertion non-vacuous only by accident) → implementer + test-author → code-reviewer, with independent APPROVE verdicts at every gate.

Test plan

  • npm test -w viewer — 61/61 passed, including a concurrency test proving a second, unclicked branch's button also disables while another branch's merge is in flight (would fail against a buggy per-row-only disable)
  • npm run lint -w viewer — clean
  • npm run lint -w examples/demo-app — clean
  • npm run test:e2e -w examples/demo-app — 19/19 passed (2 new): the merge test uses a genuinely fresh (name, viewport) key with no prior master baseline, so its final assertion (a brand-new unscoped run's first-time processing status) is only reachable if the merge actually copied bytes to master — confirmed non-vacuous by reading render.py's process_pending/scoped_baseline_read_path and by a before/after check (both new tests fail without the fix, pass with it)
  • backend/.venv/bin/pytest backend/tests -q — 145 passed, zero backend files touched (no backend changes in this PR)
  • viewer/CODEMAP.md, examples/demo-app/CODEMAP.md updated

🤖 Generated with Claude Code

https://claude.ai/code/session_01NrQeh9CXrigN1cvpJuyzy4

Fixes #78. The backend endpoints (POST /api/branches/<id>/merge,
POST /api/releases) already existed and were fully tested -- an
earlier PR deliberately scoped viewer wiring out ("those stay
curl/CI-only for now"). This wires them in: a "Merge to master"
button per branch row, and an inline "Cut release" input+button in
the Releases section. No confirm dialogs, matching every other write
action already in this app (bulk approve, delete category, delete
mask all fire immediately with an error banner on failure).

All branch rows' merge buttons disable together while any merge is
in flight (mergingBranch !== null, not per-row) -- load-bearing, not
cosmetic: the app has only ever had one action button per view before
this, so a shared result-state slot needs a genuine one-at-a-time
invariant to stay race-free with several branches listed side by side.

Design went through two rounds of architect SOLID review (first
CONCERNS -- caught this exact race plus a missing clear-state-first
convention -- then SOUND after revision), and the build went through
propose-review (proposer -> plan-reviewer, one REVISE round to force
an explicit fresh snapshot name in the e2e merge test rather than an
ambiguous one -> implementer + test-author -> code-reviewer), with
independent APPROVE verdicts at each gate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NrQeh9CXrigN1cvpJuyzy4
@stolau
stolau merged commit f97b99b into main Jul 28, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add merge-to-master / cut-release actions to the viewer's Branches & Releases view

1 participant