Tracker: logging and normal user notifications #170

Closed
opened 2026-04-12 17:22:06 +00:00 by barrettruth · 2 comments
barrettruth commented 2026-04-12 17:22:06 +00:00

Tracker: logging and normal user notifications

Problem

Forge still needs follow-up work around picker failure details, async error preservation, and user-facing notification noise. This issue started as the exploratory root note; the concrete remaining work now lives in linked child issues.

Desired behavior

  • successful normal flows should usually be silent
  • long-running or side-effecting actions can emit a small start/success/failure trail
  • warnings and errors should stay user-facing
  • detailed command/request tracing should live behind debug logging or file logging
  • request failures should preserve real stderr/stdout/decode errors when available

Tracked issues

Current state

  • runtime notifications are already mostly centralized in forge.logger
  • the current logger contract is:
    • vim.g.forge.debug = false: no debug output
    • vim.g.forge.debug = true: debug logs go through vim.notify
    • vim.g.forge.debug = \"/tmp/forge.log\": all levels append to a file; info/warn/error still notify

Notes

  • the older async error-handling umbrella is now split across #431, #433, and #434
  • existing-PR lookup failures during create_pr are already handled and do not need a separate child issue
# Tracker: logging and normal user notifications ## Problem Forge still needs follow-up work around picker failure details, async error preservation, and user-facing notification noise. This issue started as the exploratory root note; the concrete remaining work now lives in linked child issues. ## Desired behavior - successful normal flows should usually be silent - long-running or side-effecting actions can emit a small start/success/failure trail - warnings and errors should stay user-facing - detailed command/request tracing should live behind debug logging or file logging - request failures should preserve real stderr/stdout/decode errors when available ## Tracked issues - [x] #431 - [x] #432 - [x] #433 - [x] #434 - [x] #435 - [x] #436 - [x] #437 ## Current state - runtime notifications are already mostly centralized in `forge.logger` - the current logger contract is: - `vim.g.forge.debug = false`: no debug output - `vim.g.forge.debug = true`: debug logs go through `vim.notify` - `vim.g.forge.debug = \"/tmp/forge.log\"`: all levels append to a file; info/warn/error still notify ## Notes - the older async error-handling umbrella is now split across #431, #433, and #434 - existing-PR lookup failures during `create_pr` are already handled and do not need a separate child issue
barrettruth commented 2026-04-21 02:38:32 +00:00

also totally not figured out at all, debug vs regular level logging, etc.

also totally not figured out at all, debug vs regular level logging, etc.
barrettruth commented 2026-04-21 03:53:11 +00:00

A focused note from exploring whether Forge can surface logging/status while an fzf-lua picker stays in the foreground:

  • default vim.notify() does not have a special picker overlay; per :help vim.notify, the stock implementation writes to :messages
  • that means a normal notify/message can sometimes appear in the bottom message area while fzf-lua is open, but it is not a reliable UX surface for picker-local status because it is easy to miss and not attached to the picker itself
  • Forge currently centralizes user-facing runtime logging in forge.logger, which routes info/warn/error through vim.notify and can additionally append all levels to a file when vim.g.forge.debug is a string
  • upstream fzf-lua is in roughly the same boat: its own action feedback uses nvim_echo, not a special in-picker notification layer

What fzf-lua does give us is a stronger picker-state surface than Forge is using today:

  • Forge already uses fzf_exec, streamed/function producers, reload actions, tracked rows, placeholder rows, and dynamic headers (transform-header on focus)
  • so short picker-scoped status is feasible in the fzf backend, e.g. transient inline states like rerunning…, rerun started, or a real failure message derived from stderr
  • but this is better thought of as inline picker status, not “display general Forge logs alongside the picker”

Important architecture detail from the current picker flows:

  • many mutation actions do not actually keep the picker open through completion today
  • PR approve/merge/close/reopen/draft-toggle, issue close/reopen, CI cancel/rerun, and release delete generally close the picker and reopen the list on async success/failure callbacks
  • so the “foreground picker while success/failure arrives” problem only partly exists in the current implementation

This leaves a few practical conclusions for #170:

  1. Normal success should usually stay silent.
  2. Warnings/errors should remain user-facing and should preserve real stderr/stdout/decode details.
  3. If we want feedback inside an open picker, the best fit is a session-owned inline status row/header plus picker reload, not vim.notify.
  4. If we want actual logs/tracing at the same time, that probably wants a separate surface: a reusable split/buffer similar to forge.log, or a polished version of the existing file sink (vim.g.forge.debug = "/tmp/forge.log").

So my current take is:

  • default vim.notify is visible only in the ordinary message area and is too weak to be the main UX for picker-local outcomes
  • inline picker status looks feasible for fzf-lua
  • full logging should likely live in a separate log/debug surface rather than trying to share the picker UI
A focused note from exploring whether Forge can surface logging/status while an `fzf-lua` picker stays in the foreground: - default `vim.notify()` does **not** have a special picker overlay; per `:help vim.notify`, the stock implementation writes to `:messages` - that means a normal notify/message can sometimes appear in the bottom message area while `fzf-lua` is open, but it is not a reliable UX surface for picker-local status because it is easy to miss and not attached to the picker itself - Forge currently centralizes user-facing runtime logging in `forge.logger`, which routes info/warn/error through `vim.notify` and can additionally append all levels to a file when `vim.g.forge.debug` is a string - upstream `fzf-lua` is in roughly the same boat: its own action feedback uses `nvim_echo`, not a special in-picker notification layer What `fzf-lua` *does* give us is a stronger picker-state surface than Forge is using today: - Forge already uses `fzf_exec`, streamed/function producers, reload actions, tracked rows, placeholder rows, and dynamic headers (`transform-header` on focus) - so short picker-scoped status is feasible in the fzf backend, e.g. transient inline states like `rerunning…`, `rerun started`, or a real failure message derived from stderr - but this is better thought of as **inline picker status**, not “display general Forge logs alongside the picker” Important architecture detail from the current picker flows: - many mutation actions do not actually keep the picker open through completion today - PR approve/merge/close/reopen/draft-toggle, issue close/reopen, CI cancel/rerun, and release delete generally close the picker and reopen the list on async success/failure callbacks - so the “foreground picker while success/failure arrives” problem only partly exists in the current implementation This leaves a few practical conclusions for #170: 1. Normal success should usually stay silent. 2. Warnings/errors should remain user-facing and should preserve real stderr/stdout/decode details. 3. If we want feedback *inside* an open picker, the best fit is a session-owned inline status row/header plus picker reload, not `vim.notify`. 4. If we want actual logs/tracing at the same time, that probably wants a separate surface: a reusable split/buffer similar to `forge.log`, or a polished version of the existing file sink (`vim.g.forge.debug = "/tmp/forge.log"`). So my current take is: - default `vim.notify` is visible only in the ordinary message area and is too weak to be the main UX for picker-local outcomes - inline picker status looks feasible for `fzf-lua` - full logging should likely live in a separate log/debug surface rather than trying to share the picker UI
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
barrettruth/forge.nvim#170
No description provided.