feat(tui): dock approval gate + two-column diff viewer

Replace the floating approval modal (which blanked the whole UI) with an
opencode-style band that takes the input bar's slot while a gate is
pending: tool/tier/risk header above a side-by-side old|new diff, with
the session output and event stream still visible above it. The band
height adapts to the diff length.

Add a unified-diff parser that aligns removals/additions into split rows
(blank left cell for a create, blank right for a delete) and a
two-column renderer shared by the band preview and the ^x fullscreen
view. Wire plain a/r to approve/reject to match the advertised keys.
This commit is contained in:
2026-06-03 00:17:08 +04:00
parent 6956102cf7
commit 03ccac76c7
6 changed files with 363 additions and 80 deletions
+9 -5
View File
@@ -22,7 +22,14 @@ func (m Model) View() string {
return m.theme.Screen.Render("correx — terminal too small")
}
mainH := m.height - statusH - footerH - inputH
bottom := m.renderInput()
bottomH := inputH
if m.displayState() == StateApproval {
bottomH = m.approvalBandHeight()
bottom = m.renderApprovalBand(bottomH)
}
mainH := m.height - statusH - footerH - bottomH
if mainH < 3 {
mainH = 3
}
@@ -30,16 +37,13 @@ func (m Model) View() string {
base := lipgloss.JoinVertical(lipgloss.Left,
m.renderStatus(),
m.renderMain(mainH),
m.renderInput(),
bottom,
m.renderFooter(),
)
if m.overlay != OverlayNone {
return m.renderOverlay(base)
}
if m.displayState() == StateApproval {
return m.renderApproval(base)
}
return base
}